mirror of https://github.com/rancher/dashboard.git
280 lines
8.6 KiB
Vue
280 lines
8.6 KiB
Vue
<script>
|
|
import { _CREATE } from '@shell/config/query-params';
|
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
import CruResource from '@shell/components/CruResource';
|
|
import Labels from '@shell/components/form/Labels';
|
|
import Loading from '@shell/components/Loading';
|
|
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
|
import { FLEET, MANAGEMENT, SCHEMA } from '@shell/config/types';
|
|
import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
// import RoleBindings from '@shell/components/RoleBindings';
|
|
import Tabbed from '@shell/components/Tabbed';
|
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
import { SCOPE_NAMESPACE, SCOPE_CLUSTER } from '@shell/components/RoleBindings.vue';
|
|
import { NAME as FLEET_NAME } from '@shell/config/product/fleet';
|
|
// import KeyValue from '@shell/components/form/KeyValue.vue';
|
|
import { mapState } from 'vuex';
|
|
import { LAST_NAMESPACE, WORKSPACE } from '@shell/store/prefs';
|
|
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
import Banner from '@components/Banner/Banner.vue';
|
|
import ArrayList from '@shell/components/form/ArrayList.vue';
|
|
import FleetOCIStorageSecret from '@shell/components/fleet/FleetOCIStorageSecret.vue';
|
|
|
|
export default {
|
|
name: 'FleetCruWorkspace',
|
|
|
|
emits: ['input'],
|
|
|
|
inheritAttrs: false,
|
|
components: {
|
|
CruResource,
|
|
FleetOCIStorageSecret,
|
|
Labels,
|
|
Loading,
|
|
NameNsDescription,
|
|
Tabbed,
|
|
Tab,
|
|
Banner,
|
|
ArrayList
|
|
},
|
|
|
|
mixins: [CreateEditView],
|
|
|
|
async fetch() {
|
|
this.rancherClusters = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER });
|
|
|
|
if (this.$store.getters['management/schemaFor']( FLEET.CLUSTER )) {
|
|
this.fleetClusters = await this.$store.dispatch('management/findAll', { type: FLEET.CLUSTER });
|
|
}
|
|
|
|
if (this.hasRepoRestrictionSchema) {
|
|
const restrictions = await this.$store.dispatch('management/findAll', { type: FLEET.GIT_REPO_RESTRICTION });
|
|
|
|
const workSpaceRestriction = restrictions.find((item) => {
|
|
return item.metadata.namespace === this.value.metadata.name && item.metadata.name.startsWith(`restriction-${ this.value.metadata.name }`);
|
|
});
|
|
|
|
if (workSpaceRestriction) {
|
|
this.workSpaceRestriction = workSpaceRestriction;
|
|
}
|
|
}
|
|
|
|
this.restrictionsOptions = await this.$store.getters[`type-map/optionsFor`](FLEET.GIT_REPO_RESTRICTION);
|
|
this.restrictionsSchema = await this.$store.getters[`management/schemaFor`](FLEET.GIT_REPO_RESTRICTION);
|
|
},
|
|
|
|
data() {
|
|
this.value['spec'] = this.value.spec || {};
|
|
|
|
return {
|
|
fleetClusters: null,
|
|
rancherClusters: null,
|
|
workSpaceRestriction: null,
|
|
restrictions: [],
|
|
targetNamespaces: [],
|
|
restrictionsSchema: { spec: {} },
|
|
namespace: this.$store.getters['prefs/get'](LAST_NAMESPACE),
|
|
hasRepoRestrictionSchema: !!this.$store.getters['management/schemaFor']( FLEET.GIT_REPO_RESTRICTION )
|
|
};
|
|
},
|
|
|
|
methods: {
|
|
async saveAll(buttonCb) {
|
|
// Anyone who can edit workspace
|
|
|
|
try {
|
|
await this.value.save();
|
|
|
|
// IF there is a restriction update it
|
|
if (this.workSpaceRestriction) {
|
|
await this.workSpaceRestriction.save();
|
|
}
|
|
|
|
// If there is no restriction and targetnamespace is set then create it.
|
|
if (!this.workSpaceRestriction && this.targetNamespaces.length) {
|
|
// For users with more limited permissions the gitreporestriction schema may not be visible until they create a workspace
|
|
if (!this.hasRepoRestrictionSchema) {
|
|
await this.$store.dispatch('management/find', { type: SCHEMA, id: FLEET.GIT_REPO_RESTRICTION }, { force: true });
|
|
}
|
|
const model = await this.$store.dispatch(`management/create`, {
|
|
type: FLEET.GIT_REPO_RESTRICTION,
|
|
allowedTargetNamespaces: this.targetNamespaces,
|
|
metadata: {
|
|
// restriction- prefix is added to the workspace name
|
|
// to identify automatically created GitRepoRestrictions
|
|
// when adding targetNamespaces at the point of workspace creation
|
|
name: `restriction-${ this.value.metadata.name }-${ Date.now() }`,
|
|
namespace: this.value.metadata.name // what the user types
|
|
}
|
|
});
|
|
|
|
await model.save();
|
|
}
|
|
|
|
await this.value.waitForWorkspaceSchema(20000, (schema) => {
|
|
// For standard user if there are no workspaces, user can't list workspaces
|
|
// Therefore wait for it.
|
|
return schema.collectionMethods?.includes('GET');
|
|
});
|
|
|
|
await this.$store.dispatch( 'management/findAll', { type: FLEET.WORKSPACE });
|
|
|
|
this.$store.commit('updateWorkspace', { value: this.value.metadata.name, getters: this.$store.getters } );
|
|
this.$store.dispatch('prefs/set', { key: WORKSPACE, value: this.value.metadata.name });
|
|
|
|
buttonCb(true);
|
|
this.done();
|
|
} catch (err) {
|
|
console.error(err) ; // eslint-disable-line no-console
|
|
buttonCb(false);
|
|
this.errors = exceptionToErrorsArray(err);
|
|
}
|
|
},
|
|
|
|
updateDefaultOCIStorageSecret(secretName) {
|
|
this.value.metadata.annotations[FLEET_ANNOTATIONS.OCI_STORAGE_SECRET_DEFAULT] = secretName;
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
...mapState(['allWorkspaces', 'workspace']),
|
|
|
|
allowedTargetNamespaces: {
|
|
get() {
|
|
return this.workSpaceRestriction?.allowedTargetNamespaces || [];
|
|
},
|
|
|
|
set(value) {
|
|
if (this.workSpaceRestriction) {
|
|
this.workSpaceRestriction.allowedTargetNamespaces = value;
|
|
}
|
|
|
|
this.targetNamespaces = value;
|
|
}
|
|
},
|
|
|
|
defaultOCIStorageSecret() {
|
|
return this.value.metadata?.annotations?.[FLEET_ANNOTATIONS.OCI_STORAGE_SECRET_DEFAULT];
|
|
},
|
|
|
|
isCreate() {
|
|
return this.mode === _CREATE;
|
|
},
|
|
|
|
SCOPE_NAMESPACE() {
|
|
return SCOPE_NAMESPACE;
|
|
},
|
|
|
|
SCOPE_CLUSTER() {
|
|
return SCOPE_CLUSTER;
|
|
},
|
|
|
|
FLEET_NAME() {
|
|
return FLEET_NAME;
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<Loading v-if="$fetchState.pending" />
|
|
<CruResource
|
|
v-else
|
|
:done-route="doneRoute"
|
|
:mode="mode"
|
|
:resource="value"
|
|
:subtypes="[]"
|
|
:validation-passed="true"
|
|
:errors="errors"
|
|
@error="e=>errors = e"
|
|
@finish="saveAll"
|
|
@cancel="done"
|
|
>
|
|
<NameNsDescription
|
|
:value="value"
|
|
:mode="mode"
|
|
:namespaced="false"
|
|
@update:value="$emit('input', $event)"
|
|
/>
|
|
|
|
<Tabbed
|
|
:side-tabs="true"
|
|
default-tab="members"
|
|
:use-hash="useTabbedHash"
|
|
>
|
|
<!-- <Tab name="members" label-key="generic.members" :weight="2">
|
|
<RoleBindings
|
|
ref="rb"
|
|
:register-after-hook="registerAfterHook"
|
|
:role-scope="SCOPE_CLUSTER"
|
|
:binding-scope="SCOPE_NAMESPACE"
|
|
:filter-role-value="FLEET_NAME"
|
|
:namespace="value.name"
|
|
:mode="mode"
|
|
in-store="management"
|
|
/>
|
|
</Tab> -->
|
|
|
|
<Tab
|
|
name="allowedtargetnamespaces"
|
|
label-key="fleet.workspaces.tabs.restrictions"
|
|
:weight="3"
|
|
>
|
|
<Banner
|
|
color="info"
|
|
>
|
|
<div>
|
|
<t
|
|
k="fleet.restrictions.banner"
|
|
:count="allowedTargetNamespaces.length"
|
|
:raw="true"
|
|
/>
|
|
<a
|
|
v-if="!!allowedTargetNamespaces.length"
|
|
@click="workSpaceRestriction.goToDetail()"
|
|
>
|
|
{{ t('generic.here') }}
|
|
</a>
|
|
</div>
|
|
</Banner>
|
|
|
|
<ArrayList
|
|
key="labels"
|
|
v-model:value="allowedTargetNamespaces"
|
|
:add-label="t('fleet.restrictions.addLabel')"
|
|
:mode="mode"
|
|
:title="t('fleet.restrictions.addTitle')"
|
|
:read-allowed="false"
|
|
:value-can-be-empty="true"
|
|
/>
|
|
</Tab>
|
|
<Tab
|
|
v-if="!isCreate"
|
|
name="ociRegistries"
|
|
label-key="fleet.workspaces.tabs.ociRegistry"
|
|
:weight="2"
|
|
>
|
|
<FleetOCIStorageSecret
|
|
data-testid="default-oci-storage-secret"
|
|
:secret="defaultOCIStorageSecret"
|
|
:workspace="value.metadata.name"
|
|
:mode="mode"
|
|
:allow-default="false"
|
|
@update:value="updateDefaultOCIStorageSecret"
|
|
/>
|
|
</Tab>
|
|
<Tab
|
|
name="labels"
|
|
label-key="generic.labelsAndAnnotations"
|
|
:weight="1"
|
|
>
|
|
<Labels
|
|
:value="value"
|
|
:mode="mode"
|
|
@update:value="$emit('input', $event)"
|
|
/>
|
|
</Tab>
|
|
</Tabbed>
|
|
</CruResource>
|
|
</template>
|