@rancher/shell 0.3.12 → 0.3.14
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/assets/translations/en-us.yaml +6 -0
- package/components/HarvesterServiceAddOnConfig.vue +115 -1
- package/config/labels-annotations.js +1 -0
- package/creators/app/files/.gitignore +0 -3
- package/edit/__tests__/namespace.test.ts +46 -0
- package/edit/namespace.vue +1 -1
- package/package.json +1 -1
- package/scripts/extension/publish +3 -1
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { mapGetters } from 'vuex';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
|
|
2
5
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
3
6
|
import { _CREATE } from '@shell/config/query-params';
|
|
4
7
|
import { get } from '@shell/utils/object';
|
|
5
8
|
import { HCI as HCI_LABELS_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
9
|
+
import { SERVICE } from '@shell/config/types';
|
|
10
|
+
import { allHash } from '@shell/utils/promise';
|
|
6
11
|
|
|
7
12
|
const HARVESTER_ADD_ON_CONFIG = [{
|
|
8
13
|
variableName: 'ipam',
|
|
9
14
|
key: HCI_LABELS_ANNOTATIONS.CLOUD_PROVIDER_IPAM,
|
|
10
15
|
default: 'dhcp'
|
|
16
|
+
}, {
|
|
17
|
+
variableName: 'sharedService',
|
|
18
|
+
key: HCI_LABELS_ANNOTATIONS.PRIMARY_SERVICE,
|
|
19
|
+
default: ''
|
|
11
20
|
}];
|
|
12
21
|
|
|
13
22
|
export default {
|
|
@@ -38,6 +47,19 @@ export default {
|
|
|
38
47
|
}
|
|
39
48
|
},
|
|
40
49
|
|
|
50
|
+
async fetch() {
|
|
51
|
+
const inStore = this.$store.getters['currentProduct'].inStore;
|
|
52
|
+
|
|
53
|
+
const hash = {
|
|
54
|
+
rke2Versions: this.$store.dispatch('management/request', { url: '/v1-rke2-release/releases' }),
|
|
55
|
+
services: this.$store.dispatch(`${ inStore }/findAll`, { type: SERVICE }),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const res = await allHash(hash);
|
|
59
|
+
|
|
60
|
+
this.rke2Versions = res.rke2Versions;
|
|
61
|
+
},
|
|
62
|
+
|
|
41
63
|
data() {
|
|
42
64
|
const harvesterAddOnConfig = {};
|
|
43
65
|
|
|
@@ -45,10 +67,24 @@ export default {
|
|
|
45
67
|
harvesterAddOnConfig[c.variableName] = this.value.metadata.annotations[c.key] || c.default;
|
|
46
68
|
});
|
|
47
69
|
|
|
48
|
-
|
|
70
|
+
let showShareIP;
|
|
71
|
+
|
|
72
|
+
if (this.value.metadata.annotations[HCI_LABELS_ANNOTATIONS.PRIMARY_SERVICE]) {
|
|
73
|
+
showShareIP = true;
|
|
74
|
+
} else {
|
|
75
|
+
showShareIP = false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...harvesterAddOnConfig,
|
|
80
|
+
showShareIP,
|
|
81
|
+
rke2Versions: {},
|
|
82
|
+
};
|
|
49
83
|
},
|
|
50
84
|
|
|
51
85
|
computed: {
|
|
86
|
+
...mapGetters(['allowedNamespaces', 'namespaces', 'currentCluster']),
|
|
87
|
+
|
|
52
88
|
ipamOptions() {
|
|
53
89
|
return [{
|
|
54
90
|
label: 'DHCP',
|
|
@@ -64,13 +100,71 @@ export default {
|
|
|
64
100
|
|
|
65
101
|
return ports.filter(p => p.port && p.protocol === 'TCP').map(p => p.port) || [];
|
|
66
102
|
},
|
|
103
|
+
|
|
104
|
+
serviceOptions() {
|
|
105
|
+
const inStore = this.$store.getters['currentProduct'].inStore;
|
|
106
|
+
const services = this.$store.getters[`${ inStore }/all`](SERVICE);
|
|
107
|
+
|
|
108
|
+
const namespaces = this.namespaces();
|
|
109
|
+
|
|
110
|
+
const out = services.filter((s) => {
|
|
111
|
+
const ingress = s?.status?.loadBalancer?.ingress || [];
|
|
112
|
+
|
|
113
|
+
return ingress.length > 0 &&
|
|
114
|
+
!s?.metadata?.annotations?.['cloudprovider.harvesterhci.io/primary-service'] &&
|
|
115
|
+
s.spec?.type === 'LoadBalancer' &&
|
|
116
|
+
namespaces[s.metadata.namespace];
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return out.map(s => s.id);
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
shareIPEnabled() {
|
|
123
|
+
const kubernetesVersion = this.currentCluster.kubernetesVersion || '';
|
|
124
|
+
const kubernetesVersionExtension = this.currentCluster.kubernetesVersionExtension;
|
|
125
|
+
|
|
126
|
+
if (kubernetesVersionExtension.startsWith('+rke2')) {
|
|
127
|
+
const charts = ((this.rke2Versions?.data || []).find(v => v.id === kubernetesVersion) || {}).charts;
|
|
128
|
+
let ccmVersion = charts?.['harvester-cloud-provider']?.version || '';
|
|
129
|
+
|
|
130
|
+
if (ccmVersion.endsWith('00')) {
|
|
131
|
+
ccmVersion = ccmVersion.slice(0, -2);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return semver.satisfies(ccmVersion, '>=0.2.0');
|
|
135
|
+
} else {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
67
139
|
},
|
|
68
140
|
|
|
69
141
|
methods: {
|
|
70
142
|
willSave() {
|
|
143
|
+
const errors = [];
|
|
144
|
+
|
|
145
|
+
if (this.showShareIP) {
|
|
146
|
+
if (!this.sharedService) {
|
|
147
|
+
errors.push(this.t('validation.required', { key: this.t('servicesPage.harvester.shareIP.label') }, true));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (errors.length > 0) {
|
|
152
|
+
return Promise.reject(errors);
|
|
153
|
+
}
|
|
154
|
+
|
|
71
155
|
HARVESTER_ADD_ON_CONFIG.forEach((c) => {
|
|
72
156
|
this.value.metadata.annotations[c.key] = String(get(this, c.variableName));
|
|
73
157
|
});
|
|
158
|
+
|
|
159
|
+
if (this.showShareIP) {
|
|
160
|
+
delete this.value.metadata.annotations[HCI_LABELS_ANNOTATIONS.CLOUD_PROVIDER_IPAM];
|
|
161
|
+
} else {
|
|
162
|
+
delete this.value.metadata.annotations[HCI_LABELS_ANNOTATIONS.PRIMARY_SERVICE];
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
toggleShareIP() {
|
|
167
|
+
this.showShareIP = !this.showShareIP;
|
|
74
168
|
},
|
|
75
169
|
},
|
|
76
170
|
};
|
|
@@ -81,11 +175,31 @@ export default {
|
|
|
81
175
|
<div class="row mt-30">
|
|
82
176
|
<div class="col span-6">
|
|
83
177
|
<LabeledSelect
|
|
178
|
+
v-if="showShareIP"
|
|
179
|
+
v-model="sharedService"
|
|
180
|
+
:mode="mode"
|
|
181
|
+
:options="serviceOptions"
|
|
182
|
+
:label="t('servicesPage.harvester.shareIP.label')"
|
|
183
|
+
:disabled="mode === 'edit'"
|
|
184
|
+
/>
|
|
185
|
+
<LabeledSelect
|
|
186
|
+
v-else
|
|
84
187
|
v-model="ipam"
|
|
85
188
|
:mode="mode"
|
|
86
189
|
:options="ipamOptions"
|
|
87
190
|
:label="t('servicesPage.harvester.ipam.label')"
|
|
88
191
|
/>
|
|
192
|
+
<div
|
|
193
|
+
v-if="mode === 'create'"
|
|
194
|
+
class="mt-10"
|
|
195
|
+
>
|
|
196
|
+
<a
|
|
197
|
+
role="button"
|
|
198
|
+
@click="toggleShareIP"
|
|
199
|
+
>
|
|
200
|
+
{{ showShareIP ? t('servicesPage.harvester.useIpam.label') : t('servicesPage.harvester.useShareIP.label') }}
|
|
201
|
+
</a>
|
|
202
|
+
</div>
|
|
89
203
|
</div>
|
|
90
204
|
</div>
|
|
91
205
|
</div>
|
|
@@ -138,6 +138,7 @@ export const HCI = {
|
|
|
138
138
|
CLOUD_PROVIDER_NAMESPACE: 'cloudprovider.harvesterhci.io/namespace',
|
|
139
139
|
CLOUD_PROVIDER_NETWORK: 'cloudprovider.harvesterhci.io/network',
|
|
140
140
|
CLOUD_PROVIDER_PROJECT: 'cloudprovider.harvesterhci.io/project',
|
|
141
|
+
PRIMARY_SERVICE: 'cloudprovider.harvesterhci.io/primary-service',
|
|
141
142
|
};
|
|
142
143
|
|
|
143
144
|
// Annotations that can be on management.cattle.io.cluster to configure a custom badge
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import Namespace from '@shell/edit/namespace.vue';
|
|
3
|
+
import { DefaultProps } from 'vue/types/options';
|
|
4
|
+
import { ExtendedVue, Vue } from 'vue/types/vue';
|
|
5
|
+
|
|
6
|
+
describe('view Namespace should', () => {
|
|
7
|
+
it('retrieve resource limits from project', () => {
|
|
8
|
+
const name = 'my project name';
|
|
9
|
+
const limits = 'whatever';
|
|
10
|
+
const project = { id: name, spec: { containerDefaultResourceLimit: limits } };
|
|
11
|
+
const wrapper = mount(Namespace as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
|
|
12
|
+
propsData: {
|
|
13
|
+
value: {
|
|
14
|
+
metadata: { labels: { 'field.cattle.io/projectId': name } },
|
|
15
|
+
annotations: { 'field.cattle.io/containerDefaultResourceLimit': undefined },
|
|
16
|
+
listLocation: {},
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
mocks: {
|
|
20
|
+
$fetchState: {},
|
|
21
|
+
$route: {
|
|
22
|
+
name: 'anything',
|
|
23
|
+
query: { AS: 'yaml' }
|
|
24
|
+
},
|
|
25
|
+
$router: { applyQuery: {} },
|
|
26
|
+
$store: {
|
|
27
|
+
getters: {
|
|
28
|
+
'i18n/t': jest.fn(),
|
|
29
|
+
'management/all': () => ([project]),
|
|
30
|
+
currentProduct: jest.fn(),
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
stubs: {
|
|
35
|
+
CruResource: { template: '<div><slot></slot></div>' }, // Required to render the slot content
|
|
36
|
+
ContainerResourceLimit: { template: '<div data-testid="limits"></div>' }, // Ensure value to be added to component
|
|
37
|
+
NameNsDescription: true,
|
|
38
|
+
Tab: true,
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const limitsUi = wrapper.find('[data-testid="limits"]');
|
|
43
|
+
|
|
44
|
+
expect(limitsUi.vm.$attrs.value).toStrictEqual(limits);
|
|
45
|
+
});
|
|
46
|
+
});
|
package/edit/namespace.vue
CHANGED
|
@@ -57,7 +57,7 @@ export default {
|
|
|
57
57
|
project: null,
|
|
58
58
|
projects: null,
|
|
59
59
|
viewMode: _VIEW,
|
|
60
|
-
containerResourceLimits: this.value.annotations[CONTAINER_DEFAULT_RESOURCE_LIMIT] || this.getDefaultContainerResourceLimits(projectName),
|
|
60
|
+
containerResourceLimits: this.value.annotations?.[CONTAINER_DEFAULT_RESOURCE_LIMIT] || this.getDefaultContainerResourceLimits(projectName),
|
|
61
61
|
projectName,
|
|
62
62
|
HARVESTER_TYPES,
|
|
63
63
|
RANCHER_TYPES,
|
package/package.json
CHANGED
|
@@ -280,7 +280,7 @@ for d in pkg/*/ ; do
|
|
|
280
280
|
fi
|
|
281
281
|
|
|
282
282
|
# Base URL referencing assets directly from GitHub
|
|
283
|
-
BASE_URL="assets
|
|
283
|
+
BASE_URL="assets/"
|
|
284
284
|
|
|
285
285
|
# Relative URL references assets within the container deployment
|
|
286
286
|
RELATIVE_URL="plugin/"
|
|
@@ -320,6 +320,8 @@ if [ "${GITHUB_BUILD}" == "false" ]; then
|
|
|
320
320
|
|
|
321
321
|
# Build the docker image
|
|
322
322
|
${SCRIPT_DIR}/bundle ${BASE_EXT} ${EXT_VERSION} ${REGISTRY} ${REGISTRY_ORG} ${IMAGE_PREFIX} ${PUSH}
|
|
323
|
+
else
|
|
324
|
+
rm -rf ${CHART_TEMPLATE}
|
|
323
325
|
fi
|
|
324
326
|
|
|
325
327
|
if [ "${GITHUB_BUILD}" == "true" ] && [ -f ${ROOT_INDEX} ]; then
|