From 9c010cd66b13e7864afa916b1cd398fb6743325a Mon Sep 17 00:00:00 2001 From: Cody Jackson Date: Thu, 7 Nov 2019 13:52:47 -0700 Subject: [PATCH 01/12] Include EdgeHTML based browers to blacklist We don't support the EdgeHTML browsers just like we don't support Internet Explorer. I added EdgeHTML to the blacklist so that we will display the unsupported page. rancher/rancher#23909 --- app/application/route.js | 3 ++- app/ie/template.hbs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/application/route.js b/app/application/route.js index 99eaf1cc3..381f211a7 100644 --- a/app/application/route.js +++ b/app/application/route.js @@ -26,7 +26,8 @@ export default Route.extend({ let agent = window.navigator.userAgent.toLowerCase(); - if ( agent.indexOf('msie ') >= 0 || agent.indexOf('trident/') >= 0 ) { + // Show the we don't support internet explorer or edge browsers (only edge html based browsers the mobile and chromium based browsers should be okay). + if ( agent.indexOf('msie ') >= 0 || agent.indexOf('trident/') >= 0 || agent.indexOf('edge/') >= 0) { this.replaceWith('ie'); return; diff --git a/app/ie/template.hbs b/app/ie/template.hbs index dcc386951..f8e5b02e7 100644 --- a/app/ie/template.hbs +++ b/app/ie/template.hbs @@ -2,5 +2,5 @@



- Sorry, IE is not supported. + Sorry, IE and Edge are not supported. From 3399b66bc3b0407a6c8b1176f33573dcd978c213 Mon Sep 17 00:00:00 2001 From: Westly Wright Date: Thu, 7 Nov 2019 13:43:10 -0700 Subject: [PATCH 02/12] refactor the logic backing GKE network/subnetwork selections While working on a ticket to provide the ability to de-select subnetworks when using the create subnetwork option I discovered the options were all messed up and allowed you to misconfigure yourself into a hole. I've moved ipalias and related networks settings out of advanced becuase depending on what you select for your subnetwork the ability to choose ipalias and the other settings changes. This change allows you deselect a node subnet so you can create a subnetwork automatically. rancher/rancher#21079 --- .../driver-googlegke/component.js | 142 +++++++++++---- .../driver-googlegke/template.hbs | 171 ++++++++---------- translations/en-us.yaml | 3 +- 3 files changed, 180 insertions(+), 136 deletions(-) diff --git a/lib/shared/addon/components/cluster-driver/driver-googlegke/component.js b/lib/shared/addon/components/cluster-driver/driver-googlegke/component.js index 46303d125..8ad717294 100644 --- a/lib/shared/addon/components/cluster-driver/driver-googlegke/component.js +++ b/lib/shared/addon/components/cluster-driver/driver-googlegke/component.js @@ -1,15 +1,15 @@ import Component from '@ember/component' import ClusterDriver from 'shared/mixins/cluster-driver'; import layout from './template'; - import { get, set, computed, observer, setProperties } from '@ember/object'; import { sortableNumericSuffix } from 'shared/utils/util'; import { reject, all } from 'rsvp'; import { inject as service } from '@ember/service'; -import { equal } from '@ember/object/computed' +import { equal } from '@ember/object/computed'; import $ from 'jquery'; +import { isEmpty } from '@ember/utils'; const times = [ { @@ -211,19 +211,21 @@ export default Component.extend(ClusterDriver, { if ( !config ) { config = get(this, 'globalStore').createRecord({ - type: 'googleKubernetesEngineConfig', - diskSizeGb: 100, - enableAlphaFeature: false, - nodeCount: 3, - machineType: 'n1-standard-2', - zone: 'us-central1-f', - clusterIpv4Cidr: '', - minNodeCount: 1, - maxNodeCount: 5, - imageType: 'UBUNTU', - diskType: 'pd-standard', - region: 'us-west2', - taints: [], + type: 'googleKubernetesEngineConfig', + diskSizeGb: 100, + enableAlphaFeature: false, + nodeCount: 3, + machineType: 'n1-standard-2', + zone: 'us-central1-f', + clusterIpv4Cidr: '', + minNodeCount: 1, + maxNodeCount: 5, + imageType: 'UBUNTU', + diskType: 'pd-standard', + region: 'us-west2', + taints: [], + useIpAliases: true, + ipPolicyCreateSubnetwork: true, }); setProperties(this, { @@ -448,8 +450,14 @@ export default Component.extend(ClusterDriver, { const subNetworkContent = get(this, 'subNetworkContent') || [] - if (subNetworkContent.length > 0) { - set(this, 'config.subNetwork', subNetworkContent[0] && subNetworkContent[0].value) + if (subNetworkContent.length > 1) { + const firstNonNullSubnetMatch = subNetworkContent.find((sn) => !isEmpty(sn.value)); + + setProperties(this, { + 'config.subNetwork': firstNonNullSubnetMatch.value, + 'config.ipPolicyCreateSubnetwork': false, + }) + const secondaryIpRangeContent = get(this, 'secondaryIpRangeContent') || [] if (secondaryIpRangeContent.length > 0) { @@ -463,6 +471,20 @@ export default Component.extend(ClusterDriver, { } }), + subnetworkChange: observer('config.subNetwork', function() { + if (this.saving) { + return; + } + + const { config: { subNetwork } } = this; + + if (isEmpty(subNetwork)) { + set(this, 'config.ipPolicyCreateSubnetwork', true); + } else { + set(this, 'config.ipPolicyCreateSubnetwork', false); + } + }), + secondaryIpRangeContentChange: observer('secondaryIpRangeContent.[]', 'config.useIpAliases', function() { if (this.saving) { return; @@ -480,8 +502,15 @@ export default Component.extend(ClusterDriver, { return; } - if (!get(this, 'config.useIpAliases')) { - set(this, 'config.enablePrivateNodes', false) + if (get(this, 'config.useIpAliases')) { + if (!isEmpty(this.config.subNetwork)) { + set(this, 'config.ipPolicyCreateSubnetwork', false); + } + } else { + setProperties(this, { + 'config.enablePrivateNodes': false, + 'config.ipPolicyCreateSubnetwork': false, + }); } }), @@ -544,43 +573,62 @@ export default Component.extend(ClusterDriver, { return zoneChoices.filter((z) => (z.name || '').startsWith(locationName) && z.name !== zone) }), - networkContent: computed('networks', function() { + networkContent: computed('networks', 'config.zone', function() { return get(this, 'networks') }), - subNetworkContent: computed('subNetworks.[]', 'config.network', function() { - const subNetworks = get(this, 'subNetworks') || [] - const networkName = get(this, 'config.network') + subNetworkContent: computed('subNetworks.[]', 'config.network', 'config.zone', function() { + const { + config: { network: networkName }, + networkContent, + subNetworks = [], + } = this; - const out = subNetworks.filter((s) => { - const { network = '' } = s - const arr = network.split('/') || [] - const networkDisplayName = arr[arr.length - 1] + const filteredSubnets = (subNetworks || []).filter((s) => { + const network = networkContent.findBy('selfLink', s.network); + const networkDisplayName = network.name; if (networkDisplayName === networkName) { return true } - }) + }); + + const mappedSubnets = filteredSubnets.map((o) => { + const network = networkContent.findBy('selfLink', o.network); + const networkDisplayName = network.name; - return out.map((o) => { return { label: `${ o.name }(${ o.ipCidrRange })`, value: o.name, secondaryIpRanges: o.secondaryIpRanges, + networkDisplayName } - }) + }); + + const defaultSubnetAry = [{ + label: this.intl.t('clusterNew.googlegke.ipPolicyCreateSubnetwork.autoLabel'), + value: '', + }]; + + return [...defaultSubnetAry, ...mappedSubnets]; }), secondaryIpRangeContent: computed('subNetworkContent.[]', 'config.network', function() { - const subNetworkContent = get(this, 'subNetworkContent') - const { secondaryIpRanges = [] } = subNetworkContent + const { subNetworkContent = [], config: { network } } = this; + const subNetwork = subNetworkContent.findBy('networkDisplayName', network); - return secondaryIpRanges.map((s) => { - return { - lable: `${ s.rangeName }(${ s.ipCidrRange })`, - value: s.rangeName, - } - }) + if (subNetwork) { + const { secondaryIpRanges = [] } = subNetwork; + + return secondaryIpRanges.map((s) => { + return { + label: `${ s.rangeName }(${ s.ipCidrRange })`, + value: s.rangeName, + } + }); + } + + return []; }), serviceAccountContent: computed('serviceAccounts', function() { @@ -593,6 +641,24 @@ export default Component.extend(ClusterDriver, { return get(this, 'maintenanceWindowTimes').findBy('value', get(this, 'config.maintenanceWindow')) || { label: 'Any Time' }; }), + shouldAllowDisableCreateSubNetwork: computed('config.subNetwork', function() { + const { + config: { subNetwork }, + secondaryIpRangeContent, + editing, + } = this; + + if (isEmpty(subNetwork)) { + return true; + } + + if (editing && isEmpty(secondaryIpRangeContent)) { + return true; + } + + return false; + }), + fetchZones() { return get(this, 'globalStore').rawRequest({ url: '/meta/gkeZones', diff --git a/lib/shared/addon/components/cluster-driver/driver-googlegke/template.hbs b/lib/shared/addon/components/cluster-driver/driver-googlegke/template.hbs index bda9b28a6..efbe0d032 100644 --- a/lib/shared/addon/components/cluster-driver/driver-googlegke/template.hbs +++ b/lib/shared/addon/components/cluster-driver/driver-googlegke/template.hbs @@ -315,14 +315,16 @@ selection=config.enableHorizontalPodAutoscaling value=true disabled=editing - }} {{t "generic.enabled"}} + }} + {{t "generic.enabled"}} @@ -345,6 +347,7 @@ +
- {{#advanced-section advanced=clusterAdvanced}} -

{{t "clusterNew.googlegke.header.iPAllocationPolicy"}}

-
-
-
-
@@ -81,6 +83,7 @@

{{t "nodeDriver.vmwarevsphere.dataStore.help"}}

+
@@ -112,6 +116,7 @@

{{t "nodeDriver.vmwarevsphere.host.help"}}

+ {{/accordion-list-item}} @@ -274,6 +279,7 @@ @valueLabel="nodeDriver.vmwarevsphere.network.valueLabel" @valuePlaceholder="nodeDriver.vmwarevsphere.network.valuePlaceholder" /> + diff --git a/lib/shared/addon/components/select-value-check/component.js b/lib/shared/addon/components/select-value-check/component.js new file mode 100644 index 000000000..a4e10b56a --- /dev/null +++ b/lib/shared/addon/components/select-value-check/component.js @@ -0,0 +1,34 @@ +import Component from '@ember/component'; +import layout from './template'; +import { computed, get } from '@ember/object'; +import StatefulPromise from 'shared/utils/stateful-promise'; + +export default Component.extend({ + layout, + + optionValues: computed.mapBy('asyncOptions.value', 'value'), + asyncOptions: computed('content', function() { + return StatefulPromise.wrap(get(this, 'options'), []); + }), + valueArray: computed('values', function() { + const values = get(this, 'values'); + + return Array.isArray(values) + ? values + : [values]; + }), + missingValues: computed('valueArray', 'optionValues', function() { + const optionValues = get(this, 'optionValues'); + + if (optionValues.length === 0) { + return []; + } + + return get(this, 'valueArray').filter((value) => { + return optionValues.indexOf(value) === -1 + }); + }), + showMessaging: computed('values', 'missingValues.length', function() { + return get(this, 'values') && get(this, 'missingValues.length') > 0; + }) +}); diff --git a/lib/shared/addon/components/select-value-check/template.hbs b/lib/shared/addon/components/select-value-check/template.hbs new file mode 100644 index 000000000..7013cec73 --- /dev/null +++ b/lib/shared/addon/components/select-value-check/template.hbs @@ -0,0 +1,10 @@ +{{#if showMessaging}} +
+ {{t "selectValueCheck.message" values=missingValues.length}} +
    + {{#each missingValues as |missingValue|}} +
  • "{{missingValue}}"
  • + {{/each}} +
+
+{{/if}} \ No newline at end of file diff --git a/lib/shared/app/components/select-value-check/component.js b/lib/shared/app/components/select-value-check/component.js new file mode 100644 index 000000000..0f9a3a569 --- /dev/null +++ b/lib/shared/app/components/select-value-check/component.js @@ -0,0 +1 @@ +export { default } from 'shared/components/select-value-check/component'; \ No newline at end of file diff --git a/translations/en-us.yaml b/translations/en-us.yaml index 2352e0223..0d22b7661 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -9823,3 +9823,10 @@ pipelineNotification: recipients: required: Recipient is required asMessage: Send a message to + +selectValueCheck: + message: | + {values, plural, + =1 {Please select a new value. The following is no longer valid:} + other {Please select new values. The following are no longer valid:} + } \ No newline at end of file From 64f05d754e1e9dc9ed49b73f3640b80471c9fdc2 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Fri, 8 Nov 2019 13:14:39 +0100 Subject: [PATCH 04/12] Fix wrap lines feature --- app/styles/pages/_container.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/app/styles/pages/_container.scss b/app/styles/pages/_container.scss index 9dc6abf64..b10f39767 100644 --- a/app/styles/pages/_container.scss +++ b/app/styles/pages/_container.scss @@ -13,7 +13,6 @@ white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word; - width: auto; } } From a905dc2c0c57a0690558228e2c9cb422bd9bd00b Mon Sep 17 00:00:00 2001 From: Westly Wright Date: Fri, 8 Nov 2019 11:01:22 -0700 Subject: [PATCH 05/12] network plugin not editable rancher/rancher#23999 --- .../addon/components/check-override-allowed/template.hbs | 4 +++- lib/shared/addon/components/form-network-config/template.hbs | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/shared/addon/components/check-override-allowed/template.hbs b/lib/shared/addon/components/check-override-allowed/template.hbs index 50792be0d..9a1c0fb03 100644 --- a/lib/shared/addon/components/check-override-allowed/template.hbs +++ b/lib/shared/addon/components/check-override-allowed/template.hbs @@ -1,6 +1,8 @@ {{#if applyClusterTemplate}} {{#if (has-override questions=questions paramName=paramName)}} - {{yield}} + {{yield (hash + hasOverride=true + )}} {{else}}
{{#if value}} diff --git a/lib/shared/addon/components/form-network-config/template.hbs b/lib/shared/addon/components/form-network-config/template.hbs index a5e20ec89..3f38c86c9 100644 --- a/lib/shared/addon/components/form-network-config/template.hbs +++ b/lib/shared/addon/components/form-network-config/template.hbs @@ -16,9 +16,10 @@ @paramName="rancherKubernetesEngineConfig.network.plugin" @clusterTemplateRevision={{clusterTemplateRevision.clusterConfig}} @applyClusterTemplate={{applyClusterTemplate}} + as |override| > {{#input-or-display - editable=(eq mode "new") + editable=(or (and (eq mode "new") (or (not applyClusterTemplate) override.hasOverride)) clusterTemplateCreate) value=config.network.plugin }} {{new-select From dcb0379cf49f953eafabfcf1dd02b426fe3c8666 Mon Sep 17 00:00:00 2001 From: Westly Wright Date: Fri, 8 Nov 2019 12:42:27 -0700 Subject: [PATCH 06/12] Remove exec call that happens to early while reviewing rancher/ui#23993 i stumbled on a case where opening the pod logs would cause an undefined error to crash the local ui server. `exec` is called correctly from the `watchReconnect` observer which needs to happen first as it parses the container name. If we call exec before we have a container name we get an undefined error --- app/components/container-logs/component.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/components/container-logs/component.js b/app/components/container-logs/component.js index b2beb2340..0e46af755 100644 --- a/app/components/container-logs/component.js +++ b/app/components/container-logs/component.js @@ -61,7 +61,6 @@ export default Component.extend({ lastScrollTop = scrollTop; }); - this.exec(); var btn = $('.scroll-bottom')[0]; // eslint-disable-line if ( btn ) { From a82abc29e04bb64070fd8b483939f7077d2d0a74 Mon Sep 17 00:00:00 2001 From: Cody Jackson Date: Fri, 8 Nov 2019 13:50:38 -0700 Subject: [PATCH 07/12] Make the select arrow visible on :hover rancher/rancher#23987 --- app/styles/components/_forms.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/components/_forms.scss b/app/styles/components/_forms.scss index 92aeaaec7..b03a03f89 100644 --- a/app/styles/components/_forms.scss +++ b/app/styles/components/_forms.scss @@ -112,7 +112,7 @@ select { &:hover { border-color: $input-bg-hover; - background: rgba($input-bg-hover, .2); + background-color: rgba($input-bg-hover, .2); &::placeholder { color: rgba($input-color-placeholder, .35); } From 322386978891d526810b5c85d2c7302103483884 Mon Sep 17 00:00:00 2001 From: Westly Wright Date: Fri, 8 Nov 2019 16:17:20 -0700 Subject: [PATCH 08/12] make cloud provider uneditable rancher/rancher#24008 --- lib/shared/addon/components/cru-cloud-provider/template.hbs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/shared/addon/components/cru-cloud-provider/template.hbs b/lib/shared/addon/components/cru-cloud-provider/template.hbs index be0fa5692..0cd79f5b9 100644 --- a/lib/shared/addon/components/cru-cloud-provider/template.hbs +++ b/lib/shared/addon/components/cru-cloud-provider/template.hbs @@ -40,7 +40,7 @@ @computedState={{not (eq selectedCloudProvider "none")}} > {{#input-or-display - editable=(not-eq mode "view") + editable=(or (and (eq mode "new") (or (not applyClusterTemplate) (and (eq mode "new") selectedCloudProviderOverrideAvailable))) clusterTemplateCreate) value=selectedCloudProvider }}
@@ -134,7 +134,7 @@
{{/input-or-display}} - {{#unless (eq selectedCloudProvider "none")}} + {{#if (and (not-eq selectedCloudProvider "none") (eq mode "new"))}}
- {{/unless}} + {{/if}}
{{#if (eq selectedCloudProvider "azure")}} From 65fb8f49ab6cfbfdbca69f030af71be1b24bc865 Mon Sep 17 00:00:00 2001 From: Cody Jackson Date: Fri, 8 Nov 2019 16:27:25 -0700 Subject: [PATCH 09/12] Add datastore cluster as an option for vsphere rancher/rancher#24002 --- .../driver-vmwarevsphere/component.js | 37 ++++++++++++++- .../driver-vmwarevsphere/template.hbs | 46 ++++++++++++++----- translations/en-us.yaml | 3 ++ 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/lib/nodes/addon/components/driver-vmwarevsphere/component.js b/lib/nodes/addon/components/driver-vmwarevsphere/component.js index 8ff2c9257..63634321d 100644 --- a/lib/nodes/addon/components/driver-vmwarevsphere/component.js +++ b/lib/nodes/addon/components/driver-vmwarevsphere/component.js @@ -135,7 +135,7 @@ export default Component.extend(NodeDriver, { this.initCustomAttributes(); this.initTag(); this.initNetwork(); - set(this, 'floof', 'floof'); + this.initUseDataStoreCluster(); }, actions: { @@ -167,6 +167,12 @@ export default Component.extend(NodeDriver, { return keyContent.filter((keyContent) => { return keyValuePairs.findIndex((kvp) => kvp.key === keyContent.value) === -1; }); + }, + toggleUseDataStoreCluster(value) { + set(this, 'config.useDataStoreCluster', value); + const clearKey = value ? 'config.datastore' : 'config.datastoreCluster'; + + set(this, clearKey, ''); } }, @@ -237,6 +243,16 @@ export default Component.extend(NodeDriver, { return this.mapPathOptionsToContent(options); }), + dataStoreClusterContent: computed('config.datacenter', async function() { + const options = await this.requestOptions( + 'data-store-clusters', + get(this, 'model.cloudCredentialId'), + get(this, 'config.datacenter') + ); + + return this.mapPathOptionsToContent(options); + }), + folderContent: computed('config.datacenter', async function() { const options = await this.requestOptions( 'folders', @@ -325,6 +341,7 @@ export default Component.extend(NodeDriver, { let config = get(this, 'globalStore').createRecord({ type: CONFIG, + useDataStoreCluster: false, cpuCount: '2', memorySize: '2048', diskSize: '20000', @@ -407,6 +424,17 @@ export default Component.extend(NodeDriver, { } }, + initUseDataStoreCluster() { + const useDataStoreCluster = !!get(this, 'config.datastoreCluster'); + + set(this, 'config.useDataStoreCluster', useDataStoreCluster); + + // Only one should be set at a time + const clearKey = useDataStoreCluster ? 'config.datastore' : 'config.datastoreCluster'; + + set(this, clearKey, ''); + }, + updateVappOptions(opts) { set(this, 'config.vappIpprotocol', opts.vappIpprotocol); set(this, 'config.vappIpallocationpolicy', opts.vappIpallocationpolicy); @@ -419,6 +447,13 @@ export default Component.extend(NodeDriver, { const configCustomAttribute = get(this, 'customAttribute').map((kvp) => `${ kvp.key }=${ kvp.value }`); set(this, 'config.customAttribute', configCustomAttribute); + + const clearKey = get(this, 'config.useDataStoreCluster') + ? 'config.datastore' + : 'config.datastoreCluster'; + + set(this, clearKey, ''); + const vappMode = get(this, 'vappMode') if (vappMode === VAPP_MODE_DISABLED) { diff --git a/lib/nodes/addon/components/driver-vmwarevsphere/template.hbs b/lib/nodes/addon/components/driver-vmwarevsphere/template.hbs index 85a5819cc..f5ee829d5 100644 --- a/lib/nodes/addon/components/driver-vmwarevsphere/template.hbs +++ b/lib/nodes/addon/components/driver-vmwarevsphere/template.hbs @@ -73,17 +73,41 @@
- -

- {{t "nodeDriver.vmwarevsphere.dataStore.help"}} -

- + {{#if config.useDataStoreCluster}} + +

+ {{t "nodeDriver.vmwarevsphere.dataStore.cluster.help"}} +

+ + {{else}} + +

+ {{t "nodeDriver.vmwarevsphere.dataStore.help"}} +

+ + {{/if}}
diff --git a/translations/en-us.yaml b/translations/en-us.yaml index db1fbb1ce..816e5da69 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -8314,6 +8314,9 @@ nodeDriver: valuePlaceholder: "e.g. VM Network" help: "Networks to attach VM to" dataStore: + cluster: + tooltip: Use datastore cluster? + help: "Datastore cluster to create VM on" label: Data Store placeholder: "e.g. datastore_cluster_name/datastore_name" help: "Datastore to create VM disk on" From 01df2b7f61a14f9f38af244cab691709c8b339b9 Mon Sep 17 00:00:00 2001 From: Westly Wright Date: Mon, 11 Nov 2019 14:24:19 -0700 Subject: [PATCH 10/12] Fix node/pod counts that were not updating correctly rancher/rancher#23866 rancher/rancher#24034 --- lib/shared/addon/mixins/subscribe.js | 12 ++++++++---- package.json | 3 ++- yarn.lock | 9 ++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/shared/addon/mixins/subscribe.js b/lib/shared/addon/mixins/subscribe.js index bed29f67a..2547e77ea 100644 --- a/lib/shared/addon/mixins/subscribe.js +++ b/lib/shared/addon/mixins/subscribe.js @@ -1,4 +1,4 @@ -import { schedule, cancel, later } from '@ember/runloop'; +import { schedule, cancel, later, next } from '@ember/runloop'; import Mixin from '@ember/object/mixin'; import { get, set, setProperties } from '@ember/object'; import Ember from 'ember'; @@ -121,17 +121,17 @@ export default Mixin.create({ // console.log(this.label, (forceRemove ? 'Remove' : 'Change'), type +':'+ event.data.id, projectId); - if ( get(this, 'updateProjectStore') && projectId && projectStore.hasType(type) ) { + if ( get(this, 'updateProjectStore') && projectId && checkStoreHasType(projectStore, type) ) { // console.log(' Update project store', type, event.data.id, projectId); updateStore(projectStore, event.data, forceRemove); } - if ( get(this, 'updateClusterStore') && clusterStore.hasType(type) ) { + if ( get(this, 'updateClusterStore') && checkStoreHasType(clusterStore, type) ) { // console.log(' Update cluster store', type, event.data.id); updateStore(clusterStore, event.data, forceRemove); } - if ( get(this, 'updateGlobalStore') && globalStore.hasType(type) ) { + if ( get(this, 'updateGlobalStore') && checkStoreHasType(globalStore, type)) { // console.log(' Update global store', type, event.data.id); updateStore(globalStore, event.data, forceRemove); } @@ -143,6 +143,10 @@ export default Mixin.create({ Ember.endPropertyChanges(); // console.log(`Processed ${count} ${this.label} change events`); + function checkStoreHasType(store, type) { + return next(() => store.hasType(type)); + } + function updateStore(store, data, forceRemove = false) { // Update the state to removed before we remove it from store if ( forceRemove ) { diff --git a/package.json b/package.json index eb957b398..413fc65da 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "devDependencies": { "@ember/jquery": "^0.6.0", "@ember/optional-features": "^0.7.0", - "@rancher/ember-api-store": "2.9.4", + "@rancher/ember-api-store": "2.9.6", "ansi_up": "^2.0.2", "async": "2.1.2", "babel-eslint": "^9.0.0", @@ -65,6 +65,7 @@ "ember-drag-drop": "^0.4.7", "ember-engines": "^0.8.2", "ember-export-application-global": "^2.0.0", + "ember-fetch": "^6.5.1", "ember-flatpickr": "^2.7.0", "ember-href-to": "^2.0.1", "ember-intl": "^4.2.0", diff --git a/yarn.lock b/yarn.lock index da3bf144f..c33c6cce0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1121,17 +1121,16 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@rancher/ember-api-store@2.9.4": - version "2.9.4" - resolved "https://registry.yarnpkg.com/@rancher/ember-api-store/-/ember-api-store-2.9.4.tgz#84920e719ce2c0306668db7fd031138c1fec8b72" - integrity sha512-Jef11/K9qGZyrSbufnlfDhY9WNfuo1th+azjRjDNwGv/7wrKiOxOquGmdKViWQXxjy8Hvm7RwsjKK5h2f85wpQ== +"@rancher/ember-api-store@2.9.6": + version "2.9.6" + resolved "https://registry.yarnpkg.com/@rancher/ember-api-store/-/ember-api-store-2.9.6.tgz#296195610a418c860dc98325e8aacaa53a159b62" + integrity sha512-SkJsDQiBPRzjjggJLT3mLPMJJBTKRTQbSjNdUoS7wjMWGqOzp+/XYtF8raov3cfYRja2D9bPV1HJo8OW2cF7dA== dependencies: babel-eslint "^10.0.1" broccoli-file-creator "^2.1.1" ember-auto-import "^1.2.19" ember-cli-babel "^7.1.2" ember-cookies "^0.4.0" - ember-fetch "^6.5.1" eslint "^4.19.1" node-fetch "^2.3.0" set-cookie-parser "^2.2.1" From e8071c2268ccac5b3bf0cfbed3b4fcc357e58d5a Mon Sep 17 00:00:00 2001 From: Cody Jackson Date: Mon, 11 Nov 2019 15:41:02 -0700 Subject: [PATCH 11/12] Show arrow on select:focus Make the arrow visible for select components when the component is focused. rancher/rancher#23987 --- app/styles/components/_forms.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/components/_forms.scss b/app/styles/components/_forms.scss index b03a03f89..9a0a3e4d5 100644 --- a/app/styles/components/_forms.scss +++ b/app/styles/components/_forms.scss @@ -126,7 +126,7 @@ select { } } &:focus { - background: rgba($input-border-focus, .2); + background-color: rgba($input-border-focus, .2); border-color: $input-border-focus; transition: ease-in-out all .25s; &::placeholder { From 8c9789f82fa47fa709d3164426072bafe496f3b5 Mon Sep 17 00:00:00 2001 From: Westly Wright Date: Tue, 12 Nov 2019 15:45:41 -0700 Subject: [PATCH 12/12] check answers required fields for mc app rancher/rancher#24057 --- app/models/templateversion.js | 4 ++-- .../addon/components/new-multi-cluster-app/component.js | 9 +++++++-- .../addon/components/new-multi-cluster-app/template.hbs | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/models/templateversion.js b/app/models/templateversion.js index 7961f2d0e..871ace952 100644 --- a/app/models/templateversion.js +++ b/app/models/templateversion.js @@ -57,7 +57,7 @@ export default Resource.extend({ return out; }), - validationErrors() { + validationErrors(answersMap) { const { intl, allQuestions, valuesYaml } = this; @@ -96,7 +96,7 @@ export default Resource.extend({ } else { if ( filteredQuestions ) { filteredQuestions.forEach((item) => { - if ( item.required && item.type !== 'boolean' && !item.answer ) { + if ( item.required && item.type !== 'boolean' && isEmpty(answersMap[item.variable]) ) { errors.push(intl.t('validation.required', { key: item.label })); } diff --git a/lib/global-admin/addon/components/new-multi-cluster-app/component.js b/lib/global-admin/addon/components/new-multi-cluster-app/component.js index 2e4997b7e..8ec237be5 100644 --- a/lib/global-admin/addon/components/new-multi-cluster-app/component.js +++ b/lib/global-admin/addon/components/new-multi-cluster-app/component.js @@ -89,6 +89,7 @@ export default Component.extend(NewOrEdit, CatalogApp, { selectedTemplateUrl: null, multiClusterApp: { targets: [], }, }, + mcAppIsSaving: false, overridesHeaders: OVERRIDE_HEADERS, @@ -277,6 +278,10 @@ export default Component.extend(NewOrEdit, CatalogApp, { }, updateAnswerOverrides: observer('selectedTemplateModel', 'multiClusterApp.answers.@each.{values}', function() { + if (this.mcAppSaving) { + return; + } + let { selectedTemplateModel = {} } = this; const questions = get(selectedTemplateModel, 'questions') @@ -363,7 +368,7 @@ export default Component.extend(NewOrEdit, CatalogApp, { } }), - templateOrHelmChartQuestions: computed('selectedTemplateModel', function() { + templateOrHelmChartQuestions: computed('selectedTemplateModel', 'selectedTemplateModel.allQuestions.@each.{answer,variable}', function() { let { selectedTemplateModel, multiClusterApp } = this; let nueQuestions = []; @@ -587,7 +592,7 @@ export default Component.extend(NewOrEdit, CatalogApp, { this._super(...arguments); const errors = get(this, 'errors') || []; - errors.pushObjects(get(this, 'selectedTemplateModel').validationErrors() || []); + errors.pushObjects(get(this, 'selectedTemplateModel').validationErrors(this.answers) || []); errors.pushObjects(this.validateTargetsProjectIds()); set(this, 'errors', errors.uniq()); diff --git a/lib/global-admin/addon/components/new-multi-cluster-app/template.hbs b/lib/global-admin/addon/components/new-multi-cluster-app/template.hbs index 156075e5d..a95ed1fcc 100644 --- a/lib/global-admin/addon/components/new-multi-cluster-app/template.hbs +++ b/lib/global-admin/addon/components/new-multi-cluster-app/template.hbs @@ -408,6 +408,7 @@ {{save-cancel createLabel=(if editing saveUpgrade saveNew) save=(action "save") + saving=mcAppSaving cancel=(action "cancel") }}