@rancher/shell 0.3.5 → 0.3.7
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/images/providers/outscale.svg +19 -0
- package/assets/styles/base/_basic.scss +18 -0
- package/assets/styles/base/_mixins.scss +0 -11
- package/assets/styles/base/_variables.scss +2 -4
- package/assets/styles/global/_button.scss +12 -2
- package/assets/translations/en-us.yaml +35 -1
- package/assets/translations/zh-hans.yaml +30 -10
- package/chart/gatekeeper.vue +3 -2
- package/chart/istio.vue +29 -3
- package/components/BrandImage.vue +1 -4
- package/components/Carousel.vue +85 -37
- package/components/EtcdInfoBanner.vue +7 -3
- package/components/ExplorerMembers.vue +100 -5
- package/components/ExplorerProjectsNamespaces.vue +32 -2
- package/components/GrafanaDashboard.vue +9 -2
- package/components/SortableTable/index.vue +23 -11
- package/components/SortableTable/selection.js +58 -50
- package/components/Wizard.vue +4 -2
- package/components/auth/AuthBanner.vue +6 -0
- package/components/auth/RoleDetailEdit.vue +2 -2
- package/components/form/HookOption.vue +14 -10
- package/components/form/Labels.vue +32 -27
- package/components/form/MatchExpressions.vue +2 -2
- package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +46 -21
- package/components/form/Tolerations.vue +4 -1
- package/components/form/ValueFromResource.vue +14 -9
- package/components/form/WorkloadPorts.vue +2 -2
- package/components/form/__tests__/NameNsDescription.ts +27 -0
- package/components/formatter/WorkloadHealthScale.vue +8 -2
- package/components/nav/NamespaceFilter.vue +8 -0
- package/{nuxt/components → components/nuxt}/nuxt.js +1 -1
- package/{nuxt → config}/middleware.js +8 -8
- package/config/product/explorer.js +24 -3
- package/config/query-params.js +1 -0
- package/config/router.js +1 -1
- package/{nuxt → config}/store.js +82 -79
- package/config/table-headers.js +46 -12
- package/config/types.js +7 -0
- package/core/plugin.ts +4 -2
- package/core/types.ts +258 -1
- package/creators/app/files/tsconfig.json +0 -1
- package/creators/app/files/vue.config.js +0 -1
- package/creators/pkg/files/.github/workflows/build-extension.yml +3 -4
- package/creators/pkg/files/tsconfig.json +0 -1
- package/creators/pkg/pkg.package.json +3 -3
- package/detail/constraints.gatekeeper.sh.constraint.vue +14 -7
- package/detail/fleet.cattle.io.clustergroup.vue +7 -1
- package/edit/auth/ldap/config.vue +21 -1
- package/edit/auth/saml.vue +132 -37
- package/edit/fleet.cattle.io.gitrepo.vue +16 -1
- package/edit/logging.banzaicloud.io.output/index.vue +18 -5
- package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
- package/edit/namespace.vue +12 -8
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -4
- package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
- package/edit/provisioning.cattle.io.cluster/rke2.vue +96 -18
- package/edit/workload/mixins/workload.js +6 -7
- package/edit/workload/storage/Mount.vue +3 -3
- package/initialize/App.js +206 -0
- package/{nuxt → initialize}/client.js +406 -360
- package/{nuxt → initialize}/index.js +21 -22
- package/layouts/standalone.vue +13 -0
- package/list/catalog.cattle.io.clusterrepo.vue +1 -0
- package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
- package/list/workload.vue +6 -4
- package/mixins/chart.js +29 -1
- package/mixins/fetch.client.js +95 -0
- package/{nuxt/mixins → mixins}/fetch.server.js +30 -26
- package/mixins/labeled-form-element.ts +2 -2
- package/models/constraints.gatekeeper.sh.constraint.js +37 -0
- package/models/pod.js +4 -0
- package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
- package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
- package/package.json +9 -13
- package/pages/c/_cluster/apps/charts/install.vue +61 -39
- package/pages/diagnostic.vue +32 -25
- package/pages/rio/mesh.vue +1 -2
- package/pkg/tsconfig.json +0 -1
- package/plugins/clean-html-directive.js +3 -0
- package/plugins/dashboard-store/index.js +1 -1
- package/plugins/plugin.js +0 -14
- package/plugins/portal-vue.js +4 -0
- package/rancher-components/components/Banner/Banner.test.ts +3 -5
- package/rancher-components/components/Banner/Banner.vue +1 -0
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
- package/scripts/extension/publish +42 -23
- package/scripts/serve-pkgs +6 -2
- package/store/type-map.js +1 -1
- package/tsconfig.json +0 -1
- package/types/rancher/index.d.ts +2 -0
- package/types/shell/index.d.ts +353 -284
- package/utils/__tests__/grafana.test.ts +44 -0
- package/utils/axios.js +190 -0
- package/{nuxt → utils}/cookie-universal-nuxt.js +7 -6
- package/utils/dom.js +15 -0
- package/utils/gc/gc.ts +1 -1
- package/utils/grafana.js +35 -16
- package/{nuxt/utils.js → utils/nuxt.js} +265 -236
- package/utils/router.scrollBehavior.js +1 -1
- package/vue.config.js +30 -19
- package/nuxt/App.js +0 -210
- package/nuxt/axios.js +0 -186
- package/nuxt/empty.js +0 -1
- package/nuxt/jsonp.js +0 -82
- package/nuxt/loading.html +0 -39
- package/nuxt/mixins/fetch.client.js +0 -90
- package/nuxt/portal-vue.js +0 -4
- package/nuxt/server.js +0 -312
- package/nuxt/views/app.template.html +0 -9
- package/nuxt/views/error.html +0 -23
- package/plugins/dashboard-store/extensions.js +0 -22
- /package/{nuxt/components → components/nuxt}/nuxt-build-indicator.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-child.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-error.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.client.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.server.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-loading.vue +0 -0
package/core/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ProductFunction } from './plugin';
|
|
1
2
|
import { RouteConfig } from 'vue-router';
|
|
2
3
|
|
|
3
4
|
// package.json metadata
|
|
@@ -136,6 +137,255 @@ export type LocationConfig = {
|
|
|
136
137
|
mode?: string[]
|
|
137
138
|
};
|
|
138
139
|
|
|
140
|
+
export interface ProductOptions {
|
|
141
|
+
/**
|
|
142
|
+
* The category this product belongs under. i.e. 'config'
|
|
143
|
+
*/
|
|
144
|
+
category?: string;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Hide the Copy KubeConfig button in the header
|
|
148
|
+
*/
|
|
149
|
+
hideCopyConfig?: boolean;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Hide the Download KubeConfig button in the header
|
|
153
|
+
*/
|
|
154
|
+
hideKubeConfig?: boolean;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Hide the Kubectl Shell button in the header
|
|
158
|
+
*/
|
|
159
|
+
hideKubeShell?: boolean;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Hide the Namespace location
|
|
163
|
+
*/
|
|
164
|
+
hideNamespaceLocation?: boolean;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Hide the system resources
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
hideSystemResources?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* The icon that should be displayed beside this item in the navigation.
|
|
173
|
+
*/
|
|
174
|
+
icon?: string,
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Only load the product if the feature is present
|
|
178
|
+
*/
|
|
179
|
+
ifFeature?: string | RegExp;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Only load the product if the type is present
|
|
183
|
+
*/
|
|
184
|
+
ifHave?: string;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Only load the product if the group is present
|
|
188
|
+
*/
|
|
189
|
+
ifHaveGroup?: string | RegExp;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Only load the product if the type is present
|
|
193
|
+
*/
|
|
194
|
+
ifHaveType?: string | RegExp;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The vuex store that this product should use by default i.e. 'management'
|
|
198
|
+
*/
|
|
199
|
+
inStore?: string;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Show the cluster switcher in the navigation
|
|
203
|
+
*/
|
|
204
|
+
showClusterSwitcher?: boolean;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Show the namespace filter in the header
|
|
208
|
+
*/
|
|
209
|
+
showNamespaceFilter?: boolean;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* A number used to determine where in navigation this item will be placed. The highest number will be at the top of the list.
|
|
213
|
+
*/
|
|
214
|
+
weight?: number;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Leaving these here for completeness but I don't think these should be advertised as useable to plugin creators.
|
|
218
|
+
*/
|
|
219
|
+
// ifHaveVerb: string | RegExp;
|
|
220
|
+
// removable: string;
|
|
221
|
+
// showWorkspaceSwitcher: boolean;
|
|
222
|
+
// supportRoute: string;
|
|
223
|
+
// to: string;
|
|
224
|
+
// typeStoreMap: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface HeaderOptions {
|
|
228
|
+
/**
|
|
229
|
+
* Name of the header. This should be unique.
|
|
230
|
+
*/
|
|
231
|
+
name?: string;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* A translation key where the resulting string will show in the table column
|
|
235
|
+
*/
|
|
236
|
+
labelKey?: string;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* A string which represents the path to access the value from the row object i.e. `row.meta.value`.
|
|
240
|
+
*/
|
|
241
|
+
value?: string;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* A string which represents the path to access the value from the row object which we'll use to sort i.e. `row.meta.value`
|
|
245
|
+
*/
|
|
246
|
+
sort?: string;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* A string which represents the path to access the value from the row object which we'll use to search i.e. `row.meta.value`
|
|
250
|
+
*/
|
|
251
|
+
search?: string;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Number of pixels the column should be in the table
|
|
255
|
+
*/
|
|
256
|
+
width?: number;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* The name of a custom formatter. The available formatters can bee seen in `@rancher/shell/components/formatter`
|
|
260
|
+
*/
|
|
261
|
+
formatter?: string;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* These options are dependent on the formatter that's chosen. Examples can be seen in `@rancher/shell/components/formatter` and `@rancher/shell/config/table-headers`
|
|
265
|
+
*/
|
|
266
|
+
formatterOpts?: any;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Provide a function which accets a row and returns the value that should be displayed in the column
|
|
270
|
+
* @param row This can be any value which represents the row
|
|
271
|
+
* @returns Can return {@link string | number | null | undefined} to display in the column
|
|
272
|
+
*/
|
|
273
|
+
getValue?: (row: any) => string | number | null | undefined;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface ConfigureTypeOptions {
|
|
277
|
+
/**
|
|
278
|
+
* The resource can edit/show yaml
|
|
279
|
+
*/
|
|
280
|
+
canYaml?: boolean;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Modify the way the name looks when displayed
|
|
284
|
+
*/
|
|
285
|
+
displayName?: string;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* New resources can be created of this type
|
|
289
|
+
*/
|
|
290
|
+
isCreatable?: boolean;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Resources of this type can be deleted/removed
|
|
294
|
+
*/
|
|
295
|
+
isRemovable?: boolean;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* This type should be grouped by namespaces when displayed in a table
|
|
299
|
+
*/
|
|
300
|
+
namespaced?: boolean;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Show the age column in when displaying this type in a table
|
|
304
|
+
*/
|
|
305
|
+
showAge?: boolean;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Show the masthead at the top of the list view of this type
|
|
309
|
+
*/
|
|
310
|
+
showListMasthead?: boolean;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Show the state column in when displaying this type in a table
|
|
314
|
+
*/
|
|
315
|
+
showState?: boolean;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Leaving these here for completeness but I don't think these should be advertised as useable to plugin creators.
|
|
319
|
+
*/
|
|
320
|
+
// alias
|
|
321
|
+
// customRoute
|
|
322
|
+
// customRoute
|
|
323
|
+
// depaginate
|
|
324
|
+
// graphConfig
|
|
325
|
+
// hasGraph
|
|
326
|
+
// isEditable
|
|
327
|
+
// limit
|
|
328
|
+
// listGroups
|
|
329
|
+
// localOnly
|
|
330
|
+
// location
|
|
331
|
+
// match
|
|
332
|
+
// realResource
|
|
333
|
+
// resource
|
|
334
|
+
// resourceDetail
|
|
335
|
+
// resourceEdit
|
|
336
|
+
// showConfigView
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface DSLReturnType {
|
|
340
|
+
/**
|
|
341
|
+
* Register multiple types by name and place them all in a group if desired. Primarily used for grouping things in the cluster explorer navigation.
|
|
342
|
+
* @param types A list of types that are going to be registered
|
|
343
|
+
* @param group Conditionally a group you want to places all the types in
|
|
344
|
+
* @returns {@link void}
|
|
345
|
+
*/
|
|
346
|
+
basicType: (types: string[], group?: string) => void;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Configure a myriad of options for the specified type
|
|
350
|
+
* @param type The type to be configured
|
|
351
|
+
* @param options {@link ConfigureTypeOptions}
|
|
352
|
+
* @returns {@link void}
|
|
353
|
+
*/
|
|
354
|
+
configureType: (type: string, options: ConfigureTypeOptions) => void;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Register the headers/columns that should be used when rendering a table for the specified type.
|
|
358
|
+
* @param type The type you'd like to register headers/columns for.
|
|
359
|
+
* @param headers {@link HeaderOptions[]}
|
|
360
|
+
* @returns {@link void}
|
|
361
|
+
*/
|
|
362
|
+
headers: (type: string, headers: HeaderOptions[]) => void;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Create and register a new product
|
|
366
|
+
* @param options {@link ProductOptions}
|
|
367
|
+
* @returns {@link void}
|
|
368
|
+
*/
|
|
369
|
+
product: (options: ProductOptions) => void;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Leaving these here for completeness but I don't think these should be advertised as useable to plugin creators.
|
|
373
|
+
*/
|
|
374
|
+
// componentForType: (type: string, replacementType: string)
|
|
375
|
+
// groupBy: (type: string, field: string)
|
|
376
|
+
// hideBulkActions: (type: string, field)
|
|
377
|
+
// ignoreGroup: (regexOrString)
|
|
378
|
+
// ignoreType: (regexOrString)
|
|
379
|
+
// mapGroup: (match, replace)
|
|
380
|
+
// mapType: (match, replace)
|
|
381
|
+
// moveType: (match, group)
|
|
382
|
+
// setGroupDefaultType: (input, defaultType)
|
|
383
|
+
// spoofedType: (obj)
|
|
384
|
+
// virtualType: (obj)
|
|
385
|
+
// weightGroup: (input, weight, forBasic)
|
|
386
|
+
// weightType: (input, weight, forBasic)
|
|
387
|
+
}
|
|
388
|
+
|
|
139
389
|
/**
|
|
140
390
|
* Interface for a Dashboard plugin
|
|
141
391
|
*/
|
|
@@ -144,7 +394,7 @@ export interface IPlugin {
|
|
|
144
394
|
* Add a product
|
|
145
395
|
* @param importFn Function that will import the module containing a product definition
|
|
146
396
|
*/
|
|
147
|
-
addProduct(importFn:
|
|
397
|
+
addProduct(importFn: ProductFunction): void;
|
|
148
398
|
|
|
149
399
|
/**
|
|
150
400
|
* Add a locale to the i18n store
|
|
@@ -249,4 +499,11 @@ export interface IPlugin {
|
|
|
249
499
|
* @param {Function} fn function that dynamically loads the module for the thing being registered
|
|
250
500
|
*/
|
|
251
501
|
register(type: string, name: string, fn: Function): void;
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Will return all of the configuration functions used for creating a new product.
|
|
505
|
+
* @param store The store that was passed to the function that's passed to `plugin.addProduct(function)`
|
|
506
|
+
* @param productName The name of the new product. This name is displayed in the navigation.
|
|
507
|
+
*/
|
|
508
|
+
DSL(store: any, productName: string): DSLReturnType;
|
|
252
509
|
}
|
|
@@ -64,7 +64,7 @@ jobs:
|
|
|
64
64
|
shell: bash
|
|
65
65
|
id: build_script
|
|
66
66
|
run: |
|
|
67
|
-
yarn publish-pkgs -s "${{ github.repository }}" -b
|
|
67
|
+
yarn publish-pkgs -s "${{ github.repository }}" -b gh-pages
|
|
68
68
|
|
|
69
69
|
- name: Upload charts artifact
|
|
70
70
|
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
|
@@ -83,8 +83,7 @@ jobs:
|
|
|
83
83
|
- name: Checkout
|
|
84
84
|
uses: actions/checkout@v3
|
|
85
85
|
with:
|
|
86
|
-
|
|
87
|
-
ref: main
|
|
86
|
+
ref: gh-pages
|
|
88
87
|
|
|
89
88
|
- name: Configure Git
|
|
90
89
|
run: |
|
|
@@ -105,7 +104,7 @@ jobs:
|
|
|
105
104
|
- name: Run chart-releaser
|
|
106
105
|
uses: helm/chart-releaser-action@v1.4.1
|
|
107
106
|
with:
|
|
108
|
-
charts_dir: ./charts
|
|
107
|
+
charts_dir: ./charts/*
|
|
109
108
|
env:
|
|
110
109
|
CR_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
|
111
110
|
CR_SKIP_EXISTING: true
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"node": ">=12"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@vue/cli-plugin-babel": "
|
|
13
|
-
"@vue/cli-service": "
|
|
14
|
-
"@vue/cli-plugin-typescript": "
|
|
12
|
+
"@vue/cli-plugin-babel": "4.5.18",
|
|
13
|
+
"@vue/cli-service": "4.5.18",
|
|
14
|
+
"@vue/cli-plugin-typescript": "4.5.18"
|
|
15
15
|
},
|
|
16
16
|
"browserslist": [
|
|
17
17
|
"> 1%",
|
|
@@ -2,18 +2,26 @@
|
|
|
2
2
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
3
3
|
import SortableTable from '@shell/components/SortableTable';
|
|
4
4
|
import Banner from '@components/Banner/Banner.vue';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CONSTRAINT_VIOLATION_RESOURCE_LINK,
|
|
7
|
+
CONSTRAINT_VIOLATION_MESSAGE,
|
|
8
|
+
CONSTRAINT_VIOLATION_TYPE,
|
|
9
|
+
CONSTRAINT_VIOLATION_NAMESPACE,
|
|
10
|
+
} from '@shell/config/table-headers';
|
|
6
11
|
|
|
7
12
|
export default {
|
|
8
13
|
components: { Banner, SortableTable },
|
|
9
14
|
mixins: [CreateEditView],
|
|
10
15
|
data() {
|
|
16
|
+
const headers = [
|
|
17
|
+
CONSTRAINT_VIOLATION_TYPE,
|
|
18
|
+
CONSTRAINT_VIOLATION_NAMESPACE,
|
|
19
|
+
CONSTRAINT_VIOLATION_RESOURCE_LINK,
|
|
20
|
+
CONSTRAINT_VIOLATION_MESSAGE
|
|
21
|
+
];
|
|
22
|
+
|
|
11
23
|
return {
|
|
12
|
-
headers
|
|
13
|
-
CONSTRAINT_VIOLATION_TYPE,
|
|
14
|
-
CONSTRAINT_VIOLATION_RESOURCE_LINK,
|
|
15
|
-
CONSTRAINT_VIOLATION_MESSAGE
|
|
16
|
-
],
|
|
24
|
+
headers,
|
|
17
25
|
violations: this.value.violations.map((violation, i) => ({ ...violation, id: i }))
|
|
18
26
|
};
|
|
19
27
|
}
|
|
@@ -46,7 +54,6 @@ export default {
|
|
|
46
54
|
<SortableTable
|
|
47
55
|
:headers="headers"
|
|
48
56
|
:rows="violations"
|
|
49
|
-
:search="false"
|
|
50
57
|
:table-actions="false"
|
|
51
58
|
:row-actions="false"
|
|
52
59
|
:paging="true"
|
|
@@ -5,6 +5,7 @@ import FleetClusters from '@shell/components/fleet/FleetClusters';
|
|
|
5
5
|
import ResourceTabs from '@shell/components/form/ResourceTabs';
|
|
6
6
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
7
7
|
import { FLEET } from '@shell/config/types';
|
|
8
|
+
import { allHash } from '@shell/utils/promise';
|
|
8
9
|
|
|
9
10
|
export default {
|
|
10
11
|
name: 'DetailClusterGroup',
|
|
@@ -25,7 +26,12 @@ export default {
|
|
|
25
26
|
},
|
|
26
27
|
|
|
27
28
|
async fetch() {
|
|
28
|
-
|
|
29
|
+
const hash = {
|
|
30
|
+
workspaces: this.$store.dispatch('cluster/findAll', { type: FLEET.WORKSPACE }),
|
|
31
|
+
FleetClusters: this.$store.dispatch('management/findAll', { type: FLEET.CLUSTER }),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
await allHash(hash);
|
|
29
35
|
},
|
|
30
36
|
|
|
31
37
|
computed: {
|
|
@@ -5,6 +5,7 @@ import { Checkbox } from '@components/Form/Checkbox';
|
|
|
5
5
|
import UnitInput from '@shell/components/form/UnitInput';
|
|
6
6
|
import { Banner } from '@components/Banner';
|
|
7
7
|
import FileSelector from '@shell/components/form/FileSelector';
|
|
8
|
+
import { OKTA, SHIBBOLETH } from '../saml';
|
|
8
9
|
|
|
9
10
|
const DEFAULT_NON_TLS_PORT = 389;
|
|
10
11
|
const DEFAULT_TLS_PORT = 636;
|
|
@@ -33,6 +34,11 @@ export default {
|
|
|
33
34
|
type: {
|
|
34
35
|
type: String,
|
|
35
36
|
required: true
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
isCreate: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
},
|
|
@@ -46,9 +52,17 @@ export default {
|
|
|
46
52
|
model: this.value,
|
|
47
53
|
hostname: this.value.servers.join(','),
|
|
48
54
|
serverSetting: null,
|
|
55
|
+
OKTA
|
|
49
56
|
};
|
|
50
57
|
},
|
|
51
58
|
|
|
59
|
+
computed: {
|
|
60
|
+
// Does the auth provider support LDAP for search in addition to SAML?
|
|
61
|
+
isSamlProvider() {
|
|
62
|
+
return this.type === SHIBBOLETH || this.type === OKTA;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
52
66
|
watch: {
|
|
53
67
|
hostname(neu, old) {
|
|
54
68
|
this.value.servers = neu.split(',');
|
|
@@ -232,6 +246,12 @@ export default {
|
|
|
232
246
|
<div class="row">
|
|
233
247
|
<h3> {{ t('authConfig.ldap.customizeSchema') }}</h3>
|
|
234
248
|
</div>
|
|
249
|
+
<Banner
|
|
250
|
+
v-if="type === OKTA && isCreate"
|
|
251
|
+
class="row"
|
|
252
|
+
color="info"
|
|
253
|
+
label-key="authConfig.ldap.oktaSchema"
|
|
254
|
+
/>
|
|
235
255
|
<div class="row">
|
|
236
256
|
<div class="col span-6">
|
|
237
257
|
<h4>{{ t('authConfig.ldap.users') }}</h4>
|
|
@@ -361,7 +381,7 @@ export default {
|
|
|
361
381
|
/>
|
|
362
382
|
</div>
|
|
363
383
|
<div
|
|
364
|
-
v-if="
|
|
384
|
+
v-if="!isSamlProvider"
|
|
365
385
|
class=" col span-6"
|
|
366
386
|
>
|
|
367
387
|
<RadioGroup
|
package/edit/auth/saml.vue
CHANGED
|
@@ -11,6 +11,31 @@ import FileSelector from '@shell/components/form/FileSelector';
|
|
|
11
11
|
import AuthBanner from '@shell/components/auth/AuthBanner';
|
|
12
12
|
import config from '@shell/edit/auth/ldap/config';
|
|
13
13
|
|
|
14
|
+
export const SHIBBOLETH = 'shibboleth';
|
|
15
|
+
export const OKTA = 'okta';
|
|
16
|
+
|
|
17
|
+
// Standard LDAP defaults
|
|
18
|
+
const LDAP_DEFAULTS = {
|
|
19
|
+
connectionTimeout: 5000,
|
|
20
|
+
groupDNAttribute: 'entryDN',
|
|
21
|
+
groupMemberMappingAttribute: 'member',
|
|
22
|
+
groupMemberUserAttribute: 'entryDN',
|
|
23
|
+
groupNameAttribute: 'cn',
|
|
24
|
+
groupObjectClass: 'groupOfNames',
|
|
25
|
+
groupSearchAttribute: 'cn',
|
|
26
|
+
nestedGroupMembershipEnabled: false,
|
|
27
|
+
port: 389,
|
|
28
|
+
servers: [],
|
|
29
|
+
starttls: false,
|
|
30
|
+
tls: false,
|
|
31
|
+
disabledStatusBitmask: 0,
|
|
32
|
+
userLoginAttribute: 'uid',
|
|
33
|
+
userMemberAttribute: 'memberOf',
|
|
34
|
+
userNameAttribute: 'cn',
|
|
35
|
+
userObjectClass: 'inetOrgPerson',
|
|
36
|
+
userSearchAttribute: 'uid|sn|givenName'
|
|
37
|
+
};
|
|
38
|
+
|
|
14
39
|
export default {
|
|
15
40
|
components: {
|
|
16
41
|
Loading,
|
|
@@ -26,7 +51,10 @@ export default {
|
|
|
26
51
|
|
|
27
52
|
mixins: [CreateEditView, AuthConfig],
|
|
28
53
|
data() {
|
|
29
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
showLdap: false,
|
|
56
|
+
showLdapDetails: false,
|
|
57
|
+
};
|
|
30
58
|
},
|
|
31
59
|
|
|
32
60
|
computed: {
|
|
@@ -42,32 +70,32 @@ export default {
|
|
|
42
70
|
return { enabled: true, ...this.model };
|
|
43
71
|
},
|
|
44
72
|
|
|
73
|
+
// Does the auth provider support LDAP for search in addition to SAML?
|
|
74
|
+
supportsLDAPSearch() {
|
|
75
|
+
return this.NAME === SHIBBOLETH || this.NAME === OKTA;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
ldapHosts() {
|
|
79
|
+
const hosts = this.model?.openLdapConfig.servers || [];
|
|
80
|
+
|
|
81
|
+
return hosts.join(',');
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
ldapProtocol() {
|
|
85
|
+
if (this.model?.openLdapConfig?.starttls) {
|
|
86
|
+
return this.t('authConfig.ldap.protocols.starttls');
|
|
87
|
+
} else if (this.model?.openLdapConfig?.tls) {
|
|
88
|
+
return this.t('authConfig.ldap.protocols.tls');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return this.t('authConfig.ldap.protocols.ldap');
|
|
92
|
+
}
|
|
45
93
|
},
|
|
46
94
|
watch: {
|
|
47
95
|
showLdap(neu, old) {
|
|
48
96
|
if (neu && !this.model.openLdapConfig) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
groupDNAttribute: 'entryDN',
|
|
52
|
-
groupMemberMappingAttribute: 'member',
|
|
53
|
-
groupMemberUserAttribute: 'entryDN',
|
|
54
|
-
groupNameAttribute: 'cn',
|
|
55
|
-
groupObjectClass: 'groupOfNames',
|
|
56
|
-
groupSearchAttribute: 'cn',
|
|
57
|
-
nestedGroupMembershipEnabled: false,
|
|
58
|
-
port: 389,
|
|
59
|
-
servers: [],
|
|
60
|
-
starttls: false,
|
|
61
|
-
tls: false,
|
|
62
|
-
disabledStatusBitmask: 0,
|
|
63
|
-
userLoginAttribute: 'uid',
|
|
64
|
-
userMemberAttribute: 'memberOf',
|
|
65
|
-
userNameAttribute: 'cn',
|
|
66
|
-
userObjectClass: 'inetOrgPerson',
|
|
67
|
-
userSearchAttribute: 'uid|sn|givenName'
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
this.$set(this.model, 'openLdapConfig', config);
|
|
97
|
+
// Use a spread of config, so that if don't make changes to the defaults if the user edits them
|
|
98
|
+
this.$set(this.model, 'openLdapConfig', { ...LDAP_DEFAULTS });
|
|
71
99
|
}
|
|
72
100
|
}
|
|
73
101
|
}
|
|
@@ -98,7 +126,9 @@ export default {
|
|
|
98
126
|
:disable="disable"
|
|
99
127
|
:edit="goToEdit"
|
|
100
128
|
>
|
|
101
|
-
<template
|
|
129
|
+
<template
|
|
130
|
+
slot="rows"
|
|
131
|
+
>
|
|
102
132
|
<tr><td>{{ t(`authConfig.saml.displayName`) }}: </td><td>{{ model.displayNameField }}</td></tr>
|
|
103
133
|
<tr><td>{{ t(`authConfig.saml.userName`) }}: </td><td>{{ model.userNameField }}</td></tr>
|
|
104
134
|
<tr><td>{{ t(`authConfig.saml.UID`) }}: </td><td>{{ model.uidField }}</td></tr>
|
|
@@ -106,6 +136,47 @@ export default {
|
|
|
106
136
|
<tr><td>{{ t(`authConfig.saml.api`) }}: </td><td>{{ model.rancherApiHost }}</td></tr>
|
|
107
137
|
<tr><td>{{ t(`authConfig.saml.groups`) }}: </td><td>{{ model.groupsField }}</td></tr>
|
|
108
138
|
</template>
|
|
139
|
+
|
|
140
|
+
<template
|
|
141
|
+
v-if="supportsLDAPSearch"
|
|
142
|
+
slot="footer"
|
|
143
|
+
>
|
|
144
|
+
<Banner
|
|
145
|
+
v-if="showLdap"
|
|
146
|
+
color="success"
|
|
147
|
+
class="banner"
|
|
148
|
+
>
|
|
149
|
+
<div
|
|
150
|
+
class="advanced-ldap-banner"
|
|
151
|
+
>
|
|
152
|
+
<div>{{ t('authConfig.saml.search.on') }}</div>
|
|
153
|
+
<div>
|
|
154
|
+
<a
|
|
155
|
+
class="toggle-btn"
|
|
156
|
+
@click="showLdapDetails = !showLdapDetails"
|
|
157
|
+
>
|
|
158
|
+
<template v-if="showLdapDetails">{{ t('authConfig.saml.search.hide') }}</template>
|
|
159
|
+
<template v-else>{{ t('authConfig.saml.search.show') }}</template>
|
|
160
|
+
</a>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</Banner>
|
|
164
|
+
<Banner
|
|
165
|
+
v-else
|
|
166
|
+
color="info"
|
|
167
|
+
>
|
|
168
|
+
{{ t('authConfig.saml.search.off') }}
|
|
169
|
+
</Banner>
|
|
170
|
+
|
|
171
|
+
<table v-if="showLdapDetails && model.openLdapConfig">
|
|
172
|
+
<tr><td>{{ t('authConfig.ldap.hostname.label') }}:</td><td>{{ ldapHosts }}</td></tr>
|
|
173
|
+
<tr><td>{{ t('authConfig.ldap.port') }}:</td><td>{{ model.openLdapConfig.port }}</td></tr>
|
|
174
|
+
<tr><td>{{ t('authConfig.ldap.protocol') }}:</td><td>{{ ldapProtocol }}</td></tr>
|
|
175
|
+
<tr><td>{{ t('authConfig.ldap.serviceAccountDN') }}:</td><td>{{ model.openLdapConfig.serviceAccountDistinguishedName }}</td></tr>
|
|
176
|
+
<tr><td>{{ t('authConfig.ldap.userSearchBase.label') }}:</td><td>{{ model.openLdapConfig.userSearchBase }}</td></tr>
|
|
177
|
+
<tr><td>{{ t('authConfig.ldap.groupSearchBase.label') }}:</td><td>{{ model.openLdapConfig.groupSearchBase }}</td></tr>
|
|
178
|
+
</table>
|
|
179
|
+
</template>
|
|
109
180
|
</AuthBanner>
|
|
110
181
|
|
|
111
182
|
<hr>
|
|
@@ -233,7 +304,26 @@ export default {
|
|
|
233
304
|
/>
|
|
234
305
|
</div>
|
|
235
306
|
</div>
|
|
236
|
-
<div
|
|
307
|
+
<div
|
|
308
|
+
v-if="!model.enabled"
|
|
309
|
+
class="row"
|
|
310
|
+
>
|
|
311
|
+
<div class="col span-12">
|
|
312
|
+
<Banner color="info">
|
|
313
|
+
<div v-clean-html="t('authConfig.associatedWarning', tArgs, true)" />
|
|
314
|
+
</Banner>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
<div v-if="supportsLDAPSearch">
|
|
318
|
+
<div class="row">
|
|
319
|
+
<h2>{{ t('authConfig.saml.search.title') }}</h2>
|
|
320
|
+
</div>
|
|
321
|
+
<div class="row">
|
|
322
|
+
<Banner
|
|
323
|
+
label-key="authConfig.saml.search.message"
|
|
324
|
+
color="info"
|
|
325
|
+
/>
|
|
326
|
+
</div>
|
|
237
327
|
<div class="row">
|
|
238
328
|
<Checkbox
|
|
239
329
|
v-model="showLdap"
|
|
@@ -243,25 +333,15 @@ export default {
|
|
|
243
333
|
</div>
|
|
244
334
|
<div class="row mt-20 mb-20">
|
|
245
335
|
<config
|
|
246
|
-
v-if="showLdap"
|
|
336
|
+
v-if="showLdap && model.openLdapConfig"
|
|
247
337
|
v-model="model.openLdapConfig"
|
|
248
338
|
:type="NAME"
|
|
249
339
|
:mode="mode"
|
|
340
|
+
:is-create="!model.enabled"
|
|
250
341
|
/>
|
|
251
342
|
</div>
|
|
252
343
|
</div>
|
|
253
344
|
</template>
|
|
254
|
-
<div
|
|
255
|
-
v-if="!model.enabled"
|
|
256
|
-
class="row"
|
|
257
|
-
>
|
|
258
|
-
<div class="col span-12">
|
|
259
|
-
<Banner
|
|
260
|
-
v-clean-html="t('authConfig.associatedWarning', tArgs, true)"
|
|
261
|
-
color="info"
|
|
262
|
-
/>
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
345
|
</CruResource>
|
|
266
346
|
</div>
|
|
267
347
|
</template>
|
|
@@ -274,4 +354,19 @@ export default {
|
|
|
274
354
|
margin: 0 3px;
|
|
275
355
|
}
|
|
276
356
|
}
|
|
357
|
+
|
|
358
|
+
// Banner shows message and link formatted right aligned
|
|
359
|
+
.advanced-ldap-banner {
|
|
360
|
+
display: flex;
|
|
361
|
+
flex: 1;
|
|
362
|
+
|
|
363
|
+
> :first-child {
|
|
364
|
+
flex: 1;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.toggle-btn {
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
user-select: none;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
277
372
|
</style>
|