@spinnaker/core 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/pipeline/config/stages/bake/bakeStageChooseManagedImage.component.d.ts +16 -0
- package/package.json +2 -2
- package/src/config/settings.ts +1 -2
- package/src/help/HelpMenu.tsx +1 -2
- package/src/help/help.contents.ts +6 -2
- package/src/pipeline/config/stages/bake/bakeStage.module.js +2 -0
- package/src/pipeline/config/stages/bake/bakeStageChooseManagedImage.component.html +12 -0
- package/src/pipeline/config/stages/bake/bakeStageChooseManagedImage.component.ts +49 -0
- package/src/pipeline/config/stages/bake/bakeStageChooseOs.component.html +0 -1
- package/src/pipeline/config/stages/bakeManifest/helm/BakeHelmConfigForm.spec.tsx +44 -0
- package/src/pipeline/config/stages/bakeManifest/helm/BakeHelmConfigForm.tsx +14 -0
- package/src/pipeline/config/stages/pipeline/pipelineStage.html +3 -0
- package/src/pipeline/executions/execution/ExecutionMarker.tsx +17 -11
- package/src/widgets/accountNamespaceClusterSelector.component.js +59 -57
- package/src/widgets/accountRegionClusterSelector.component.js +96 -93
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IController } from 'angular';
|
|
2
|
+
export interface IManagedImageOption {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
osType: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class BakeStageChooseManagedImageController implements IController {
|
|
8
|
+
model: any;
|
|
9
|
+
managedImageOptions: IManagedImageOption[];
|
|
10
|
+
onChange: () => any;
|
|
11
|
+
$onChanges(): void;
|
|
12
|
+
getManagedImageDescription(managedImageOption: IManagedImageOption): string;
|
|
13
|
+
getManagedImageDetailedDescription(managedImageOption: IManagedImageOption): string;
|
|
14
|
+
getManagedImageDisabled(managedImageOption: IManagedImageOption): boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const PIPELINE_BAKE_STAGE_CHOOSE_MANAGED_IMAGE = "spinnaker.core.pipeline.bake.chooseManagedImage.component";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spinnaker/core",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.23.0",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -120,5 +120,5 @@
|
|
|
120
120
|
"shx": "0.3.3",
|
|
121
121
|
"typescript": "4.3.5"
|
|
122
122
|
},
|
|
123
|
-
"gitHead": "
|
|
123
|
+
"gitHead": "4d61e53884040e8cae45d29b398c88e3814c6aca"
|
|
124
124
|
}
|
package/src/config/settings.ts
CHANGED
|
@@ -162,8 +162,7 @@ SETTINGS.analytics = SETTINGS.analytics || {};
|
|
|
162
162
|
SETTINGS.providers = SETTINGS.providers || {};
|
|
163
163
|
SETTINGS.defaultTimeZone = SETTINGS.defaultTimeZone || 'America/Los_Angeles';
|
|
164
164
|
SETTINGS.dockerInsights = SETTINGS.dockerInsights || { enabled: false, url: '' };
|
|
165
|
-
SETTINGS.changelogUrl =
|
|
166
|
-
SETTINGS.changelogUrl || 'https://www.spinnaker.io/community/releases/versions/:version-changelog';
|
|
165
|
+
SETTINGS.changelogUrl = SETTINGS.changelogUrl || 'https://spinnaker.io/changelogs/:version-changelog';
|
|
167
166
|
SETTINGS.managedDelivery = SETTINGS.managedDelivery || {
|
|
168
167
|
defaultManifest: 'spinnaker.yml',
|
|
169
168
|
manifestBasePath: '.spinnaker',
|
package/src/help/HelpMenu.tsx
CHANGED
|
@@ -38,8 +38,7 @@ const Version = () => {
|
|
|
38
38
|
return null;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const
|
|
42
|
-
const CHANGELOG_URL = SETTINGS.changelogUrl.replace(':version', CHANGELOG_PATH);
|
|
41
|
+
const CHANGELOG_URL = SETTINGS.changelogUrl.replace(':version', SETTINGS.version);
|
|
43
42
|
|
|
44
43
|
return (
|
|
45
44
|
<MenuItem href={CHANGELOG_URL} target="_blank">
|
|
@@ -298,10 +298,12 @@ const helpContents: { [key: string]: string } = {
|
|
|
298
298
|
'<p>Explicitly evaluate SpEL expressions in overrides just prior to manifest baking. Can be paired with the "Skip SpEL evaluation" option in the Deploy Manifest stage when baking a third-party manifest artifact with expressions not meant for Spinnaker to evaluate as SpEL.</p>',
|
|
299
299
|
'pipeline.config.bake.manifest.templateRenderer': '<p>This is the engine used for rendering your manifest.</p>',
|
|
300
300
|
'pipeline.config.bake.manifest.helm.chartFilePath': `
|
|
301
|
-
<p>This is the relative path to the Chart.yaml file within your Git repo.</p>
|
|
302
|
-
<p>e.g.: <b>helm/my-chart
|
|
301
|
+
<p>This is the relative path to the directory containing the Chart.yaml file within your Git repo.</p>
|
|
302
|
+
<p>e.g.: <b>helm/my-chart</b></p>`,
|
|
303
303
|
'pipeline.config.bake.manifest.helm.rawOverrides':
|
|
304
304
|
'Use <i>--set</i> instead of <i>--set-string</i> when injecting override values. Values injected using <i>--set</i> will be converted to primitive types by Helm.',
|
|
305
|
+
'pipeline.config.bake.manifest.helm.includeCRDs':
|
|
306
|
+
'<p>Include Custom Resource Definitions in the templated output.</p>',
|
|
305
307
|
'pipeline.config.bake.manifest.kustomize.filePath': `
|
|
306
308
|
<p>This is the relative path to the kustomization.yaml file within your Git repo.</p>
|
|
307
309
|
<p>e.g.: <b>examples/wordpress/mysql/kustomization.yaml</b></p>`,
|
|
@@ -468,6 +470,8 @@ const helpContents: { [key: string]: string } = {
|
|
|
468
470
|
Typing into this verification field is annoying! But it serves as a reminder that you are
|
|
469
471
|
changing something in an account deemed important, and prevents you from accidentally changing something
|
|
470
472
|
when you meant to click on the "Cancel" button.`,
|
|
473
|
+
'pipeline.skipDownstreamOutput':
|
|
474
|
+
'when checked, the output of the child pipeline is not added to the pipeline context',
|
|
471
475
|
'pipeline.waitForCompletion':
|
|
472
476
|
'if unchecked, marks the stage as successful right away without waiting for the pipeline to complete',
|
|
473
477
|
'jenkins.waitForCompletion':
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { module } from 'angular';
|
|
4
4
|
|
|
5
5
|
import { CORE_PIPELINE_CONFIG_STAGES_BAKE_BAKESTAGE } from './bakeStage';
|
|
6
|
+
import { PIPELINE_BAKE_STAGE_CHOOSE_MANAGED_IMAGE } from './bakeStageChooseManagedImage.component';
|
|
6
7
|
import { PIPELINE_BAKE_STAGE_CHOOSE_OS } from './bakeStageChooseOs.component';
|
|
7
8
|
import { CORE_PIPELINE_CONFIG_STAGES_BAKE_MODAL_ADDEXTENDEDATTRIBUTE_CONTROLLER_MODAL } from './modal/addExtendedAttribute.controller.modal';
|
|
8
9
|
|
|
@@ -12,4 +13,5 @@ module(CORE_PIPELINE_CONFIG_STAGES_BAKE_BAKESTAGE_MODULE, [
|
|
|
12
13
|
CORE_PIPELINE_CONFIG_STAGES_BAKE_BAKESTAGE,
|
|
13
14
|
CORE_PIPELINE_CONFIG_STAGES_BAKE_MODAL_ADDEXTENDEDATTRIBUTE_CONTROLLER_MODAL,
|
|
14
15
|
PIPELINE_BAKE_STAGE_CHOOSE_OS,
|
|
16
|
+
PIPELINE_BAKE_STAGE_CHOOSE_MANAGED_IMAGE,
|
|
15
17
|
]);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<ui-select ng-model="$ctrl.model" on-select="$ctrl.onChange()" class="form-control input-sm">
|
|
2
|
+
<ui-select-match placeholder="Select a Managed Image">
|
|
3
|
+
<span ng-bind-html="$ctrl.getManagedImageDescription($select.selected)"></span>
|
|
4
|
+
</ui-select-match>
|
|
5
|
+
<ui-select-choices
|
|
6
|
+
repeat="managedImageOption.id as managedImageOption in $ctrl.managedImageOptions | filter: $select.search"
|
|
7
|
+
ui-disable-choice="$ctrl.getManagedImageDisabled(managedImageOption)"
|
|
8
|
+
>
|
|
9
|
+
<strong ng-bind-html="$ctrl.getManagedImageDescription(managedImageOption)"></strong>
|
|
10
|
+
<div ng-bind-html="$ctrl.getManagedImageDetailedDescription(managedImageOption)"></div>
|
|
11
|
+
</ui-select-choices>
|
|
12
|
+
</ui-select>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { IComponentOptions, IController } from 'angular';
|
|
2
|
+
import { module } from 'angular';
|
|
3
|
+
import { SETTINGS } from '../../../../config/settings';
|
|
4
|
+
|
|
5
|
+
export interface IManagedImageOption {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
osType: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class BakeStageChooseManagedImageController implements IController {
|
|
12
|
+
public model: any;
|
|
13
|
+
public managedImageOptions: IManagedImageOption[];
|
|
14
|
+
public onChange: () => any;
|
|
15
|
+
|
|
16
|
+
public $onChanges(): void {}
|
|
17
|
+
|
|
18
|
+
public getManagedImageDescription(managedImageOption: IManagedImageOption): string {
|
|
19
|
+
return managedImageOption?.name || '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public getManagedImageDetailedDescription(managedImageOption: IManagedImageOption): string {
|
|
23
|
+
if (managedImageOption?.osType) {
|
|
24
|
+
return `${managedImageOption.name} (${managedImageOption.osType})`;
|
|
25
|
+
}
|
|
26
|
+
return `${managedImageOption.name}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public getManagedImageDisabled(managedImageOption: IManagedImageOption): boolean {
|
|
30
|
+
const disabledImages = SETTINGS.disabledImages || [];
|
|
31
|
+
return disabledImages.includes(managedImageOption.id);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const bakeStageChooseManagedImageComponent: IComponentOptions = {
|
|
36
|
+
bindings: {
|
|
37
|
+
managedImageOptions: '<',
|
|
38
|
+
model: '=',
|
|
39
|
+
onChange: '=',
|
|
40
|
+
},
|
|
41
|
+
controller: BakeStageChooseManagedImageController,
|
|
42
|
+
templateUrl: require('./bakeStageChooseManagedImage.component.html'),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const PIPELINE_BAKE_STAGE_CHOOSE_MANAGED_IMAGE = 'spinnaker.core.pipeline.bake.chooseManagedImage.component';
|
|
46
|
+
module(PIPELINE_BAKE_STAGE_CHOOSE_MANAGED_IMAGE, []).component(
|
|
47
|
+
'bakeStageChooseManagedImage',
|
|
48
|
+
bakeStageChooseManagedImageComponent,
|
|
49
|
+
);
|
|
@@ -129,4 +129,48 @@ describe('<BakeHelmConfigForm />', () => {
|
|
|
129
129
|
expect(component.find('.Select-value-label > span').text().includes(expectedArtifactDisplayName)).toBe(true);
|
|
130
130
|
expect(component.find(StageConfigField).findWhere((x) => x.text() === helmChartFilePathFieldName).length).toBe(1);
|
|
131
131
|
});
|
|
132
|
+
|
|
133
|
+
it('render the include crds checkbox if the template render is HELM3', async () => {
|
|
134
|
+
const stage = ({
|
|
135
|
+
templateRenderer: 'HELM3',
|
|
136
|
+
} as unknown) as IStage;
|
|
137
|
+
|
|
138
|
+
const props = getProps();
|
|
139
|
+
|
|
140
|
+
const component = mount(
|
|
141
|
+
<SpinFormik
|
|
142
|
+
initialValues={stage}
|
|
143
|
+
onSubmit={() => null}
|
|
144
|
+
validate={() => null}
|
|
145
|
+
render={(formik) => <BakeHelmConfigForm {...props} formik={formik} />}
|
|
146
|
+
/>,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
await new Promise((resolve) => setTimeout(resolve)); // wait one js tick for promise to resolve
|
|
150
|
+
component.setProps({}); // force a re-render
|
|
151
|
+
|
|
152
|
+
expect(component.find('span.label-text').findWhere((x) => x.text() === 'Include CRDs').length).toBe(1);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('does not render the include crds checkbox if the template render is HELM2', async () => {
|
|
156
|
+
const stage = ({
|
|
157
|
+
templateRenderer: 'HELM2',
|
|
158
|
+
} as unknown) as IStage;
|
|
159
|
+
|
|
160
|
+
const props = getProps();
|
|
161
|
+
|
|
162
|
+
const component = mount(
|
|
163
|
+
<SpinFormik
|
|
164
|
+
initialValues={stage}
|
|
165
|
+
onSubmit={() => null}
|
|
166
|
+
validate={() => null}
|
|
167
|
+
render={(formik) => <BakeHelmConfigForm {...props} formik={formik} />}
|
|
168
|
+
/>,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
await new Promise((resolve) => setTimeout(resolve)); // wait one js tick for promise to resolve
|
|
172
|
+
component.setProps({}); // force a re-render
|
|
173
|
+
|
|
174
|
+
expect(component.find('span.label-text').findWhere((x) => x.text() === 'Include CRDs').length).toBe(0);
|
|
175
|
+
});
|
|
132
176
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import type { IFormikStageConfigInjectedProps } from '../../FormikStageConfig';
|
|
4
|
+
import { ManifestRenderers } from '../ManifestRenderers';
|
|
4
5
|
import { AccountService } from '../../../../../account';
|
|
5
6
|
import {
|
|
6
7
|
ArtifactTypePatterns,
|
|
@@ -257,6 +258,19 @@ export class BakeHelmConfigForm extends React.Component<IFormikStageConfigInject
|
|
|
257
258
|
onChange={() => this.props.formik.setFieldValue('rawOverrides', !stage.rawOverrides)}
|
|
258
259
|
/>
|
|
259
260
|
</StageConfigField>
|
|
261
|
+
{stage.templateRenderer === ManifestRenderers.HELM3 && (
|
|
262
|
+
<StageConfigField
|
|
263
|
+
fieldColumns={6}
|
|
264
|
+
helpKey={'pipeline.config.bake.manifest.helm.includeCRDs'}
|
|
265
|
+
label="Include CRDs"
|
|
266
|
+
>
|
|
267
|
+
<CheckboxInput
|
|
268
|
+
value={stage.includeCRDs}
|
|
269
|
+
text={''}
|
|
270
|
+
onChange={() => this.props.formik.setFieldValue('includeCRDs', !stage.includeCRDs)}
|
|
271
|
+
/>
|
|
272
|
+
</StageConfigField>
|
|
273
|
+
)}
|
|
260
274
|
<StageConfigField
|
|
261
275
|
fieldColumns={6}
|
|
262
276
|
helpKey={'pipeline.config.bake.manifest.overrideExpressionEvaluation'}
|
|
@@ -105,6 +105,9 @@
|
|
|
105
105
|
</div>
|
|
106
106
|
</div>
|
|
107
107
|
</div>
|
|
108
|
+
<stage-config-field label="Skip downstream output" help-key="pipeline.skipDownstreamOutput">
|
|
109
|
+
<input type="checkbox" class="input-sm" name="skipDownstreamOutput" ng-model="stage.skipDownstreamOutput" />
|
|
110
|
+
</stage-config-field>
|
|
108
111
|
<stage-config-field label="Wait for results" help-key="pipeline.waitForCompletion">
|
|
109
112
|
<input type="checkbox" class="input-sm" name="waitForCompletion" ng-model="stage.waitForCompletion" />
|
|
110
113
|
</stage-config-field>
|
|
@@ -95,18 +95,24 @@ export class ExecutionMarker extends React.Component<IExecutionMarkerProps, IExe
|
|
|
95
95
|
public render() {
|
|
96
96
|
const { stage, application, execution, active, previousStageActive, width } = this.props;
|
|
97
97
|
let stageType = (stage.activeStageType || stage.type).toLowerCase(); // support groups
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
98
|
+
if (SETTINGS.feature.manualJudgmentParentPipeline) {
|
|
99
|
+
stage.stages.forEach((childStage: IStage) => {
|
|
100
|
+
if (
|
|
101
|
+
childStage.type == 'pipeline' &&
|
|
102
|
+
application.executions != undefined &&
|
|
103
|
+
application.executions.data != undefined
|
|
104
|
+
) {
|
|
105
|
+
const childPipeline = application.executions.data.find((p: any) => p.id === childStage.context.executionId);
|
|
106
|
+
if (childPipeline != undefined) {
|
|
107
|
+
childPipeline.stages.forEach((stageToCheck: IStage) => {
|
|
108
|
+
if (stageToCheck.type == 'manualJudgment' && stageToCheck.status == 'RUNNING') {
|
|
109
|
+
stageType = 'manualjudgment';
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
107
113
|
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
110
116
|
const pipelineStatus = this.stageStatus(stage.status.toLowerCase());
|
|
111
117
|
const markerClassName = [
|
|
112
118
|
stage.type !== 'group' ? 'clickable' : '',
|
|
@@ -25,74 +25,76 @@ module(CORE_WIDGETS_ACCOUNTNAMESPACECLUSTERSELECTOR_COMPONENT, []).directive(
|
|
|
25
25
|
templateUrl: require('./accountNamespaceClusterSelector.component.html'),
|
|
26
26
|
controllerAs: 'vm',
|
|
27
27
|
controller: function controller() {
|
|
28
|
-
this
|
|
28
|
+
this.$onInit = () => {
|
|
29
|
+
this.clusterField = this.clusterField || 'cluster';
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const vm = this;
|
|
32
|
+
let isTextInputForClusterFiled;
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
let namespaces;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const setNamespaceList = () => {
|
|
37
|
+
const accountFilter = (cluster) => (cluster ? cluster.account === vm.component.credentials : true);
|
|
38
|
+
// TODO(lwander): Move away from regions to namespaces here.
|
|
39
|
+
const namespaceList = AppListExtractor.getRegions([vm.application], accountFilter);
|
|
40
|
+
vm.namespaces = namespaceList.length ? namespaceList : namespaces;
|
|
41
|
+
};
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
const setClusterList = () => {
|
|
44
|
+
const namespaceField = vm.component.namespaces;
|
|
45
|
+
// TODO(lwander): Move away from regions to namespaces here.
|
|
46
|
+
const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(
|
|
47
|
+
vm.component.credentials,
|
|
48
|
+
namespaceField,
|
|
49
|
+
);
|
|
50
|
+
vm.clusterList = AppListExtractor.getClusters([vm.application], clusterFilter);
|
|
51
|
+
};
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
vm.namespaceChanged = () => {
|
|
54
|
+
setClusterList();
|
|
55
|
+
if (!isTextInputForClusterFiled && !_.includes(vm.clusterList, vm.component[this.clusterField])) {
|
|
56
|
+
vm.component[this.clusterField] = undefined;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const setToggledState = () => {
|
|
61
|
+
vm.namespaces = namespaces;
|
|
62
|
+
isTextInputForClusterFiled = true;
|
|
63
|
+
};
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
const setUnToggledState = () => {
|
|
66
|
+
vm.component[this.clusterField] = undefined;
|
|
67
|
+
isTextInputForClusterFiled = false;
|
|
68
|
+
setNamespaceList();
|
|
69
|
+
};
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
vm.clusterSelectInputToggled = (isToggled) => {
|
|
72
|
+
isToggled ? setToggledState() : setUnToggledState();
|
|
73
|
+
};
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
vm.accountUpdated = () => {
|
|
76
|
+
vm.component[this.clusterField] = undefined;
|
|
77
|
+
setNamespaceList();
|
|
78
|
+
setClusterList();
|
|
79
|
+
};
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
const init = () => {
|
|
82
|
+
AccountService.getUniqueAttributeForAllAccounts(vm.component.cloudProviderType, 'namespaces')
|
|
83
|
+
.then((allNamespaces) => {
|
|
84
|
+
namespaces = allNamespaces;
|
|
85
|
+
return allNamespaces;
|
|
86
|
+
})
|
|
87
|
+
.then((allNamespaces) => {
|
|
88
|
+
setNamespaceList();
|
|
89
|
+
setClusterList();
|
|
90
|
+
vm.namespaces = _.includes(vm.clusterList, vm.component[this.clusterField])
|
|
91
|
+
? vm.namespaces
|
|
92
|
+
: allNamespaces;
|
|
93
|
+
});
|
|
94
|
+
};
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
init();
|
|
97
|
+
};
|
|
96
98
|
},
|
|
97
99
|
};
|
|
98
100
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { module } from 'angular';
|
|
4
4
|
import _ from 'lodash';
|
|
5
|
+
import { $log } from 'ngimport';
|
|
5
6
|
|
|
6
7
|
import { AccountService } from '../account/AccountService';
|
|
7
8
|
import { AppListExtractor } from '../application/listExtractor/AppListExtractor';
|
|
@@ -27,104 +28,106 @@ module(CORE_WIDGETS_ACCOUNTREGIONCLUSTERSELECTOR_COMPONENT, []).directive('accou
|
|
|
27
28
|
templateUrl: require('./accountRegionClusterSelector.component.html'),
|
|
28
29
|
controllerAs: 'vm',
|
|
29
30
|
controller: function controller() {
|
|
30
|
-
this
|
|
31
|
+
this.$onInit = () => {
|
|
32
|
+
this.clusterField = this.clusterField || 'cluster';
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
const vm = this;
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const showAllRegions = vm.showAllRegions || false;
|
|
39
|
-
|
|
40
|
-
let isTextInputForClusterFiled;
|
|
41
|
-
|
|
42
|
-
let regions;
|
|
43
|
-
|
|
44
|
-
const setRegionList = () => {
|
|
45
|
-
const accountFilter = (cluster) => (cluster ? cluster.account === vm.component.credentials : true);
|
|
46
|
-
const regionList = AppListExtractor.getRegions([vm.application], accountFilter);
|
|
47
|
-
vm.regions = showAllRegions ? regions : regionList.length ? regionList : regions;
|
|
48
|
-
(vm.regions || []).sort();
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const setClusterList = () => {
|
|
52
|
-
const regionField = this.singleRegion ? vm.component.region : vm.component.regions;
|
|
53
|
-
const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(
|
|
54
|
-
vm.component.credentials,
|
|
55
|
-
regionField,
|
|
56
|
-
);
|
|
57
|
-
vm.clusterList = AppListExtractor.getClusters([vm.application], clusterFilter);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
vm.regionChanged = () => {
|
|
61
|
-
setClusterList();
|
|
62
|
-
if (!isTextInputForClusterFiled && !_.includes(vm.clusterList, vm.component[this.clusterField])) {
|
|
63
|
-
vm.component[this.clusterField] = undefined;
|
|
36
|
+
if (vm.showClusterSelect === undefined) {
|
|
37
|
+
vm.showClusterSelect = true;
|
|
64
38
|
}
|
|
65
|
-
};
|
|
66
39
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
isTextInputForClusterFiled
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
vm.component.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
40
|
+
const showAllRegions = vm.showAllRegions || false;
|
|
41
|
+
|
|
42
|
+
let isTextInputForClusterFiled;
|
|
43
|
+
|
|
44
|
+
let regions;
|
|
45
|
+
|
|
46
|
+
const setRegionList = () => {
|
|
47
|
+
const accountFilter = (cluster) => (cluster ? cluster.account === vm.component.credentials : true);
|
|
48
|
+
const regionList = AppListExtractor.getRegions([vm.application], accountFilter);
|
|
49
|
+
vm.regions = showAllRegions ? regions : regionList.length ? regionList : regions;
|
|
50
|
+
(vm.regions || []).sort();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const setClusterList = () => {
|
|
54
|
+
const regionField = this.singleRegion ? vm.component.region : vm.component.regions;
|
|
55
|
+
const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(
|
|
56
|
+
vm.component.credentials,
|
|
57
|
+
regionField,
|
|
58
|
+
);
|
|
59
|
+
vm.clusterList = AppListExtractor.getClusters([vm.application], clusterFilter);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
vm.regionChanged = () => {
|
|
63
|
+
setClusterList();
|
|
64
|
+
if (!isTextInputForClusterFiled && !_.includes(vm.clusterList, vm.component[this.clusterField])) {
|
|
65
|
+
vm.component[this.clusterField] = undefined;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const setToggledState = () => {
|
|
70
|
+
vm.regions = regions;
|
|
71
|
+
isTextInputForClusterFiled = true;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const setUnToggledState = () => {
|
|
75
|
+
vm.component[this.clusterField] = undefined;
|
|
76
|
+
isTextInputForClusterFiled = false;
|
|
77
|
+
setRegionList();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
vm.clusterSelectInputToggled = (isToggled) => {
|
|
81
|
+
isToggled ? setToggledState() : setUnToggledState();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
vm.clusterChanged = (clusterName) => {
|
|
85
|
+
const filterByCluster = AppListExtractor.monikerClusterNameFilter(clusterName);
|
|
86
|
+
const clusterMoniker = _.first(_.uniq(AppListExtractor.getMonikers([vm.application], filterByCluster)));
|
|
87
|
+
if (_.isNil(clusterMoniker)) {
|
|
88
|
+
//remove the moniker from the stage if one doesn't exist.
|
|
89
|
+
vm.component.moniker = undefined;
|
|
90
|
+
} else {
|
|
91
|
+
//clusters don't contain sequences, so null it out.
|
|
92
|
+
clusterMoniker.sequence = null;
|
|
93
|
+
vm.component.moniker = clusterMoniker;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
vm.accountUpdated = () => {
|
|
98
|
+
vm.component[this.clusterField] = undefined;
|
|
99
|
+
setRegionList();
|
|
100
|
+
setClusterList();
|
|
101
|
+
if (vm.onAccountUpdate) {
|
|
102
|
+
vm.onAccountUpdate();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const init = () => {
|
|
107
|
+
AccountService.getUniqueAttributeForAllAccounts(vm.component.cloudProviderType, 'regions')
|
|
108
|
+
.then((allRegions) => {
|
|
109
|
+
regions = allRegions;
|
|
110
|
+
|
|
111
|
+
// TODO(duftler): Remove this once we finish deprecating the old style regions/zones in clouddriver GCE credentials.
|
|
112
|
+
const regionObjs = _.filter(regions, (region) => _.isObject(region));
|
|
113
|
+
if (regionObjs.length) {
|
|
114
|
+
const oldStyleRegions = _.chain(regionObjs)
|
|
115
|
+
.map((regionObj) => _.keys(regionObj))
|
|
116
|
+
.flatten()
|
|
117
|
+
.value();
|
|
118
|
+
regions = _.chain(regions).difference(regionObjs).union(oldStyleRegions).value();
|
|
119
|
+
}
|
|
120
|
+
return regions.sort();
|
|
121
|
+
})
|
|
122
|
+
.then((allRegions) => {
|
|
123
|
+
setRegionList();
|
|
124
|
+
setClusterList();
|
|
125
|
+
vm.regions = _.includes(vm.clusterList, vm.component[this.clusterField]) ? vm.regions : allRegions;
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
init();
|
|
125
130
|
};
|
|
126
|
-
|
|
127
|
-
init();
|
|
128
131
|
},
|
|
129
132
|
};
|
|
130
133
|
});
|