if orig_value:
self._ceph_cmd(['config', 'set', 'mon', config_name, orig_value[0]['value']])
+ def test_filter_config_options(self):
+ config_names = ['osd_scrub_during_recovery', 'osd_scrub_begin_hour', 'osd_scrub_end_hour']
+ data = self._get('/api/cluster_conf/filter?names={}'.format(','.join(config_names)))
+ self.assertStatus(200)
+ self.assertIsInstance(data, list)
+ self.assertEqual(len(data), 3)
+ for conf in data:
+ self._validate_single(conf)
+ self.assertIn(conf['name'], config_names)
+
+ def test_filter_config_options_empty_names(self):
+ self._get('/api/cluster_conf/filter?names=')
+ self.assertStatus(404)
+ self.assertEqual(self._resp.json()['detail'], 'Config options `` not found')
+
+ def test_filter_config_options_unknown_name(self):
+ self._get('/api/cluster_conf/filter?names=abc')
+ self.assertStatus(404)
+ self.assertEqual(self._resp.json()['detail'], 'Config options `abc` not found')
+
+ def test_filter_config_options_contains_unknown_name(self):
+ config_names = ['osd_scrub_during_recovery', 'osd_scrub_begin_hour', 'abc']
+ data = self._get('/api/cluster_conf/filter?names={}'.format(','.join(config_names)))
+ self.assertStatus(200)
+ self.assertIsInstance(data, list)
+ self.assertEqual(len(data), 2)
+ for conf in data:
+ self._validate_single(conf)
+ self.assertIn(conf['name'], config_names)
+
def test_create(self):
config_name = 'debug_ms'
orig_value = self._get_config_by_name(config_name)
self._clear_all_values_for_config_option(config_name)
self._reset_original_values(config_name, orig_value)
+ def test_delete(self):
+ config_name = 'debug_ms'
+ orig_value = self._get_config_by_name(config_name)
+
+ # set a config option
+ expected_result = [{'section': 'mon', 'value': '0/3'}]
+ self._post('/api/cluster_conf', {
+ 'name': config_name,
+ 'value': expected_result
+ })
+ self.assertStatus(201)
+ self._wait_for_expected_get_result(self._get_config_by_name, config_name, expected_result)
+
+ # delete it and check if it's deleted
+ self._delete('/api/cluster_conf/{}?section={}'.format(config_name, 'mon'))
+ self.assertStatus(204)
+ result = self._wait_for_expected_get_result(self._get_config_by_name, config_name, None)
+ self.assertEqual(result, None)
+
+ # reset original value
+ self._clear_all_values_for_config_option(config_name)
+ self._reset_original_values(config_name, orig_value)
+
def test_create_cant_update_at_runtime(self):
config_name = 'public_bind_addr' # not updatable
config_value = [{'section': 'global', 'value': 'true'}]
def get(self, name):
return self._get_config_option(name)
+ @RESTController.Collection('GET', query_params=['name'])
+ def filter(self, names=None):
+ config_options = []
+
+ if names:
+ for name in names.split(','):
+ try:
+ config_options.append(self._get_config_option(name))
+ except cherrypy.HTTPError:
+ pass
+
+ if not config_options:
+ raise cherrypy.HTTPError(404, 'Config options `{}` not found'.format(names))
+
+ return config_options
+
def create(self, name, value):
# Check if config option is updateable at runtime
self._updateable_at_runtime([name])
else:
CephService.send_command('mon', 'config rm', who=section, name=name)
+ def delete(self, name, section):
+ return CephService.send_command('mon', 'config rm', who=section, name=name)
+
def bulk_set(self, options):
self._updateable_at_runtime(options.keys())
import * as _ from 'lodash';
import { ToastModule } from 'ng2-toastr';
import { BsModalRef, ModalModule } from 'ngx-bootstrap/modal';
+import { of as observableOf } from 'rxjs';
import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { ConfigurationService } from '../../../../shared/api/configuration.service';
import { SharedModule } from '../../../../shared/shared.module';
import { OsdRecvSpeedModalComponent } from './osd-recv-speed-modal.component';
describe('OsdRecvSpeedModalComponent', () => {
let component: OsdRecvSpeedModalComponent;
let fixture: ComponentFixture<OsdRecvSpeedModalComponent>;
+ let configurationService: ConfigurationService;
configureTestBed({
imports: [
fixture = TestBed.createComponent(OsdRecvSpeedModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
-
+ configurationService = TestBed.get(ConfigurationService);
configOptions = [
{
name: 'osd_max_backfills',
default: 0
}
];
+ spyOn(configurationService, 'filter').and.returnValue(observableOf(configOptions));
});
it('should create', () => {
expect(component).toBeTruthy();
});
+ describe('ngOnInit', () => {
+ let setPriority;
+ let setValidators;
+
+ beforeEach(() => {
+ setPriority = spyOn(component, 'setPriority').and.callThrough();
+ setValidators = spyOn(component, 'setValidators').and.callThrough();
+ component.ngOnInit();
+ });
+
+ it('should call setValidators', () => {
+ expect(setValidators).toHaveBeenCalled();
+ });
+
+ it('should get and set priority correctly', () => {
+ const defaultPriority = _.find(component.priorities, (p) => {
+ return _.isEqual(p.name, 'default');
+ });
+ expect(setPriority).toHaveBeenCalledWith(defaultPriority);
+ });
+
+ it('should set descriptions correctly', () => {
+ expect(component.priorityAttrs['osd_max_backfills'].desc).toBe('');
+ expect(component.priorityAttrs['osd_recovery_max_active'].desc).toBe('');
+ expect(component.priorityAttrs['osd_recovery_max_single_start'].desc).toBe('');
+ expect(component.priorityAttrs['osd_recovery_sleep'].desc).toBe(
+ 'Time in seconds to sleep before next recovery or backfill op'
+ );
+ });
+ });
+
describe('setPriority', () => {
it('should prepare the form for a custom priority', () => {
const customPriority = {
import { I18n } from '@ngx-translate/i18n-polyfill';
import * as _ from 'lodash';
import { BsModalRef } from 'ngx-bootstrap/modal';
-import { forkJoin as observableForkJoin, of } from 'rxjs';
-import { mergeMap } from 'rxjs/operators';
import { ConfigurationService } from '../../../../shared/api/configuration.service';
import { OsdService } from '../../../../shared/api/osd.service';
}
ngOnInit() {
- const observables = [];
- Object.keys(this.priorityAttrs).forEach((configOptionName) => {
- observables.push(this.configService.get(configOptionName));
- });
-
- observableForkJoin(observables)
- .pipe(
- mergeMap((configOptions) => {
- return of(this.getCurrentValues(configOptions));
- })
- )
- .subscribe((resp) => {
- this.detectPriority(resp.values, (priority) => {
- this.setPriority(priority);
- });
- this.setDescription(resp.configOptions);
- this.setValidators(resp.configOptions);
+ this.configService.filter(Object.keys(this.priorityAttrs)).subscribe((data: any) => {
+ const config_option_values = this.getCurrentValues(data);
+ this.detectPriority(config_option_values.values, (priority) => {
+ this.setPriority(priority);
});
+ this.setDescription(config_option_values.configOptions);
+ this.setValidators(config_option_values.configOptions);
+ });
}
detectPriority(configOptionValues: any, callbackFn: Function) {
expect(req.request.method).toBe('POST');
expect(req.request.body).toEqual(configOption);
});
+
+ it('should call bulkCreate', () => {
+ const configOptions = {
+ configOption1: { section: 'section', value: 'value' },
+ configOption2: { section: 'section', value: 'value' }
+ };
+ service.bulkCreate(configOptions).subscribe();
+ const req = httpTesting.expectOne('api/cluster_conf/');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual(configOptions);
+ });
+
+ it('should call filter', () => {
+ const configOptions = ['configOption1', 'configOption2', 'configOption3'];
+ service.filter(configOptions).subscribe();
+ const req = httpTesting.expectOne(
+ 'api/cluster_conf/filter?names=configOption1,configOption2,configOption3'
+ );
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call delete', () => {
+ service.delete('testOption', 'testSection').subscribe();
+ const reg = httpTesting.expectOne('api/cluster_conf/testOption?section=testSection');
+ expect(reg.request.method).toBe('DELETE');
+ });
});
return this.http.get(`api/cluster_conf/${configOption}`);
}
+ filter(configOptionNames: Array<string>) {
+ return this.http.get(`api/cluster_conf/filter?names=${configOptionNames.join(',')}`);
+ }
+
create(configOption: ConfigFormCreateRequestModel) {
return this.http.post('api/cluster_conf/', configOption);
}
+ delete(configOption: string, section: string) {
+ return this.http.delete(`api/cluster_conf/${configOption}?section=${section}`);
+ }
+
bulkCreate(configOptions: Object) {
- return this.http.put('api/cluster_conf', configOptions);
+ return this.http.put('api/cluster_conf/', configOptions);
}
}