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 23, 2025
1 parent ba81cd8 commit 2da290c
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,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 @@ -24,9 +24,18 @@ import {
jest.mock('@/services/helpers/generateName');
(generateWorkspaceName as jest.Mock).mockImplementation(name => name + '1234');

const mockFetchRemoteData = jest.fn();
jest.mock('@/services/backend-client/dataResolverApi', () => {
return {
getDataResolver: async (href: string) => {
return mockFetchRemoteData(href);
},
};
});

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 @@ -42,14 +51,14 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
}),
};

const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, false);

expect(newDevfile.attributes).toEqual({
[DEVWORKSPACE_METADATA_ANNOTATION]: factorySource,
});
});

test('update the attribute with annotation', () => {
test('update the attribute with annotation', async () => {
const customAnnotation = {
'custom-annotation': 'value',
};
Expand All @@ -73,7 +82,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, false);

expect(newDevfile.attributes?.[DEVWORKSPACE_METADATA_ANNOTATION]).toEqual(
expect.objectContaining(customAnnotation),
Expand All @@ -83,7 +92,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 All @@ -105,15 +114,15 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, false);

expect(newDevfile.attributes?.[DEVWORKSPACE_METADATA_ANNOTATION]).not.toContain(
badMetadataAnnotation,
);
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 All @@ -137,7 +146,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, false);

expect(newDevfile.attributes?.[DEVWORKSPACE_METADATA_ANNOTATION]).not.toContain(
expect.objectContaining(badDevworkspaceDevfileSource),
Expand All @@ -147,7 +156,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 @@ -156,12 +165,12 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, false);

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 @@ -170,12 +179,12 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, true);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, true);

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 @@ -184,12 +193,12 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, false);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, false);

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 @@ -198,7 +207,7 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

const newDevfile = prepareDevfile(devfile, factoryId, undefined, true);
const newDevfile = await prepareDevfile(devfile, factoryId, undefined, true);

expect(newDevfile.metadata.name).toEqual('wksp-1234');
});
Expand All @@ -213,18 +222,144 @@ describe('FactoryLoaderContainer/prepareDevfile', () => {
},
} as devfileApi.Devfile;

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

expect(newDevfile.metadata.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toBeUndefined();
expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toBeUndefined();
});

test('non-default storage type', () => {
const newDevfile = prepareDevfile(devfile, factoryId, 'ephemeral', false);
test('non-default storage type', async () => {
const newDevfile = await prepareDevfile(devfile, factoryId, 'ephemeral', false);

expect(mockFetchRemoteData).not.toHaveBeenCalled();
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 () => {
const devfile = {
schemaVersion: '2.2.0',
metadata: {
name: 'wksp-test',
},
parent: {
id: 'nodejs',
registryUrl: 'https://registry.devfile.io/',
},
} as devfileApi.Devfile;

mockFetchRemoteData.mockResolvedValueOnce(
dump({
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
attributes: {
'controller.devfile.io/storage-type': 'ephemeral',
},
}),
);

const newDevfile = await prepareDevfile(devfile, factoryId, 'ephemeral', false);

expect(mockFetchRemoteData).toHaveBeenCalledWith(
'https://registry.devfile.io//devfiles/nodejs',
);
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;

mockFetchRemoteData.mockResolvedValueOnce(
dump({
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
}),
);

const newDevfile = await prepareDevfile(devfile, factoryId, 'ephemeral', false);

expect(mockFetchRemoteData).toHaveBeenCalledWith(
'https://registry.devfile.io//devfiles/nodejs',
);
expect(newDevfile.attributes?.[DEVWORKSPACE_STORAGE_TYPE_ATTR]).toEqual('ephemeral');
});
});
describe('with uri', () => {
it('with 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;

mockFetchRemoteData.mockResolvedValueOnce(
dump({
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
attributes: {
'controller.devfile.io/storage-type': 'ephemeral',
},
}),
);

const newDevfile = await prepareDevfile(devfile, factoryId, 'ephemeral', false);

expect(mockFetchRemoteData).toHaveBeenCalledWith(
'https://raw.githubusercontent.com/test/devfile.yaml',
);
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;

mockFetchRemoteData.mockResolvedValueOnce(
dump({
schemaVersion: '2.2.2',
metadata: {
generateName: 'nodejs',
},
}),
);

const newDevfile = await prepareDevfile(devfile, factoryId, 'ephemeral', false);

expect(mockFetchRemoteData).toHaveBeenCalledWith(
'https://raw.githubusercontent.com/test/devfile.yaml',
);
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,9 @@ 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 updatedDevfile = await prepareDevfile(devfile, factoryId, storageType, appendSuffix);

this.setState({
devfile: updatedDevfile,
Expand Down Expand Up @@ -265,7 +267,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 +298,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 +319,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 +467,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
Loading

0 comments on commit 2da290c

Please sign in to comment.