import React, { useEffect, useState } from 'react'; import type { IStage, IStageConfigProps } from '@spinnaker/core'; import { AccountService, AppListExtractor, ChecklistInput, StageConfigField, StageConstants } from '@spinnaker/core'; import type { IAccount } from '@spinnaker/core'; type AmazonStageFieldType = 'account' | 'onlyEnabled' | 'regions' | 'selectionStrategy' | 'target' | 'text'; export interface IAmazonStageField { fieldName: string; label: string; type?: AmazonStageFieldType; } const selectionStrategies = [ { label: 'Largest', val: 'LARGEST', description: 'When multiple server groups exist, prefer the server group with the most instances', }, { label: 'Newest', val: 'NEWEST', description: 'When multiple server groups exist, prefer the newest' }, { label: 'Oldest', val: 'OLDEST', description: 'When multiple server groups exist, prefer the oldest' }, { label: 'Fail', val: 'FAIL', description: 'When multiple server groups exist, fail' }, ]; const findImageFields: IAmazonStageField[] = [ { fieldName: 'credentials', label: 'Account', type: 'account' }, { fieldName: 'regions', label: 'Region', type: 'regions' }, { fieldName: 'cluster', label: 'Cluster' }, { fieldName: 'selectionStrategy', label: 'Server Group Selection', type: 'selectionStrategy' }, { fieldName: 'onlyEnabled', label: 'Server Group Filters', type: 'onlyEnabled' }, ]; const amazonStageFields: { [type: string]: IAmazonStageField[] } = { destroyAsg: [ { fieldName: 'credentials', label: 'Account', type: 'account' }, { fieldName: 'regions', label: 'Region', type: 'regions' }, { fieldName: 'cluster', label: 'Cluster' }, { fieldName: 'target', label: 'Server Group', type: 'target' }, ], destroyServerGroup: [ { fieldName: 'credentials', label: 'Account', type: 'account' }, { fieldName: 'regions', label: 'Region', type: 'regions' }, { fieldName: 'cluster', label: 'Cluster' }, { fieldName: 'target', label: 'Server Group', type: 'target' }, ], findAmi: findImageFields, findImage: findImageFields, }; const defaultFields: IAmazonStageField[] = [ { fieldName: 'credentials', label: 'Account', type: 'account' }, { fieldName: 'regions', label: 'Region', type: 'regions' }, ]; export function getAmazonStageFields(stage: Partial): IAmazonStageField[] { return amazonStageFields[stage.type || stage.alias || stage.key || ''] || defaultFields; } function getFieldValue(stage: IStage, field: IAmazonStageField): string { if (field.type === 'regions') { return (stage.regions || []).join(', '); } if (field.type === 'account') { return stage[field.fieldName] || stage.account || ''; } return stage[field.fieldName] || ''; } function renderField(props: IStageConfigProps, field: IAmazonStageField, accounts: IAccount[], regions: string[]) { const { application, stage, updateStageField } = props; if (field.type === 'selectionStrategy') { return ( ); } if (field.type === 'onlyEnabled') { return ( ); } if (field.type === 'target') { return ( ); } if (field.type === 'account') { return ( ); } if (field.type === 'regions') { return ( updateStageField({ [field.fieldName]: event.target.value })} showSelectAll={true} stringOptions={regions} value={stage[field.fieldName] || []} /> ); } if (field.fieldName === 'cluster') { const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(stage.credentials, stage.regions); const clusters = AppListExtractor.getClusters([application], clusterFilter); return ( ); } const updateField = (value: string) => { if (field.type === 'regions') { updateStageField({ regions: value .split(',') .map((region) => region.trim()) .filter(Boolean), }); return; } if (field.type === 'account') { updateStageField({ [field.fieldName]: value, account: value }); return; } updateStageField({ [field.fieldName]: value }); }; return ( updateField(event.target.value)} value={getFieldValue(stage, field)} /> ); } export function AmazonStageConfig({ application, stage, updateStageField }: IStageConfigProps) { const fields = getAmazonStageFields(stage); const [accounts, setAccounts] = useState([]); const [regions, setRegions] = useState([]); useEffect(() => { let mounted = true; AccountService.listAccounts('aws').then((accts) => mounted && setAccounts(accts)); AccountService.getUniqueAttributeForAllAccounts('aws', 'regions').then((regs) => mounted && setRegions(regs)); return () => { mounted = false; }; }, []); useEffect(() => { const defaults: any = {}; if (!stage.cloudProvider) { defaults.cloudProvider = 'aws'; } if (fields.some((field) => field.type === 'regions') && !stage.regions) { defaults.regions = []; } if (fields.some((field) => field.type === 'selectionStrategy') && !stage.selectionStrategy) { defaults.selectionStrategy = selectionStrategies[0].val; } if (fields.some((field) => field.type === 'selectionStrategy') && stage.onlyEnabled === undefined) { defaults.onlyEnabled = true; } if (fields.some((field) => field.type === 'account') && !stage.credentials && application.defaultCredentials.aws) { defaults.credentials = application.defaultCredentials.aws; defaults.account = application.defaultCredentials.aws; } if ( fields.some((field) => field.type === 'regions') && (!stage.regions || !stage.regions.length) && application.defaultRegions.aws ) { defaults.regions = [application.defaultRegions.aws]; } if (Object.keys(defaults).length) { updateStageField(defaults); } }, [ application, fields, stage.cloudProvider, stage.credentials, stage.onlyEnabled, stage.regions, stage.selectionStrategy, updateStageField, ]); return (
{fields.map((field) => ( {renderField({ application, stage, updateStageField } as IStageConfigProps, field, accounts, regions)} ))}
); }