@spinnaker/kubernetes 2025.1.4 → 2025.2.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/dist/index.js +37010 -4266
- package/dist/index.js.map +1 -1
- package/dist/interfaces/infrastructure.types.d.ts +4 -0
- package/dist/loadBalancer/details/KubernetesLoadBalancerActions.d.ts +7 -0
- package/dist/loadBalancer/details/sections/IKubernetesLoadBalancerDetailsSectionProps.d.ts +5 -0
- package/dist/loadBalancer/details/sections/LoadBalancerAnnotationCustomSection.d.ts +3 -0
- package/dist/loadBalancer/details/sections/LoadBalancerEventsSection.d.ts +3 -0
- package/dist/loadBalancer/details/sections/LoadBalancerInformationSection.d.ts +3 -0
- package/dist/loadBalancer/details/sections/LoadBalancerLabelsSection.d.ts +3 -0
- package/dist/loadBalancer/details/sections/LoadBalancerStatusSection.d.ts +3 -0
- package/dist/loadBalancer/details/sections/index.d.ts +6 -0
- package/dist/loadBalancer/details/useKubernetesLoadBalancerDetails.d.ts +3 -0
- package/dist/loadBalancer/index.d.ts +4 -1
- package/dist/loadBalancer/transformer.d.ts +5 -1
- package/dist/manifest/delete/Delete.d.ts +10 -0
- package/dist/manifest/delete/DeleteModal.d.ts +13 -0
- package/dist/manifest/rollout/PauseRollout.d.ts +9 -0
- package/dist/manifest/rollout/ResumeRollout.d.ts +9 -0
- package/dist/manifest/rollout/RollingRestart.d.ts +1 -0
- package/dist/manifest/rollout/UndoRollout.d.ts +9 -0
- package/dist/manifest/rollout/UndoRolloutModal.d.ts +12 -0
- package/dist/manifest/rollout/undo.controller.d.ts +4 -0
- package/dist/manifest/scale/Scale.d.ts +10 -0
- package/dist/manifest/scale/ScaleModal.d.ts +13 -0
- package/package.json +2 -2
- package/src/interfaces/infrastructure.types.ts +11 -0
- package/src/kubernetes.module.ts +30 -7
- package/src/loadBalancer/details/KubernetesLoadBalancerActions.tsx +68 -0
- package/src/loadBalancer/details/sections/IKubernetesLoadBalancerDetailsSectionProps.ts +6 -0
- package/src/loadBalancer/details/sections/LoadBalancerAnnotationCustomSection.tsx +9 -0
- package/src/loadBalancer/details/sections/LoadBalancerEventsSection.tsx +15 -0
- package/src/loadBalancer/details/sections/LoadBalancerInformationSection.tsx +28 -0
- package/src/loadBalancer/details/sections/LoadBalancerLabelsSection.tsx +15 -0
- package/src/loadBalancer/details/sections/LoadBalancerStatusSection.tsx +138 -0
- package/src/loadBalancer/details/sections/index.ts +6 -0
- package/src/loadBalancer/details/useKubernetesLoadBalancerDetails.ts +52 -0
- package/src/loadBalancer/index.ts +4 -1
- package/src/loadBalancer/transformer.ts +2 -13
- package/src/manifest/delete/Delete.tsx +34 -0
- package/src/manifest/delete/DeleteModal.tsx +152 -0
- package/src/manifest/editor/json/JsonEditor.tsx +3 -4
- package/src/manifest/rollout/PauseRollout.tsx +46 -0
- package/src/manifest/rollout/ResumeRollout.tsx +46 -0
- package/src/manifest/rollout/RollingRestart.tsx +21 -13
- package/src/manifest/rollout/UndoRollout.tsx +33 -0
- package/src/manifest/rollout/UndoRolloutModal.tsx +123 -0
- package/src/manifest/rollout/undo.controller.ts +1 -1
- package/src/manifest/scale/Scale.tsx +34 -0
- package/src/manifest/scale/ScaleModal.tsx +115 -0
- package/src/manifest/selector/ManifestSelector.spec.tsx +2 -3
- package/src/manifest/selector/ManifestSelector.tsx +1 -2
- package/src/rawResource/rawResource.dataSource.ts +20 -24
- package/src/securityGroup/transformer.ts +1 -5
- package/dist/loadBalancer/details/details.controller.d.ts +0 -1
- package/src/loadBalancer/details/details.controller.ts +0 -101
- package/src/loadBalancer/details/details.html +0 -187
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { FormikProps } from 'formik';
|
|
2
|
+
import { Form } from 'formik';
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
import { Button, Modal } from 'react-bootstrap';
|
|
5
|
+
|
|
6
|
+
import type { Application, IModalComponentProps, IModalProps } from '@spinnaker/core';
|
|
7
|
+
import {
|
|
8
|
+
ManifestWriter,
|
|
9
|
+
ModalClose,
|
|
10
|
+
robotToHuman,
|
|
11
|
+
SpinFormik,
|
|
12
|
+
SubmitButton,
|
|
13
|
+
TaskMonitorWrapper,
|
|
14
|
+
TaskReason,
|
|
15
|
+
UserVerification,
|
|
16
|
+
useTaskMonitor,
|
|
17
|
+
} from '@spinnaker/core';
|
|
18
|
+
|
|
19
|
+
import { ScaleSettingsForm } from './ScaleSettingsForm';
|
|
20
|
+
import type { IAnyKubernetesResource } from '../../interfaces';
|
|
21
|
+
import type { IScaleCommand } from './scale.controller';
|
|
22
|
+
|
|
23
|
+
export interface IKubernetesScaleModalProps
|
|
24
|
+
extends Pick<IModalProps, 'isOpen'>,
|
|
25
|
+
Pick<IModalComponentProps, 'dismissModal'> {
|
|
26
|
+
application: Application;
|
|
27
|
+
resource: IAnyKubernetesResource;
|
|
28
|
+
currentReplicas: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface IKubernetesScaleValues {
|
|
32
|
+
reason?: string;
|
|
33
|
+
replicas: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function ScaleModal({
|
|
37
|
+
application,
|
|
38
|
+
resource,
|
|
39
|
+
currentReplicas,
|
|
40
|
+
isOpen,
|
|
41
|
+
dismissModal,
|
|
42
|
+
}: IKubernetesScaleModalProps) {
|
|
43
|
+
const initialValues: IKubernetesScaleValues = {
|
|
44
|
+
replicas: currentReplicas,
|
|
45
|
+
};
|
|
46
|
+
const [verified, setVerified] = useState<boolean>(false);
|
|
47
|
+
const taskMonitor = useTaskMonitor(
|
|
48
|
+
{
|
|
49
|
+
application,
|
|
50
|
+
title: `Scaling ${resource.name} in ${resource.namespace}`,
|
|
51
|
+
onTaskComplete: () => application.serverGroups.refresh(true),
|
|
52
|
+
},
|
|
53
|
+
dismissModal,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const submit = (values: IKubernetesScaleValues): void => {
|
|
57
|
+
const payload = {
|
|
58
|
+
cloudProvider: 'kubernetes',
|
|
59
|
+
manifestName: resource.name,
|
|
60
|
+
location: resource.namespace,
|
|
61
|
+
account: resource.account,
|
|
62
|
+
reason: values.reason,
|
|
63
|
+
replicas: values.replicas,
|
|
64
|
+
};
|
|
65
|
+
return taskMonitor.submit(() => ManifestWriter.scaleManifest(payload, application));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const onOptionChange = (formik: FormikProps<IKubernetesScaleValues>, values: IScaleCommand): void => {
|
|
69
|
+
formik.setFieldValue('replicas', values.replicas);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Modal show={isOpen} onHide={dismissModal}>
|
|
74
|
+
<TaskMonitorWrapper monitor={taskMonitor} />
|
|
75
|
+
<SpinFormik<IKubernetesScaleValues>
|
|
76
|
+
initialValues={initialValues}
|
|
77
|
+
onSubmit={submit}
|
|
78
|
+
render={(formik) => (
|
|
79
|
+
<>
|
|
80
|
+
<ModalClose dismiss={dismissModal} />
|
|
81
|
+
<Modal.Header>
|
|
82
|
+
<Modal.Title>
|
|
83
|
+
Scale {robotToHuman(resource.name)} in {resource.namespace}
|
|
84
|
+
</Modal.Title>
|
|
85
|
+
</Modal.Header>
|
|
86
|
+
<Modal.Body>
|
|
87
|
+
<Form className="form-horizontal">
|
|
88
|
+
<ScaleSettingsForm
|
|
89
|
+
onChange={(options: IScaleCommand) => onOptionChange(formik, options)}
|
|
90
|
+
options={
|
|
91
|
+
({
|
|
92
|
+
replicas: formik.values.replicas,
|
|
93
|
+
} as unknown) as IScaleCommand
|
|
94
|
+
}
|
|
95
|
+
/>
|
|
96
|
+
<TaskReason reason={formik.values.reason} onChange={(val) => formik.setFieldValue('reason', val)} />
|
|
97
|
+
</Form>
|
|
98
|
+
</Modal.Body>
|
|
99
|
+
<Modal.Footer>
|
|
100
|
+
<UserVerification account={resource.account} onValidChange={setVerified} />
|
|
101
|
+
<Button onClick={dismissModal}>Cancel</Button>
|
|
102
|
+
<SubmitButton
|
|
103
|
+
onClick={() => submit(formik.values)}
|
|
104
|
+
isDisabled={!formik.isValid || formik.isSubmitting || !verified}
|
|
105
|
+
isFormSubmit={true}
|
|
106
|
+
submitting={formik.isSubmitting}
|
|
107
|
+
label={`Scale ${resource.name}`}
|
|
108
|
+
/>
|
|
109
|
+
</Modal.Footer>
|
|
110
|
+
</>
|
|
111
|
+
)}
|
|
112
|
+
/>
|
|
113
|
+
</Modal>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { mount } from 'enzyme';
|
|
2
|
-
import { $q } from 'ngimport';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import type { Option } from 'react-select';
|
|
5
4
|
import Select, { Creatable } from 'react-select';
|
|
@@ -25,8 +24,8 @@ describe('<ManifestSelector />', () => {
|
|
|
25
24
|
let searchService: Spy;
|
|
26
25
|
|
|
27
26
|
beforeEach(() => {
|
|
28
|
-
searchService = spyOn(ManifestKindSearchService, 'search').and.returnValue(
|
|
29
|
-
spyOn(AccountService, 'getAllAccountDetailsForProvider').and.returnValue(
|
|
27
|
+
searchService = spyOn(ManifestKindSearchService, 'search').and.returnValue(Promise.resolve([]));
|
|
28
|
+
spyOn(AccountService, 'getAllAccountDetailsForProvider').and.returnValue(Promise.resolve([]));
|
|
30
29
|
});
|
|
31
30
|
|
|
32
31
|
describe('initialization', () => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { get, isEmpty } from 'lodash';
|
|
2
|
-
import { $q } from 'ngimport';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import type { Option } from 'react-select';
|
|
5
4
|
import Select, { Creatable } from 'react-select';
|
|
@@ -247,7 +246,7 @@ export class ManifestSelector extends React.Component<IManifestSelectorProps, IM
|
|
|
247
246
|
|
|
248
247
|
private search = (kind: string, namespace: string, account: string): PromiseLike<string[]> => {
|
|
249
248
|
if (this.isExpression(account)) {
|
|
250
|
-
return
|
|
249
|
+
return Promise.resolve([]);
|
|
251
250
|
}
|
|
252
251
|
return ManifestKindSearchService.search(kind, namespace, account).then((results) =>
|
|
253
252
|
results.map((result) => result.name).sort(),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { IQService } from 'angular';
|
|
2
1
|
import { module } from 'angular';
|
|
3
2
|
|
|
4
3
|
import type { Application } from '@spinnaker/core';
|
|
@@ -13,27 +12,24 @@ type ApiK8sResource = any;
|
|
|
13
12
|
const fetchK8sResources = (application: Application): PromiseLike<ApiK8sResource> =>
|
|
14
13
|
REST('applications').path(application.name, 'rawResources').get();
|
|
15
14
|
|
|
16
|
-
const formatK8sResources = (
|
|
17
|
-
|
|
15
|
+
const formatK8sResources = (_: Application, result: ApiK8sResource): PromiseLike<ApiK8sResource> =>
|
|
16
|
+
Promise.resolve(result);
|
|
18
17
|
|
|
19
|
-
module(KUBERNETS_RAW_RESOURCE_DATA_SOURCE, []).run(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
38
|
-
},
|
|
39
|
-
]);
|
|
18
|
+
module(KUBERNETS_RAW_RESOURCE_DATA_SOURCE, []).run(() => {
|
|
19
|
+
ApplicationDataSourceRegistry.registerDataSource({
|
|
20
|
+
key: KUBERNETS_RAW_RESOURCE_DATA_SOURCE_KEY,
|
|
21
|
+
label: 'Kubernetes',
|
|
22
|
+
category: INFRASTRUCTURE_KEY,
|
|
23
|
+
sref: KUBERNETS_RAW_RESOURCE_DATA_SOURCE_SREF,
|
|
24
|
+
primary: true,
|
|
25
|
+
icon: 'fas fa-xs fa-fw fa-th-large',
|
|
26
|
+
iconName: 'spMenuK8s',
|
|
27
|
+
loader: fetchK8sResources,
|
|
28
|
+
onLoad: formatK8sResources,
|
|
29
|
+
providerField: 'cloudProvider',
|
|
30
|
+
credentialsField: 'account',
|
|
31
|
+
regionField: 'region',
|
|
32
|
+
description: 'Collections of kubernetes resources',
|
|
33
|
+
defaultData: [],
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import type { IQService } from 'angular';
|
|
2
1
|
import { module } from 'angular';
|
|
3
2
|
|
|
4
3
|
import type { ISecurityGroup } from '@spinnaker/core';
|
|
5
4
|
|
|
6
5
|
class KubernetesV2SecurityGroupTransformer {
|
|
7
|
-
public static $inject = ['$q'];
|
|
8
|
-
constructor(private $q: IQService) {}
|
|
9
|
-
|
|
10
6
|
public normalizeSecurityGroup(securityGroup: ISecurityGroup): PromiseLike<ISecurityGroup> {
|
|
11
|
-
return
|
|
7
|
+
return Promise.resolve(securityGroup);
|
|
12
8
|
}
|
|
13
9
|
}
|
|
14
10
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const KUBERNETES_LOAD_BALANCER_DETAILS_CTRL = "spinnaker.kubernetes.loadBalancerDetails.controller";
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { StateService } from '@uirouter/angularjs';
|
|
2
|
-
import type { IController, IScope } from 'angular';
|
|
3
|
-
import { module } from 'angular';
|
|
4
|
-
import type { IModalService } from 'angular-ui-bootstrap';
|
|
5
|
-
|
|
6
|
-
import type { Application, ILoadBalancer, IManifest } from '@spinnaker/core';
|
|
7
|
-
import { ManifestReader, SETTINGS } from '@spinnaker/core';
|
|
8
|
-
|
|
9
|
-
import type { IKubernetesLoadBalancer } from '../../interfaces';
|
|
10
|
-
import { KubernetesManifestCommandBuilder } from '../../manifest/manifestCommandBuilder.service';
|
|
11
|
-
import { ManifestWizard } from '../../manifest/wizard/ManifestWizard';
|
|
12
|
-
|
|
13
|
-
interface ILoadBalancerFromStateParams {
|
|
14
|
-
accountId: string;
|
|
15
|
-
region: string;
|
|
16
|
-
name: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
class KubernetesLoadBalancerDetailsController implements IController {
|
|
20
|
-
public state = { loading: true };
|
|
21
|
-
public manifest: IManifest;
|
|
22
|
-
public loadBalancer: IKubernetesLoadBalancer;
|
|
23
|
-
|
|
24
|
-
public static $inject = ['$uibModal', '$state', '$scope', 'loadBalancer', 'app'];
|
|
25
|
-
constructor(
|
|
26
|
-
private $uibModal: IModalService,
|
|
27
|
-
private $state: StateService,
|
|
28
|
-
private $scope: IScope,
|
|
29
|
-
loadBalancer: ILoadBalancerFromStateParams,
|
|
30
|
-
private app: Application,
|
|
31
|
-
) {
|
|
32
|
-
const dataSource = this.app.getDataSource('loadBalancers');
|
|
33
|
-
dataSource
|
|
34
|
-
.ready()
|
|
35
|
-
.then(() => {
|
|
36
|
-
this.extractLoadBalancer(loadBalancer);
|
|
37
|
-
this.$scope.isDisabled = !SETTINGS.kubernetesAdHocInfraWritesEnabled;
|
|
38
|
-
dataSource.onRefresh(this.$scope, () => this.extractLoadBalancer(loadBalancer));
|
|
39
|
-
})
|
|
40
|
-
.catch(() => this.autoClose());
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public deleteLoadBalancer(): void {
|
|
44
|
-
this.$uibModal.open({
|
|
45
|
-
templateUrl: require('../../manifest/delete/delete.html'),
|
|
46
|
-
controller: 'kubernetesV2ManifestDeleteCtrl',
|
|
47
|
-
controllerAs: 'ctrl',
|
|
48
|
-
resolve: {
|
|
49
|
-
coordinates: {
|
|
50
|
-
name: this.loadBalancer.name,
|
|
51
|
-
namespace: this.loadBalancer.namespace,
|
|
52
|
-
account: this.loadBalancer.account,
|
|
53
|
-
},
|
|
54
|
-
application: this.app,
|
|
55
|
-
manifestController: (): string => null,
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public editLoadBalancer(): void {
|
|
61
|
-
KubernetesManifestCommandBuilder.buildNewManifestCommand(
|
|
62
|
-
this.app,
|
|
63
|
-
this.manifest.manifest,
|
|
64
|
-
this.loadBalancer.moniker,
|
|
65
|
-
this.loadBalancer.account,
|
|
66
|
-
).then((builtCommand) => {
|
|
67
|
-
ManifestWizard.show({ title: 'Edit Manifest', application: this.app, command: builtCommand });
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private extractLoadBalancer({ accountId, name, region }: ILoadBalancerFromStateParams): void {
|
|
72
|
-
const loadBalancer = this.app.getDataSource('loadBalancers').data.find((test: ILoadBalancer) => {
|
|
73
|
-
return test.name === name && test.account === accountId && test.region === region;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
if (!loadBalancer) {
|
|
77
|
-
return this.autoClose();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
ManifestReader.getManifest(accountId, region, name).then((manifest: IManifest) => {
|
|
81
|
-
this.manifest = manifest;
|
|
82
|
-
this.loadBalancer = loadBalancer;
|
|
83
|
-
this.state.loading = false;
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private autoClose(): void {
|
|
88
|
-
if (this.$scope.$$destroyed) {
|
|
89
|
-
return;
|
|
90
|
-
} else {
|
|
91
|
-
this.$state.params.allowModalToStayOpen = true;
|
|
92
|
-
this.$state.go('^', null, { location: 'replace' });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export const KUBERNETES_LOAD_BALANCER_DETAILS_CTRL = 'spinnaker.kubernetes.loadBalancerDetails.controller';
|
|
98
|
-
module(KUBERNETES_LOAD_BALANCER_DETAILS_CTRL, []).controller(
|
|
99
|
-
'kubernetesV2LoadBalancerDetailsCtrl',
|
|
100
|
-
KubernetesLoadBalancerDetailsController,
|
|
101
|
-
);
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
<div class="details-panel">
|
|
2
|
-
<div ng-if="ctrl.state.loading" class="header">
|
|
3
|
-
<div class="close-button">
|
|
4
|
-
<a class="btn btn-link" ui-sref="^">
|
|
5
|
-
<span class="glyphicon glyphicon-remove"></span>
|
|
6
|
-
</a>
|
|
7
|
-
</div>
|
|
8
|
-
<h4 class="text-center">
|
|
9
|
-
<span us-spinner="{radius:20, width:6, length: 12}"></span>
|
|
10
|
-
</h4>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
<div class="header" ng-if="!ctrl.state.loading">
|
|
14
|
-
<div class="close-button">
|
|
15
|
-
<a class="btn btn-link" ui-sref="^">
|
|
16
|
-
<span class="glyphicon glyphicon-remove"></span>
|
|
17
|
-
</a>
|
|
18
|
-
</div>
|
|
19
|
-
<div class="header-text horizontal middle">
|
|
20
|
-
<cloud-provider-logo
|
|
21
|
-
provider="ctrl.loadBalancer.cloudProvider"
|
|
22
|
-
height="'36px'"
|
|
23
|
-
width="'36px'"
|
|
24
|
-
></cloud-provider-logo>
|
|
25
|
-
<h3 class="horizontal middle space-between flex-1" select-on-dbl-click>
|
|
26
|
-
{{ctrl.loadBalancer.displayName}}
|
|
27
|
-
<render-if-feature feature="entityTags">
|
|
28
|
-
<entity-notifications
|
|
29
|
-
ng-if="!state.loading"
|
|
30
|
-
entity="ctrl.loadBalancer"
|
|
31
|
-
application="ctrl.app"
|
|
32
|
-
placement="bottom"
|
|
33
|
-
h-offset-percent="90%"
|
|
34
|
-
entity-type="loadBalancer"
|
|
35
|
-
page-location="details"
|
|
36
|
-
on-update="ctrl.app.loadBalancers.refresh()"
|
|
37
|
-
></entity-notifications>
|
|
38
|
-
</render-if-feature>
|
|
39
|
-
</h3>
|
|
40
|
-
</div>
|
|
41
|
-
<div class="actions">
|
|
42
|
-
<div class="dropdown" uib-dropdown dropdown-append-to-body>
|
|
43
|
-
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle ng-hide="isDisabled">
|
|
44
|
-
{{ctrl.loadBalancer.kind | robotToHuman}} Actions <span class="caret"></span>
|
|
45
|
-
</button>
|
|
46
|
-
<ul class="dropdown-menu" uib-dropdown-menu role="menu">
|
|
47
|
-
<li>
|
|
48
|
-
<a href ng-click="ctrl.deleteLoadBalancer()">Delete</a>
|
|
49
|
-
</li>
|
|
50
|
-
<li>
|
|
51
|
-
<a href ng-click="ctrl.editLoadBalancer()">Edit</a>
|
|
52
|
-
</li>
|
|
53
|
-
<render-if-feature feature="entityTags">
|
|
54
|
-
<add-entity-tag-links
|
|
55
|
-
component="ctrl.loadBalancer"
|
|
56
|
-
application="ctrl.app"
|
|
57
|
-
entity-type="loadBalancer"
|
|
58
|
-
on-update="ctrl.app.loadBalancers.refresh"
|
|
59
|
-
></add-entity-tag-links>
|
|
60
|
-
</render-if-feature>
|
|
61
|
-
</ul>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
|
|
66
|
-
<div ng-if="!ctrl.state.loading" class="content">
|
|
67
|
-
<collapsible-section heading="Information" expanded="true">
|
|
68
|
-
<dl class="dl-horizontal dl-narrow">
|
|
69
|
-
<dt>Created</dt>
|
|
70
|
-
<dd>{{ctrl.loadBalancer.createdTime | timestamp}}</dd>
|
|
71
|
-
<dt>Account</dt>
|
|
72
|
-
<dd><account-tag account="ctrl.loadBalancer.account" pad="right"></account-tag></dd>
|
|
73
|
-
<dt>Namespace</dt>
|
|
74
|
-
<dd>{{ctrl.loadBalancer.namespace}}</dd>
|
|
75
|
-
<dt>Kind</dt>
|
|
76
|
-
<dd>{{ctrl.loadBalancer.kind}}</dd>
|
|
77
|
-
<dt>Service Type</dt>
|
|
78
|
-
<dd>{{ctrl.manifest.manifest.spec.type}}</dd>
|
|
79
|
-
<dt>Sess. Affinity</dt>
|
|
80
|
-
<dd>{{ctrl.manifest.manifest.spec.sessionAffinity}}</dd>
|
|
81
|
-
</dl>
|
|
82
|
-
</collapsible-section>
|
|
83
|
-
<collapsible-section heading="Status" expanded="true">
|
|
84
|
-
<dl class="dl-horizontal dl-narrow">
|
|
85
|
-
<div ng-if="!ctrl.loadBalancer.serverGroups.length">
|
|
86
|
-
No workloads associated with this {{ctrl.loadBalancer.kind | robotToHuman}}.
|
|
87
|
-
</div>
|
|
88
|
-
<dt ng-if="ctrl.loadBalancer.serverGroups.length">Workloads</dt>
|
|
89
|
-
<dd ng-if="ctrl.loadBalancer.serverGroups.length">
|
|
90
|
-
<ul>
|
|
91
|
-
<li ng-repeat="serverGroup in ctrl.loadBalancer.serverGroups | orderBy: ['isDisabled', '-name']">
|
|
92
|
-
<a
|
|
93
|
-
ui-sref="^.serverGroup({region: serverGroup.region,
|
|
94
|
-
accountId: serverGroup.account,
|
|
95
|
-
serverGroup: serverGroup.name,
|
|
96
|
-
provider: 'kubernetes'})"
|
|
97
|
-
>
|
|
98
|
-
{{serverGroup.name}}
|
|
99
|
-
</a>
|
|
100
|
-
</li>
|
|
101
|
-
</ul>
|
|
102
|
-
</dd>
|
|
103
|
-
<div ng-if="ctrl.loadBalancer.serverGroups.length">
|
|
104
|
-
<dt>Pod status</dt>
|
|
105
|
-
<dd>
|
|
106
|
-
<health-counts class="pull-left" container="ctrl.loadBalancer.instanceCounts"></health-counts>
|
|
107
|
-
</dd>
|
|
108
|
-
</div>
|
|
109
|
-
<div ng-if="ctrl.manifest.manifest.spec.clusterIP">
|
|
110
|
-
<dt>Cluster IP</dt>
|
|
111
|
-
<dd>
|
|
112
|
-
<a target="_blank" href="//{{ctrl.manifest.manifest.spec.clusterIP}}">
|
|
113
|
-
{{ctrl.manifest.manifest.spec.clusterIP}}
|
|
114
|
-
</a>
|
|
115
|
-
<copy-to-clipboard
|
|
116
|
-
class="copy-to-clipboard copy-to-clipboard-sm"
|
|
117
|
-
text="ctrl.manifest.manifest.spec.clusterIP"
|
|
118
|
-
tool-tip="'Copy Cluster IP to clipboard'"
|
|
119
|
-
>
|
|
120
|
-
</copy-to-clipboard>
|
|
121
|
-
</dd>
|
|
122
|
-
</div>
|
|
123
|
-
<div ng-if="ctrl.manifest.manifest.spec.loadBalancerIP">
|
|
124
|
-
<dt>Load Balancer IP</dt>
|
|
125
|
-
<dd>
|
|
126
|
-
<a target="_blank" href="//{{ctrl.manifest.manifest.spec.loadBalancerIP}}">
|
|
127
|
-
{{ctrl.manifest.manifest.spec.loadBalancerIP}}
|
|
128
|
-
</a>
|
|
129
|
-
<copy-to-clipboard
|
|
130
|
-
class="copy-to-clipboard copy-to-clipboard-sm"
|
|
131
|
-
text="ctrl.manifest.manifest.spec.loadBalancerIP"
|
|
132
|
-
tool-tip="'Copy Load Balancer IP to clipboard'"
|
|
133
|
-
>
|
|
134
|
-
</copy-to-clipboard>
|
|
135
|
-
</dd>
|
|
136
|
-
</div>
|
|
137
|
-
<div ng-if="ctrl.manifest.manifest.spec.rules.length">
|
|
138
|
-
<dt>Host Rules</dt>
|
|
139
|
-
<dd ng-repeat="ingressRule in ctrl.manifest.manifest.spec.rules">
|
|
140
|
-
<a ng-if="ingressRule.host" target="_blank" href="//{{ingressRule.host}}"> {{ingressRule.host}} </a>
|
|
141
|
-
<copy-to-clipboard
|
|
142
|
-
ng-if="ingressRule.host"
|
|
143
|
-
class="copy-to-clipboard copy-to-clipboard-sm"
|
|
144
|
-
text="ingressRule.host"
|
|
145
|
-
tool-tip="'Copy ingress rule host to clipboard'"
|
|
146
|
-
>
|
|
147
|
-
</copy-to-clipboard>
|
|
148
|
-
</dd>
|
|
149
|
-
</div>
|
|
150
|
-
<div ng-if="ctrl.manifest.manifest.status.loadBalancer.ingress.length">
|
|
151
|
-
<dt>Ingress</dt>
|
|
152
|
-
<dd ng-repeat="ingress in ctrl.manifest.manifest.status.loadBalancer.ingress">
|
|
153
|
-
<a ng-if="ingress.hostname" target="_blank" href="//{{ingress.hostname}}"> {{ingress.hostname}} </a>
|
|
154
|
-
<copy-to-clipboard
|
|
155
|
-
ng-if="ingress.hostname"
|
|
156
|
-
class="copy-to-clipboard copy-to-clipboard-sm"
|
|
157
|
-
text="ingress.hostname"
|
|
158
|
-
tool-tip="'Copy Ingress hostname to clipboard'"
|
|
159
|
-
>
|
|
160
|
-
</copy-to-clipboard>
|
|
161
|
-
<a ng-if="ingress.ip" target="_blank" href="//{{ingress.ip}}"> {{ingress.ip}} </a>
|
|
162
|
-
<copy-to-clipboard
|
|
163
|
-
ng-if="ingress.ip"
|
|
164
|
-
class="copy-to-clipboard copy-to-clipboard-sm"
|
|
165
|
-
text="ingress.ip"
|
|
166
|
-
tool-tip="'Copy Ingress IP to clipboard'"
|
|
167
|
-
>
|
|
168
|
-
</copy-to-clipboard>
|
|
169
|
-
</dd>
|
|
170
|
-
</div>
|
|
171
|
-
</dl>
|
|
172
|
-
</collapsible-section>
|
|
173
|
-
|
|
174
|
-
<kubernetes-annotation-custom-sections
|
|
175
|
-
manifest="ctrl.manifest.manifest"
|
|
176
|
-
resource="ctrl.loadBalancer"
|
|
177
|
-
></kubernetes-annotation-custom-sections>
|
|
178
|
-
|
|
179
|
-
<collapsible-section heading="Events" expanded="true">
|
|
180
|
-
<kubernetes-manifest-events manifest="ctrl.manifest"></kubernetes-manifest-events>
|
|
181
|
-
</collapsible-section>
|
|
182
|
-
|
|
183
|
-
<collapsible-section heading="Labels" expanded="true">
|
|
184
|
-
<kubernetes-manifest-labels manifest="ctrl.manifest.manifest"></kubernetes-manifest-labels>
|
|
185
|
-
</collapsible-section>
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|