Skip to content

Commit

Permalink
feat: add support a devfite which includes a parent with the storage-…
Browse files Browse the repository at this point in the history
…type attribute

Signed-off-by: Oleksii Orel <[email protected]>
  • Loading branch information
olexii4 committed Jan 27, 2025
1 parent 9bedb62 commit 60b7f69
Show file tree
Hide file tree
Showing 14 changed files with 348 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ const devfile = {
},
} as devfileApi.Devfile;

// mute console.error
console.error = jest.fn();

describe('Creating steps, applying a devfile', () => {
let searchParams: URLSearchParams;
let factoryId: string;
Expand Down Expand Up @@ -245,6 +248,7 @@ describe('Creating steps, applying a devfile', () => {
factoryId,
undefined,
false,
undefined,
),
);
await waitFor(() => expect(mockCreateWorkspaceFromDevfile).toHaveBeenCalled());
Expand Down Expand Up @@ -334,6 +338,7 @@ describe('Creating steps, applying a devfile', () => {
factoryId,
undefined,
false,
undefined,
),
);
await waitFor(() => expect(mockCreateWorkspaceFromDevfile).toHaveBeenCalled());
Expand Down Expand Up @@ -410,6 +415,7 @@ describe('Creating steps, applying a devfile', () => {
factoryId,
undefined,
false,
undefined,
),
);
await waitFor(() => expect(mockCreateWorkspaceFromDevfile).toHaveBeenCalled());
Expand Down Expand Up @@ -488,6 +494,7 @@ describe('Creating steps, applying a devfile', () => {
factoryId,
undefined,
false,
undefined,
),
);
await waitFor(() => expect(mockCreateWorkspaceFromDevfile).toHaveBeenCalled());
Expand All @@ -511,7 +518,7 @@ describe('Creating steps, applying a devfile', () => {
await jest.advanceTimersByTimeAsync(MIN_STEP_DURATION_MS);

await waitFor(() =>
expect(prepareDevfile).toHaveBeenCalledWith(devfile, factoryId, undefined, true),
expect(prepareDevfile).toHaveBeenCalledWith(devfile, factoryId, undefined, true, undefined),
);
});

Expand All @@ -534,7 +541,7 @@ describe('Creating steps, applying a devfile', () => {
await jest.advanceTimersByTimeAsync(MIN_STEP_DURATION_MS);

await waitFor(() =>
expect(prepareDevfile).toHaveBeenCalledWith(devfile, factoryId, undefined, true),
expect(prepareDevfile).toHaveBeenCalledWith(devfile, factoryId, undefined, true, undefined),
);
});

Expand All @@ -554,7 +561,13 @@ describe('Creating steps, applying a devfile', () => {
await jest.advanceTimersByTimeAsync(MIN_STEP_DURATION_MS);

await waitFor(() =>
expect(prepareDevfile).toHaveBeenCalledWith(devfile, factoryId, undefined, false),
expect(prepareDevfile).toHaveBeenCalledWith(
devfile,
factoryId,
undefined,
false,
undefined,
),
);
});
});
Expand Down Expand Up @@ -679,7 +692,7 @@ describe('Creating steps, applying a devfile', () => {
expect(mockOnNextStep).not.toHaveBeenCalled();
expect(mockOnError).not.toHaveBeenCalled();

expect(mockCreateWorkspaceFromDevfile).toHaveBeenCalledTimes(1);
await waitFor(() => expect(mockCreateWorkspaceFromDevfile).toHaveBeenCalledTimes(1));
});

test('action callback to continue with default devfile', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jest.mock('@/services/helpers/generateName');

describe('FactoryLoaderContainer/prepareDevfile', () => {
describe('DEVWORKSPACE_METADATA_ANNOTATION attribute', () => {
test('add the attribute with annotation', () => {
test('add the attribute with annotation', async () => {
const devfile = {
schemaVersion: '2.2.0',
metadata: {
Expand All @@ -49,7 +49,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
});
});

test('update the attribute with annotation', () => {
test('update the attribute with annotation', async () => {
const customAnnotation = {
'custom-annotation': 'value',
};
Expand Down Expand Up @@ -83,7 +83,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
);
});

test('update the attribute with annotation - bad DEVWORKSPACE_METADATA_ANNOTATION', () => {
test('update the attribute with annotation - bad DEVWORKSPACE_METADATA_ANNOTATION', async () => {
const factoryId = 'url=https://devfile-location';
const factorySource = {
[DEVWORKSPACE_DEVFILE_SOURCE]: dump({
Expand Down Expand Up @@ -113,7 +113,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
expect(newDevfile.attributes?.[DEVWORKSPACE_METADATA_ANNOTATION]).toEqual(factorySource);
});

test('update the attribute with annotation - bad DEVWORKSPACE_DEVFILE_SOURCE', () => {
test('update the attribute with annotation - bad DEVWORKSPACE_DEVFILE_SOURCE', async () => {
const factoryId = 'url=https://devfile-location';
const factorySource = {
[DEVWORKSPACE_DEVFILE_SOURCE]: dump({
Expand Down Expand Up @@ -147,7 +147,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
});

describe('DevWorkspace name', () => {
it('should not change the name', () => {
it('should not change the name', async () => {
const factoryId = 'url=https://devfile-location';
const devfile = {
schemaVersion: '2.2.0',
Expand All @@ -161,7 +161,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
expect(newDevfile.metadata.name).toEqual('wksp-test');
});

it('should append a suffix to the name', () => {
it('should append a suffix to the name', async () => {
const factoryId = 'url=https://devfile-location';
const devfile = {
schemaVersion: '2.2.0',
Expand All @@ -175,7 +175,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
expect(newDevfile.metadata.name).toEqual('wksp-test1234');
});

it('should generate a new name #1', () => {
it('should generate a new name #1', async () => {
const factoryId = 'url=https://devfile-location';
const devfile = {
schemaVersion: '2.2.0',
Expand All @@ -189,7 +189,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
expect(newDevfile.metadata.name).toEqual('wksp-1234');
});

it('should generate a new name #2', () => {
it('should generate a new name #2', async () => {
const factoryId = 'url=https://devfile-location';
const devfile = {
schemaVersion: '2.2.0',
Expand All @@ -213,7 +213,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

test('default storage type', () => {
test('default storage type', async () => {
const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);

expect(newDevfile.metadata.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toBeUndefined();
Expand All @@ -226,5 +226,112 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
expect(newDevfile.metadata.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toBeUndefined();
expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toEqual('ephemeral');
});

describe('has parent', () => {
describe('with registryUrl', () => {
it('with storage-type attribute', async () => {
// mute console logs
console.warn = jest.fn();
const devfile = {
schemaVersion: '2.2.0',
metadata: {
name: 'wksp-test',
},
parent: {
id: 'nodejs',
registryUrl: 'https://registry.devfile.io/',
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, 'ephemeral', false, {
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
attributes: {
'controller.devfile.io/storage-type': 'ephemeral',
},
} as devfileApi.Devfile);

expect(console.warn).toHaveBeenCalledWith(
'Unable to apply controller.devfile.io/storage-type attribute.',
);
expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toBeUndefined();
});

it('without storage-type attribute', async () => {
const devfile = {
schemaVersion: '2.2.0',
metadata: {
name: 'wksp-test',
},
parent: {
id: 'nodejs',
registryUrl: 'https://registry.devfile.io/',
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, 'ephemeral', false, {
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
} as devfileApi.Devfile);

expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toEqual('ephemeral');
});
});
describe('with uri', () => {
it('with storage-type attribute', async () => {
// mute console logs
console.warn = jest.fn();
const devfile = {
schemaVersion: '2.2.0',
metadata: {
name: 'wksp-test',
},
parent: {
uri: 'https://raw.githubusercontent.com/test/devfile.yaml',
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, 'ephemeral', false, {
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
attributes: {
'controller.devfile.io/storage-type': 'ephemeral',
},
} as devfileApi.Devfile);

expect(console.warn).toHaveBeenCalledWith(
'Unable to apply controller.devfile.io/storage-type attribute.',
);
expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toBeUndefined();
});

it('without storage-type attribute', async () => {
const devfile = {
schemaVersion: '2.2.0',
metadata: {
name: 'wksp-test',
},
parent: {
uri: 'https://raw.githubusercontent.com/test/devfile.yaml',
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, 'ephemeral', false, {
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
} as devfileApi.Devfile);

expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toEqual('ephemeral');
});
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { RootState } from '@/store';
import { selectDefaultDevfile } from '@/store/DevfileRegistries/selectors';
import { selectFactoryResolver } from '@/store/FactoryResolver/selectors';
import { selectDefaultNamespace } from '@/store/InfrastructureNamespaces/selectors';
import { selectPvcStrategy } from '@/store/ServerConfig';
import { workspacesActionCreators } from '@/store/Workspaces';
import { selectDevWorkspaceWarnings } from '@/store/Workspaces/devWorkspaces/selectors';
import { selectAllWorkspaces } from '@/store/Workspaces/selectors';
Expand Down Expand Up @@ -173,10 +174,10 @@ class CreatingStepApplyDevfile extends ProgressStep<Props, State> {
this.prepareAndRun();
}

private updateCurrentDevfile(devfile: devfileApi.Devfile): void {
private async updateCurrentDevfile(devfile: devfileApi.Devfile): Promise<void> {
const { factoryResolver, allWorkspaces, defaultDevfile } = this.props;
const { factoryParams } = this.state;
const { factoryId, policiesCreate, sourceUrl, storageType, remotes } = factoryParams;
const { factoryId, policiesCreate, sourceUrl, remotes } = factoryParams;

// when using the default devfile instead of a user devfile
if (factoryResolver === undefined && isEqual(devfile, defaultDevfile)) {
Expand Down Expand Up @@ -214,8 +215,16 @@ class CreatingStepApplyDevfile extends ProgressStep<Props, State> {
// test the devfile name to decide if we need to append a suffix to is
const nameConflict = allWorkspaces.some(w => devfile.metadata.name === w.name);

const storageType = factoryParams.storageType || this.props.preferredStorageType || undefined;
const appendSuffix = policiesCreate === 'perclick' || nameConflict;
const updatedDevfile = prepareDevfile(devfile, factoryId, storageType, appendSuffix);
const parentDevfile = factoryResolver?.parentDevfile;
const updatedDevfile = prepareDevfile(
devfile,
factoryId,
storageType,
appendSuffix,
parentDevfile,
);

this.setState({
devfile: updatedDevfile,
Expand Down Expand Up @@ -265,7 +274,7 @@ class CreatingStepApplyDevfile extends ProgressStep<Props, State> {
throw new Error('Failed to resolve the default devfile.');
}
const _devfile = cloneDeep(defaultDevfile);
this.updateCurrentDevfile(_devfile);
await this.updateCurrentDevfile(_devfile);
} else {
try {
await this.createWorkspaceFromDevfile(devfile);
Expand Down Expand Up @@ -296,7 +305,7 @@ class CreatingStepApplyDevfile extends ProgressStep<Props, State> {
_devfile.metadata.generateName = metadata.generateName;
}

this.updateCurrentDevfile(_devfile);
await this.updateCurrentDevfile(_devfile);
return false;
}

Expand All @@ -317,7 +326,7 @@ class CreatingStepApplyDevfile extends ProgressStep<Props, State> {
throw new Error('Failed to resolve the devfile.');
}
const _devfile = cloneDeep(resolvedDevfile);
this.updateCurrentDevfile(_devfile);
await this.updateCurrentDevfile(_devfile);
} else {
const { devfile } = this.state;
if (devfile) {
Expand Down Expand Up @@ -465,6 +474,7 @@ const mapStateToProps = (state: RootState) => ({
factoryResolver: selectFactoryResolver(state),
defaultDevfile: selectDefaultDevfile(state),
devWorkspaceWarnings: selectDevWorkspaceWarnings(state),
preferredStorageType: selectPvcStrategy(state),
});

const connector = connect(mapStateToProps, workspacesActionCreators, null, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function prepareDevfile(
factoryId: string,
storageType: che.WorkspaceStorageType | undefined,
appendSuffix: boolean,
parentDevfile?: devfileApi.Devfile | undefined,
): devfileApi.Devfile {
const devfile = cloneDeep(_devfile);
const attributes = DevfileAdapter.getAttributes(devfile);
Expand Down Expand Up @@ -60,8 +61,15 @@ export function prepareDevfile(
devfile.metadata.name = sanitizeName(devfile.metadata.name);

// propagate storage type
if (storageType === 'ephemeral') {
attributes[DEVWORKSPACE_STORAGE_TYPE_ATTR] = 'ephemeral';
if (storageType) {
attributes[DEVWORKSPACE_STORAGE_TYPE_ATTR] = storageType;
}
if (parentDevfile && attributes[DEVWORKSPACE_STORAGE_TYPE_ATTR]) {
const parentDevfileAttributes = DevfileAdapter.getAttributes(parentDevfile);
if (parentDevfileAttributes[DEVWORKSPACE_STORAGE_TYPE_ATTR]) {
delete attributes[DEVWORKSPACE_STORAGE_TYPE_ATTR];
console.warn(`Unable to apply ${DEVWORKSPACE_STORAGE_TYPE_ATTR} attribute.`);
}
}

return devfile;
Expand Down
Loading

0 comments on commit 60b7f69

Please sign in to comment.