Skip to content
This repository has been archived by the owner on Dec 6, 2024. It is now read-only.

Commit

Permalink
feat: display Configuration Name and Instance Type on Workspace detai…
Browse files Browse the repository at this point in the history
…ls card (#669)

feat: display Configuration Name and Instance Type on Workspace details card and when selecting configuration to create a new workspace
  • Loading branch information
maghirardelli authored Aug 24, 2021
1 parent 2c5bb1a commit f0fa819
Show file tree
Hide file tree
Showing 10 changed files with 282 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const ScEnvironment = types
rev: types.maybe(types.number),
status: '',
description: '',
envTypeConfigId: '',
name: '',
projectId: '',
envTypeId: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { observer, inject } from 'mobx-react';
import { withRouter } from 'react-router-dom';
import { Header, Label, Popup, Icon, Divider, Message, Table, Grid, Segment } from 'semantic-ui-react';
import TimeAgo from 'react-timeago';
import { niceNumber } from '@aws-ee/base-ui/dist/helpers/utils';
import { niceNumber, swallowError } from '@aws-ee/base-ui/dist/helpers/utils';
import { isStoreLoading, isStoreNotEmpty, isStoreError } from '@aws-ee/base-ui/dist/models/BaseStore';
import ErrorBox from '@aws-ee/base-ui/dist/parts/helpers/ErrorBox';
import ProgressPlaceHolder from '@aws-ee/base-ui/dist/parts/helpers/BasicProgressPlaceholder';

import By from '../helpers/By';
import ScEnvironmentButtons from './parts/ScEnvironmentButtons';
Expand All @@ -31,7 +34,40 @@ class ScEnvironmentCard extends React.Component {
return envType;
}

getEnvTypeConfigsStore() {
const configsStore = this.envTypesStore.getEnvTypeConfigsStore(this.environment.envTypeId);
return configsStore;
}

getConfiguration(envTypeConfigId) {
const configsStore = this.getEnvTypeConfigsStore();
const config = configsStore.getEnvTypeConfig(envTypeConfigId);
return config;
}

componentDidMount() {
const configsStore = this.getEnvTypeConfigsStore();
swallowError(configsStore.load());
}

render() {
const configsStore = this.getEnvTypeConfigsStore();
let content = null;

if (isStoreError(configsStore)) {
content = <ErrorBox error={configsStore.error} className="p0" />;
} else if (isStoreLoading(configsStore)) {
content = <ProgressPlaceHolder segmentCount={3} />;
} else if (isStoreNotEmpty(configsStore)) {
content = this.renderMain();
} else {
content = null;
}

return content;
}

renderMain() {
const env = this.environment;
const state = env.state;

Expand Down Expand Up @@ -64,6 +100,10 @@ class ScEnvironmentCard extends React.Component {
const studyCount = _.size(_.get(env, 'studyIds', []));
const envType = this.envType || {};

const config = this.getConfiguration(this.environment.envTypeConfigId);
const configName = config.name;
const instanceType = config.instanceType;

const renderRow = (key, value) => (
<Table.Row>
<Table.Cell width={5}>{key}</Table.Cell>
Expand All @@ -74,12 +114,14 @@ class ScEnvironmentCard extends React.Component {
);

return (
<Table definition>
<Table data-testid="environment-card-details-table" definition>
<Table.Body>
{renderRow('Owner', <By uid={env.createdBy} skipPrefix />)}
{renderRow('Studies', studyCount === 0 ? 'No studies linked to this workspace' : niceNumber(studyCount))}
{renderRow('Project', _.isEmpty(env.projectId) ? 'N/A' : env.projectId)}
{renderRow('Workspace Type', envType.name)}
{renderRow('Configuration Name', configName)}
{renderRow('Instance Type', instanceType)}
</Table.Body>
</Table>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import React from 'react';
import { shallow } from 'enzyme';

// Mock buttons to avoid error
jest.mock('../parts/ScEnvironmentButtons', () => ({
__ScEnvironmentButtons: true,
}));
// eslint-disable-next-line import/first
import {} from '../parts/ScEnvironmentButtons';

// const ScEnvironmentCard = require('../ScEnvironmentCard');
// eslint-disable-next-line import/first
import ScEnvironmentCard from '../ScEnvironmentCard';

jest.mock('@aws-ee/base-ui/dist/helpers/notification');
const displayErrorMock = require('@aws-ee/base-ui/dist/helpers/notification');

const scEnvironment = {
id: 'id',
rev: 2,
status: 'active',
description: 'sample description',
envTypeConfigId: 'env type config id',
name: 'name',
projectId: 'project id',
envTypeId: 'env type id',
createdAt: '01-01-1900',
createdBy: 'anonymous',
updatedAt: '01-02-1900',
updatedBy: 'anonymous',
error: 'error',
connections: [],
hasConnections: false,
studyIds: [],
cidr: [],
outputs: [],
};

const envTypesStore = {
getEnvTypeConfigsStore: jest.fn(() => envTypesStore),
load: jest.fn(),
getEnvTypeConfig: jest.fn(),
};

describe('ScEnvironmentCard', () => {
let component = null;
let wrapper = null;
beforeEach(() => {
// render component
wrapper = shallow(
<ScEnvironmentCard.WrappedComponent scEnvironment={scEnvironment} envTypesStore={envTypesStore} />,
);

// get instance of component
component = wrapper.instance();

// mock error function because it doesn't function properly in enzyme
displayErrorMock.displayError = jest.fn(x => x);
});

it('should get env type configs store', async () => {
// BUILD, OPERATE
component.getEnvTypeConfigsStore();

// CHECK
expect(envTypesStore.getEnvTypeConfigsStore).toHaveBeenCalledWith(scEnvironment.envTypeId);
});

it('should get configuration', async () => {
// BUILD
const spyOnConfigsStore = jest.spyOn(component, 'getEnvTypeConfigsStore');

// OPERATE
component.getConfiguration(scEnvironment.envTypeConfigId);

// CHECK
expect(spyOnConfigsStore).toHaveBeenCalled();
expect(envTypesStore.getEnvTypeConfig).toHaveBeenCalledWith(scEnvironment.envTypeConfigId);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class SelectConfigurationCards extends React.Component {
</div>
<Divider />
{this.renderEstimatedCostInfo(config)}
{this.renderInstanceType(config)}
</Card.Description>
</Card.Content>
</Card>
Expand Down Expand Up @@ -116,6 +117,17 @@ class SelectConfigurationCards extends React.Component {
return content;
}

renderInstanceType(config) {
const content = (
<div className="flex p1">
<div className="bold flex-auto">Instance Type</div>
<div className="pr1">{config.instanceType}</div>
</div>
);

return content;
}

renderTableInfo(config) {
// estimatedCostInfo
const priceTitle = item => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* permissions and limitations under the License.
*/

import { toJS } from 'mobx';
import { types, applySnapshot, getEnv } from 'mobx-state-tree';

const KeyValuePair = types.model('KeyValuePair', {
Expand Down Expand Up @@ -58,6 +59,17 @@ const EnvTypeConfig = types
const showdown = getEnv(self).showdown;
return showdown.convert(self.estimatedCostInfo);
},
get instanceType() {
const params = self.params;
const paramsAsJson = toJS(params);
const instanceTypeIndex = paramsAsJson.findIndex(({ key }) => {
return key === 'InstanceType' || key === 'MasterInstanceType';
});
if (instanceTypeIndex < 0) {
return 'Not available';
}
return paramsAsJson[instanceTypeIndex].value;
},
}));

export default EnvTypeConfig;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
// require('../EnvTypeConfig');
import EnvTypeConfig from '../EnvTypeConfig';

describe('EnvTypeConfig', () => {
it('should get the instance type', async () => {
// BUILD
const config = {
id: 'envtypeconfigid',
name: 'Name',
desc: 'some desc',
estimatedCostInfo: 'money',
params: [{ key: 'InstanceType', value: 't3.large' }],
};
const envTypeConfig = EnvTypeConfig.create(config); // Initialize the whole object

// OPERATE
const instanceType = envTypeConfig.instanceType;

// CHECK
expect(instanceType).not.toBe('Not available');
expect(instanceType).toBe('t3.large');
});

it('should get master instance type from config params for EMR', async () => {
// BUILD
const config = {
id: 'envtypeconfigid',
name: 'Name',
desc: 'some desc',
estimatedCostInfo: 'money',
params: [{ key: 'MasterInstanceType', value: 't3.large' }],
};
const envTypeConfig = EnvTypeConfig.create(config); // Initialize the whole object

// OPERATE
const instanceType = envTypeConfig.instanceType;

// CHECK
expect(instanceType).not.toBe('Not available');
expect(instanceType).toBe('t3.large');
});

it('should display something graceful when no InstanceType param in config params', async () => {
// BUILD
const config = {
id: 'envtypeconfigid',
name: 'Name',
desc: 'some desc',
estimatedCostInfo: 'money',
params: [{ key: 'name', value: 'name' }],
};
const envTypeConfig = EnvTypeConfig.create(config); // Initialize the whole object

// OPERATE
const instanceType = envTypeConfig.instanceType;

// CHECK
expect(instanceType).toBe('Not available');
});
});
5 changes: 5 additions & 0 deletions main/end-to-end-tests/cypress.github.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
"workspaceTypeName": "EC2 Linux-v1",
"configuration": "ec2-linux-e2e",
"projectId": "e2eTestProject"
},
"emr": {
"workspaceTypeName": "EMR-v5",
"configuration": "emr-e2e",
"projectId": "e2eTestProject"
}
},
"studies": {
Expand Down
5 changes: 5 additions & 0 deletions main/end-to-end-tests/cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
"workspaceTypeName": "<NAME OF EC2 WORKSPACE TYPE>",
"configuration": "<EC2 WORKSPACE CONFIGURATION>",
"projectId": "<PROJECT TO LAUNCH EC2 WORKSPACE IN>"
},
"emr": {
"workspaceTypeName": "<NAME OF EMR WORKSPACE TYPE>",
"configuration": "<EMR WORKSPACE CONFIGURATION>",
"projectId": "<PROJECT TO LAUNCH EMR WORKSPACE IN>"
}
},
"studies": {
Expand Down
5 changes: 5 additions & 0 deletions main/end-to-end-tests/cypress.local.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
"workspaceTypeName": "ec2-linux-instances",
"configuration": "ec2-instance",
"projectId": "GalCrossAccountProject"
},
"emr": {
"workspaceTypeName": "emr-instances",
"configuration": "emr-instance",
"projectId": "GalCrossAccountProject"
}
},
"studies": {
Expand Down
Loading

0 comments on commit f0fa819

Please sign in to comment.