Merge pull request #3034 from loganhz/istio-catalog

Bug fix for enabling istio and registry page
This commit is contained in:
Westly Wright 2019-06-05 10:00:22 -07:00 committed by GitHub
commit 3e647571b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 706 additions and 529 deletions

View File

@ -14,13 +14,12 @@ import { parseSi } from 'shared/utils/parse-unit'
const INTERNAL = 'internal'
const INGRESS_HOSTS_CORE = 'expose.ingress.host';
const DEFAULT_ADMIN_PASSWORD = 'Harbor12345';
const APP_VERSION = 'catalog://?catalog=system-library&template=harbor&version=1.7.5-rancher1';
const STORAGE_TYPE = ['filesystem', 's3'];
const S3_REGION = C.AWS_S3_REGIONS;
const ACCESS_MODE = ['ReadWriteOnce']
const RDISE_EXTENNAL_KEYS = ['host', 'port', 'coreDatabaseIndex', 'jobserviceDatabaseIndex', 'registryDatabaseIndex', 'password']
const RDISE_EXTENNAL_KEYS = ['host', 'port', 'jobserviceDatabaseIndex', 'registryDatabaseIndex', 'password']
const PERSISTENCE_KEYS = ['existingClaim', 'size', 'storageClass']
const DATABASE_EXTERNAL_KEYS = ['host', 'port', 'username', 'password', 'coreDatabase', 'clairDatabase', 'notaryServerDatabase', 'notarySignerDatabase', 'sslmode']
const S3_KEYS = ['region', 'bucket', 'accesskey', 'secretkey', 'regionendpoint']
@ -48,10 +47,15 @@ const CLAIR_REQUEST_MEM = 'clair.resources.requests.memory'
const CLAIR_LIMIT_CPU = 'clair.resources.limits.cpu'
const CLAIR_LIMIT_MEM = 'clair.resources.limits.memory'
const NOTARY_REQUEST_CPU = 'notary.resources.requests.cpu'
const NOTARY_REQUEST_MEM = 'notary.resources.requests.memory'
const NOTARY_LIMIT_CPU = 'notary.resources.limits.cpu'
const NOTARY_LIMIT_MEM = 'notary.resources.limits.memory'
const NOTARY_REQUEST_CPU = 'notary.server.resources.requests.cpu'
const NOTARY_REQUEST_MEM = 'notary.server.resources.requests.memory'
const NOTARY_LIMIT_CPU = 'notary.server.resources.limits.cpu'
const NOTARY_LIMIT_MEM = 'notary.server.resources.limits.memory'
const SIGNER_REQUEST_CPU = 'notary.signer.resources.requests.cpu'
const SIGNER_REQUEST_MEM = 'notary.signer.resources.requests.memory'
const SIGNER_LIMIT_CPU = 'notary.signer.resources.limits.cpu'
const SIGNER_LIMIT_MEM = 'notary.signer.resources.limits.memory'
const REGISTRY_NODE_SELECTOR_PREFIX = 'registry.nodeSelector.'
const DATABASE_NODE_SELECTOR_PREFIX = 'database.internal.nodeSelector.'
@ -59,7 +63,7 @@ const REDIS_NODE_SELECTOR_PREFIX = 'redis.internal.nodeSelector.'
const CLAIR_NODE_SELECTOR_PREFIX = 'clair.nodeSelector.'
const NOTARY_NODE_SELECTOR_PREFIX = 'notary.nodeSelector.'
const WORKLOADS = ['database', 'redis', 'registry', 'clair', 'notary']
const WORKLOADS = ['database', 'redis', 'registry', 'clair', 'notaryServer', 'notarySigner']
const HIDDEN_KEYS = {
'externalURL': `https://${ window.location.host }`,
@ -91,10 +95,14 @@ const ANSWER_TO_CONFIG = {
[CLAIR_REQUEST_MEM]: 'clairRequestMemory',
[CLAIR_LIMIT_CPU]: 'clairLimitCpu',
[CLAIR_LIMIT_MEM]: 'clairLimitMemory',
[NOTARY_REQUEST_CPU]: 'notaryRequestCpu',
[NOTARY_REQUEST_MEM]: 'notaryRequestMemory',
[NOTARY_LIMIT_CPU]: 'notaryLimitCpu',
[NOTARY_LIMIT_MEM]: 'notaryLimitMemory',
[NOTARY_REQUEST_CPU]: 'notaryServerRequestCpu',
[NOTARY_REQUEST_MEM]: 'notaryServerRequestMemory',
[NOTARY_LIMIT_CPU]: 'notaryServerLimitCpu',
[NOTARY_LIMIT_MEM]: 'notaryServerLimitMemory',
[SIGNER_REQUEST_CPU]: 'notarySignerRequestCpu',
[SIGNER_REQUEST_MEM]: 'notarySignerRequestMemory',
[SIGNER_LIMIT_CPU]: 'notarySignerLimitCpu',
[SIGNER_LIMIT_MEM]: 'notarySignerLimitMemory',
}
export default Component.extend(CrudCatalog, ReservationCheck, {
@ -111,7 +119,9 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
nsExists: true,
config: null,
level: 'cluster',
level: 'cluster',
clusterLevelMinCpu: 500,
clusterLevelMinMemory: 500,
init() {
this._super(...arguments);
@ -165,6 +175,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case CLAIR_LIMIT_CPU:
case NOTARY_REQUEST_CPU:
case NOTARY_LIMIT_CPU:
case SIGNER_REQUEST_CPU:
case SIGNER_LIMIT_CPU:
answers[key] = `${ value }m`
break;
case DATABASE_REQUEST_MEM:
@ -177,6 +189,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case CLAIR_LIMIT_MEM:
case NOTARY_REQUEST_MEM:
case NOTARY_LIMIT_MEM:
case SIGNER_REQUEST_MEM:
case SIGNER_LIMIT_MEM:
answers[key] = `${ value }Mi`
break;
default:
@ -214,11 +228,13 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
answers[key] = get(this, key)
})
answers['redis.external.coreDatabaseIndex'] = '0'
} else if (redisType === INTERNAL) {
this.willSavePersistence(answers, 'redis')
}
WORKLOADS.map((component) => {
['registry', 'database', 'redis', 'clair', 'notary'].map((component) => {
(get(this, `${ component }NodeSelectors`) || []).map((selector) => {
let { key, value } = selector
@ -271,17 +287,18 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
set(this, `${ w }NodeSelectors`, [])
}
});
if (get(this, 'config.storageType') === 's3') {
set(this, `registryNodeSelectors`, [])
}
set(this, `registryNodeSelectors`, [])
this.notifyPropertyChange('requestsCpu')
this.notifyPropertyChange('requestsMemory')
this.notifyPropertyChange('saveDisabled')
}),
dockerLogin: computed('app.answers', function() {
const url = (get(this, 'app.answers') || HIDDEN_KEYS)[INGRESS_HOSTS_CORE];
const username = get(this, 'showForm') ? 'admin' : 'USERNAME'
return `docker login --username=admin ${ url }`;
return `docker login --username=${ username } ${ url }`;
}),
dockerPull: computed('app.answers', function() {
@ -344,12 +361,14 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}))
}),
requestsCpu: computed('config.redisRequestCpu', 'config.databaseRequestCpu', 'config.registryRequestCpu', 'config.notaryRequestCpu', 'config.calirRequestCpu', function() {
requestsCpu: computed('config.redisRequestCpu', 'config.databaseRequestCpu', 'config.registryRequestCpu', 'config.notaryServerRequestCpu', 'config.calirRequestCpu', 'config.notarySignerRequestCpu', function() {
return WORKLOADS
.filter((w) => {
if (['redis', 'database'].includes(w) && !get(this, `config.${ w }Enabled`)) {
if (['notaryServer', 'notarySigner'].includes(w) && !get(this, `config.notaryEnabled`)) {
return false
} else if (['notary', 'clair'].includes(w) && get(this, `config.${ w }Type`) === 'external') {
} else if (w === 'clair' && !get(this, `config.clairEnabled`)) {
return false
} else if (['redis', 'database'].includes(w) && get(this, `config.${ w }Type`) === 'external') {
return false
}
@ -360,12 +379,14 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}, 0)
}),
requestsMemory: computed('config.redisRequestMemory', 'config.databaseRequestMemory', 'config.registryRequestMemory', 'config.clairRequestMemory', 'config.notaryRequestMemory', function() {
requestsMemory: computed('config.redisRequestMemory', 'config.databaseRequestMemory', 'config.registryRequestMemory', 'config.clairRequestMemory', 'config.notaryServerRequestMemory', 'config.notarySignerRequestMemory', function() {
return WORKLOADS
.filter((w) => {
if (['redis', 'database'].includes(w) && !get(this, `config.${ w }Enabled`)) {
if (['notaryServer', 'notarySigner'].includes(w) && !get(this, `config.notaryEnabled`)) {
return false
} else if (['notary', 'clair'].includes(w) && get(this, `config.${ w }Type`) === 'external') {
} else if (w === 'clair' && !get(this, `config.clairEnabled`)) {
return false
} else if (['redis', 'database'].includes(w) && get(this, `config.${ w }Type`) === 'external') {
return false
}
@ -402,11 +423,13 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}
}),
saveDisabled: computed('globalRegistryWarning', 'databaseWarning', 'redisWarning', 'registryWarning', 'clairWarning', 'notaryWarning', function() {
return WORKLOADS.reduce((out, w) => {
if (['clair', 'notary'].includes(w) && !get(this, `config.${ w }Enabled`)) {
saveDisabled: computed('globalRegistryWarning', 'databaseWarning', 'redisWarning', 'registryWarning', 'clairWarning', 'notaryWarning', 'notarySignerWarning', 'notaryServerWarning', function() {
return [...WORKLOADS, 'notary'].reduce((out, w) => {
if (w === 'clair' && get(this, `config.clairEnabled`)) {
return out || (get(this, `${ w }Warning`) || false)
} else if (['database', 'redis'].includes(w) && !get(this, `config.${ w }Type`)) {
} else if (['database', 'redis'].includes(w) && get(this, `config.${ w }Type`) === 'internal') {
return out || (get(this, `${ w }Warning`) || false)
} else if (['notary', 'notaryServer', 'notarySigner'].includes(w) && get(this, `config.notaryEnabled`)) {
return out || (get(this, `${ w }Warning`) || false)
} else {
return out || (get(this, `${ w }Warning`) || false)
@ -414,38 +437,34 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}, false) || get(this, 'globalRegistryWarning')
}),
minCpu: computed('requestsCpu', 'clusterLevelMinCpu', 'projectLevelMinCpu', 'enabled', 'preRequestsCpu', function() {
let cpu = parseInt(get(this, 'requestsCpu') || 0, 10);
let preRequestsCpu = parseInt(get(this, 'preRequestsCpu') || 0, 10);
if ( isNaN(cpu) ) {
cpu = 0;
notarySchedulableNodes: computed('notaryNodeSelectors.[]', 'cluster.nodes.@each.{allocatable,requested}', 'config.notaryEnabled', function() {
if (!get(this, 'config.notaryEnabled')) {
return []
} else {
return this.getSchedulableNodes('notary')
}
if ( isNaN(preRequestsCpu) ) {
preRequestsCpu = 0
}
const minCpu = (get(this, 'level') === 'cluster' ? get(this, 'clusterLevelMinCpu') : get(this, 'projectLevelMinCpu'))
return get(this, 'enabled') ? cpu - preRequestsCpu : minCpu + cpu
}),
minMemory: computed('requestsMemory', 'clusterLevelMinMemory', 'projectLevelMinMemory', 'enabled', 'preRequestsMemory', function() {
let memory = parseInt(get(this, 'requestsMemory') || 0, 10);
let preRequestsMemory = parseInt(get(this, 'preRequestsMemory') || 0, 10);
insufficientNotaryCpu: computed(`notarySchedulableNodes.@each.{allocatable,requested}`, `config.notaryServerRequestCpu`, 'config.notarySignerRequestCpu', 'cluster.nodes.@each.{allocatable,requested}', function() {
const reservation = Math.max(parseInt(get(this, 'config.notaryServerRequestCpu') || '0'), parseInt(get(this, 'config.notarySignerRequestCpu') || '0'))
if ( isNaN(memory) ) {
memory = 0;
return this.getComponentInsufficient('notary', 'cpu', reservation)
}),
insufficientNotaryMemory: computed(`notarySchedulableNodes.@each.{allocatable,requested}`, `config.notaryServerRequestMemory`, 'config.notarySignerRequestMemory', 'cluster.nodes.@each.{allocatable,requested}', function() {
const reservation = Math.max(parseInt(get(this, 'config.notaryServerRequestMemory') || '0'), parseInt(get(this, 'config.notarySignerRequestMemory') || '0'))
return this.getComponentInsufficient('notary', 'memory', reservation)
}),
notaryWarning: computed(`insufficientNotaryCpu`, `insufficientNotaryMemory`, function() {
if (!get(this, 'config.notaryEnabled')) {
return
}
const componentCpu = Math.max(parseInt(get(this, 'config.notaryServerRequestCpu') || '0'), parseInt(get(this, 'config.notarySignerRequestCpu') || '0'))
const componentMemory = Math.max(parseInt(get(this, 'config.notaryServerRequestMemory') || '0'), parseInt(get(this, 'config.notarySignerRequestMemory') || '0'))
if ( isNaN(preRequestsMemory) ) {
preRequestsMemory = 0
}
const minMemory = (get(this, 'level') === 'cluster' ? get(this, 'clusterLevelMinMemory') : get(this, 'projectLevelMinMemory'))
return get(this, 'enabled') ? memory - preRequestsMemory : minMemory + memory
return this.getComponentWarning('notary', componentCpu, componentMemory, get(this, 'intl').t('globalRegistryPage.notaryAndSigner'))
}),
initConfig() {
@ -472,9 +491,7 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
notaryEnabled: true,
databaseType: INTERNAL,
redisType: INTERNAL,
secretKey: 'add-your-secret0',
storageType: 'filesystem',
password: DEFAULT_ADMIN_PASSWORD,
databaseRequestCpu: 100,
databaseRequestMemory: 256,
databaseLimitCpu: 500,
@ -491,10 +508,14 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
clairRequestMemory: 256,
clairLimitCpu: 500,
clairLimitMemory: 2048,
notaryRequestCpu: 100,
notaryRequestMemory: 256,
notaryLimitCpu: 200,
notaryLimitMemory: 512,
notaryServerRequestCpu: 100,
notaryServerRequestMemory: 256,
notaryServerLimitCpu: 500,
notaryServerLimitMemory: 2048,
notarySignerRequestCpu: 100,
notarySignerRequestMemory: 256,
notarySignerLimitCpu: 500,
notarySignerLimitMemory: 2048,
},
'database.external.sslmode': 'disable',
'database.external.coreDatabase': 'registry',
@ -559,10 +580,11 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
notaryNodeSelector[key] = value
});
const workloads = ['database.internal', 'redis.internal', 'registry.registry', 'clair', 'notary']
const workloads = this.getEnalbedWorkloads(answers)
const preRequestsCpu = workloads.reduce((all, current) => {
const value = answers[`${ current }.internal.resources.requests.cpu`]
const value = answers[`${ current }.resources.requests.cpu`]
return value ? all + convertToMillis(value) : all
}, 0)
@ -605,7 +627,7 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
return set(this, key, answers[key])
}
if (Object.keys(HIDDEN_KEYS).includes(key)) {
if (Object.keys(HIDDEN_KEYS).includes(key) || key === 'redis.external.coreDatabaseIndex') {
return
}
@ -623,6 +645,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case CLAIR_LIMIT_CPU:
case NOTARY_REQUEST_CPU:
case NOTARY_LIMIT_CPU:
case SIGNER_REQUEST_CPU:
case SIGNER_LIMIT_CPU:
value = convertToMillis(answers[key] || '0')
break;
case DATABASE_REQUEST_MEM:
@ -635,6 +659,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case CLAIR_LIMIT_MEM:
case NOTARY_REQUEST_MEM:
case NOTARY_LIMIT_MEM:
case SIGNER_REQUEST_MEM:
case SIGNER_LIMIT_MEM:
value = parseSi(answers[key] || '0', 1024) / 1048576
break;
default:
@ -666,9 +692,6 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
errors.pushObject(requiredError('globalRegistryPage.setting.adminPassword.label'))
}
if (!get(this, 'config.storageType')) {
errors.pushObject(requiredError('globalRegistryPage.config.storageType.label'))
}
const secretKey = get(this, 'config.secretKey')
if (secretKey && secretKey.length !== 16) {
@ -678,13 +701,16 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
if (get(this, 'config.storageType') === 'filesystem') {
errors.pushObjects(this.validatePV('registry'))
}
errors.pushObjects(this.validateLimitAndRequest('registry'))
if (get(this, 'config.databaseType') === INTERNAL) {
errors.pushObjects(this.validatePV('database'))
errors.pushObjects(this.validateLimitAndRequest('database'))
}
if (get(this, 'config.redisType') === INTERNAL) {
errors.pushObjects(this.validatePV('redis'))
errors.pushObjects(this.validateLimitAndRequest('redis'))
}
if (get(this, 'config.storageType') === 's3') {
@ -710,13 +736,23 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}
if (get(this, 'config.redisType') === 'external') {
RDISE_EXTENNAL_KEYS.map((k) => {
const key = `redis.external.${ k }`
RDISE_EXTENNAL_KEYS
.filter((k) => k !== 'password')
.map((k) => {
const key = `redis.external.${ k }`
if (!get(this, key)) {
errors.pushObject(requiredError(`globalRegistryPage.config.redis.external.${ k }.label`))
}
})
if (!get(this, key)) {
errors.pushObject(requiredError(`globalRegistryPage.config.redis.external.${ k }.label`))
}
})
}
if (get(this, 'config.notaryEnabled')) {
errors.pushObjects(this.validateLimitAndRequest('notaryServer'))
errors.pushObjects(this.validateLimitAndRequest('notarySigner'))
}
if (get(this, 'config.clairEnabled')) {
errors.pushObjects(this.validateLimitAndRequest('clair'))
}
return errors.uniq()
@ -748,8 +784,12 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
errors.pushObject(emptyError)
}
if (!get(this, `persistence.persistentVolumeClaim.${ component }.size`)) {
errors.pushObject(intl.t('globalRegistryPage.config.storageClass.sizeRequired', { component: ucFirst(component) }))
}
} else if (!get(this, `persistence.persistentVolumeClaim.${ component }.existingClaim`)){
errors.pushObject(requiredError(`globalRegistryPage.config.${ component }.existingClaim.label`))
errors.pushObject(requiredError(`clusterIstioPage.existingClaim.label`, { component: ucFirst(component) }))
}
return errors
@ -791,5 +831,24 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
return this.getComponentWarning(w)
}))
});
},
getEnalbedWorkloads(answers) {
let out = ['registry.registry']
if (answers['redis.type'] === 'internal') {
out.push('redis.internal')
}
if (answers['database.type'] === 'internal') {
out.push('database.internal')
}
if (answers['notary.enabled'] === 'true') {
out = [...out, 'notary.server', 'notary.signer']
}
if (answers['clair.enabled'] === 'true') {
out.push('clair')
}
return out;
}
});

View File

@ -75,34 +75,34 @@
{{#if showForm}}
<div class="box mb-10">
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-admin-password">
{{t "globalRegistryPage.setting.adminPassword.label"}}{{field-required}}
</label>
{{input
type="text"
class="conceal"
id="input-admin-password"
placeholder=(t "globalRegistryPage.setting.adminPassword.placeholder")
value=config.password
}}
{{#unless enabled}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-admin-password">
{{t "globalRegistryPage.setting.adminPassword.label"}}{{field-required}}
</label>
{{input
type="password"
id="input-admin-password"
placeholder=(t "globalRegistryPage.setting.adminPassword.placeholder")
value=config.password
}}
</div>
<div class="col span-6">
<label class="acc-label" for="input-secret-key">
{{t "globalRegistryPage.config.secretKey.label"}}
</label>
{{schema/input-password
id="input-secret-key"
value=config.secretKey
question=secretKeyQuestion
}}
<p class="help-block">
{{t "globalRegistryPage.config.secretKey.description"}}
</p>
</div>
</div>
<div class="col span-6">
<label class="acc-label" for="input-secret-key">
{{t "globalRegistryPage.config.secretKey.label"}}
</label>
{{schema/input-password
id="input-secret-key"
value=config.secretKey
question=secretKeyQuestion
conceal=true
}}
<p class="help-block">
{{t "globalRegistryPage.config.secretKey.description"}}
</p>
</div>
</div>
{{/unless}}
<div class="over-hr">
<span>
@ -113,13 +113,14 @@
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-storage-type">
{{t "globalRegistryPage.config.storageType.label"}}{{field-required}}
{{t "globalRegistryPage.config.storageType.label"}}
</label>
{{new-select
class="form-control"
id="input-storage-type"
content=storageTypeContent
value=config.storageType
disabled=enabled
}}
</div>
{{#if (eq config.storageType "s3")}}
@ -137,33 +138,15 @@
</div>
{{#if (eq config.storageType "filesystem")}}
{{catalog-persistence-row
component="registry"
useStorageClass=useRegistryStorageClass
config=persistence.persistentVolumeClaim.registry
storageClasses=storageClasses
persistentVolumeClaims=persistentVolumeClaims
}}
{{form-reservation
component="Registry"
requestCpu=config.registryRequestCpu
requestMemory=config.registryRequestMemory
limitCpu=config.registryLimitCpu
limitMemory=config.registryLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Registry"}}
</label>
{{form-key-value
changedArray=(action (mut registryNodeSelectors))
initialMap=registryNodeSelector
allowEmptyValue=true
addActionLabel="clusterIstioPage.nodeSelector.addSelectorLabel"
}}
</div>
</div>
{{#unless enabled}}
{{catalog-persistence-row
component="registry"
useStorageClass=useRegistryStorageClass
config=persistence.persistentVolumeClaim.registry
storageClasses=storageClasses
persistentVolumeClaims=persistentVolumeClaims
}}
{{/unless}}
{{else if (eq config.storageType "s3")}}
<div class="row">
<div class="col span-6">
@ -214,6 +197,27 @@
</div>
{{/if}}
{{form-reservation
component="Registry"
requestCpu=config.registryRequestCpu
requestMemory=config.registryRequestMemory
limitCpu=config.registryLimitCpu
limitMemory=config.registryLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Registry"}}
</label>
{{form-key-value
changedArray=(action (mut registryNodeSelectors))
initialMap=registryNodeSelector
allowEmptyValue=true
addActionLabel="clusterIstioPage.nodeSelector.addSelectorLabel"
}}
</div>
</div>
<div class="over-hr">
<span>
{{t "globalRegistryPage.config.header.postgresql"}}
@ -230,6 +234,7 @@
id="input-database-type"
content=databaseTypeContent
value=config.databaseType
disabled=enabled
}}
</div>
{{#if (eq config.databaseType "external")}}
@ -247,17 +252,20 @@
{{/if}}
</div>
{{#if (eq config.databaseType "internal")}}
{{catalog-persistence-row
component="database"
useStorageClass=useDatabaseStorageClass
config=persistence.persistentVolumeClaim.database
storageClasses=storageClasses
persistentVolumeClaims=persistentVolumeClaims
}}
{{#unless enabled}}
{{catalog-persistence-row
component="database"
useStorageClass=useDatabaseStorageClass
config=persistence.persistentVolumeClaim.database
storageClasses=storageClasses
persistentVolumeClaims=persistentVolumeClaims
}}
{{/unless}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-database-limit-cpu">
{{t "globalRegistryPage.config.databaseLimitCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -276,6 +284,7 @@
<div class="col span-6">
<label class="acc-label" for="input-database-limit-memory">
{{t "globalRegistryPage.config.databaseLimitMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -297,6 +306,7 @@
<div class="col span-6">
<label class="acc-label" for="input-database-request-cpu">
{{t "globalRegistryPage.config.databaseRequestCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -315,6 +325,7 @@
<div class="col span-6">
<label class="acc-label" for="input-database-request-memory">
{{t "globalRegistryPage.config.databaseRequestMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -454,12 +465,13 @@
class="form-control"
content=databaseTypeContent
value=config.redisType
disabled=enabled
}}
</div>
{{#if (eq config.redisType "external")}}
<div class="col span-6">
<label class="acc-label" for="input-redis-external-password">
{{t "globalRegistryPage.config.redis.external.password.label"}}{{field-required}}
{{t "globalRegistryPage.config.redis.external.password.label"}}
</label>
{{input
type="password"
@ -472,18 +484,21 @@
{{/if}}
</div>
{{#if (eq config.redisType "internal")}}
{{catalog-persistence-row
component="redis"
useStorageClass=useRedisStorageClass
config=persistence.persistentVolumeClaim.redis
storageClasses=storageClasses
persistentVolumeClaims=persistentVolumeClaims
}}
{{#unless enabled}}
{{catalog-persistence-row
component="redis"
useStorageClass=useRedisStorageClass
config=persistence.persistentVolumeClaim.redis
storageClasses=storageClasses
persistentVolumeClaims=persistentVolumeClaims
}}
{{/unless}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-redis-limit-cpu">
{{t "globalRegistryPage.config.redisLimitCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -502,6 +517,7 @@
<div class="col span-6">
<label class="acc-label" for="input-redis-limit-memory">
{{t "globalRegistryPage.config.redisLimitMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -523,6 +539,7 @@
<div class="col span-6">
<label class="acc-label" for="input-redis-request-cpu">
{{t "globalRegistryPage.config.redisRequestCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -541,6 +558,7 @@
<div class="col span-6">
<label class="acc-label" for="input-redis-request-memory">
{{t "globalRegistryPage.config.redisRequestMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -595,16 +613,6 @@
</div>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-redis-external-coredatabaseindex">
{{t "globalRegistryPage.config.redis.external.coreDatabaseIndex.label"}}{{field-required}}
</label>
{{schema/input-string
id="input-redis-external-coredatabaseindex"
value=redis.external.coreDatabaseIndex
placeholder=(t "globalRegistryPage.config.redis.external.coreDatabaseIndex.placeholder")
}}
</div>
<div class="col span-6">
<label class="acc-label" for="input-redis-external-jobservicedatabaseindex">
{{t "globalRegistryPage.config.redis.external.jobserviceDatabaseIndex.label"}}{{field-required}}
@ -615,8 +623,6 @@
placeholder=(t "globalRegistryPage.config.redis.external.jobserviceDatabaseIndex.placeholder")
}}
</div>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-redis-external-registrydatabaseindex">
{{t "globalRegistryPage.config.redis.external.registryDatabaseIndex.label"}}{{field-required}}
@ -689,16 +695,23 @@
{{#if config.notaryEnabled}}
{{form-reservation
component="Notary"
requestCpu=config.notaryRequestCpu
requestMemory=config.notaryRequestMemory
limitCpu=config.notaryLimitCpu
limitMemory=config.notaryLimitMemory
component="notaryServer"
requestCpu=config.notaryServerRequestCpu
requestMemory=config.notaryServerRequestMemory
limitCpu=config.notaryServerLimitCpu
limitMemory=config.notaryServerLimitMemory
}}
{{form-reservation
component="notarySigner"
requestCpu=config.notarySignerRequestCpu
requestMemory=config.notarySignerRequestMemory
limitCpu=config.notarySignerLimitCpu
limitMemory=config.notarySignerLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Notary"}}
{{t "clusterIstioPage.nodeSelector.helpText" component=(t 'globalRegistryPage.notaryAndSigner')}}
</label>
{{form-key-value
changedArray=(action (mut notaryNodeSelectors))
@ -727,14 +740,12 @@
{{/advanced-section}}
</div>
{{#if (or globalRegistryWarning registryWarning databaseWarning redisWarning clairWarning notaryWarning)}}
{{#if (or globalRegistryWarning registryWarning databaseWarning redisWarning clairWarning notaryServerWarning notarySignerWarning notaryWarning)}}
{{#banner-message color="bg-warning"}}
{{#if globalRegistryWarning}}
<p>{{globalRegistryWarning}}</p>
{{else}}
{{#if (eq config.storageType "filesystem")}}
<p>{{registryWarning}}</p>
{{/if}}
<p>{{registryWarning}}</p>
{{#if (eq config.databaseType "internal")}}
<p>{{databaseWarning}}</p>
{{/if}}
@ -745,6 +756,8 @@
<p>{{clairWarning}}</p>
{{/if}}
{{#if config.notaryEnabled}}
<p>{{notaryServerWarning}}</p>
<p>{{notarySignerWarning}}</p>
<p>{{notaryWarning}}</p>
{{/if}}
{{/if}}

View File

@ -43,6 +43,11 @@ const MIXER_LIMIT_CPU = 'mixer.telemetry.resources.limits.cpu'
const MIXER_LIMIT_MEM = 'mixer.telemetry.resources.limits.memory'
const MIXER_NODE_SELECTOR_PREFIX = 'mixer.nodeSelector.'
const POLICY_REQUEST_CPU = 'mixer.policy.resources.requests.cpu'
const POLICY_REQUEST_MEM = 'mixer.policy.resources.requests.memory'
const POLICY_LIMIT_CPU = 'mixer.policy.resources.limits.cpu'
const POLICY_LIMIT_MEM = 'mixer.policy.resources.limits.memory'
const GRAFANA_REQUEST_CPU = 'grafana.resources.requests.cpu'
const GRAFANA_REQUEST_MEM = 'grafana.resources.requests.memory'
const GRAFANA_LIMIT_CPU = 'grafana.resources.limits.cpu'
@ -55,10 +60,10 @@ const GATEWAY_LIMIT_CPU = 'gateways.istio-ingressgateway.resources.limits.cpu'
const GATEWAY_LIMIT_MEM = 'gateways.istio-ingressgateway.resources.limits.memory'
const GATEWAY_NODE_SELECTOR_PREFIX = 'gateways.istio-ingressgateway.nodeSelector.'
const TRACING_REQUEST_CPU = 'tracing.resources.requests.cpu'
const TRACING_REQUEST_MEM = 'tracing.resources.requests.memory'
const TRACING_LIMIT_CPU = 'tracing.resources.limits.cpu'
const TRACING_LIMIT_MEM = 'tracing.resources.limits.memory'
const TRACING_REQUEST_CPU = 'tracing.jaeger.resources.requests.cpu'
const TRACING_REQUEST_MEM = 'tracing.jaeger.resources.requests.memory'
const TRACING_LIMIT_CPU = 'tracing.jaeger.resources.limits.cpu'
const TRACING_LIMIT_MEM = 'tracing.jaeger.resources.limits.memory'
const TRACING_NODE_SELECTOR_PREFIX = 'tracing.nodeSelector.'
const ANSWER_TO_CONFIG = {
@ -78,10 +83,10 @@ const ANSWER_TO_CONFIG = {
[PROMETHEUS_LIMIT_MEM]: 'prometheusLimitMemory',
[PROMETHEUS_REQUEST_CPU]: 'prometheusRequestCpu',
[PROMETHEUS_LIMIT_CPU]: 'prometheusLimitCpu',
[MIXER_REQUEST_MEM]: 'mixerRequestMemory',
[MIXER_LIMIT_MEM]: 'mixerLimitMemory',
[MIXER_REQUEST_CPU]: 'mixerRequestCpu',
[MIXER_LIMIT_CPU]: 'mixerLimitCpu',
[MIXER_REQUEST_MEM]: 'mixerTelemetryRequestMemory',
[MIXER_LIMIT_MEM]: 'mixerTelemetryLimitMemory',
[MIXER_REQUEST_CPU]: 'mixerTelemetryRequestCpu',
[MIXER_LIMIT_CPU]: 'mixerTelemetryLimitCpu',
'pilot.traceSampling': 'traceSampling',
'mixer.policy.enabled': 'mixerPolicyEnabled',
'mtls.enabled': 'mtlsEnabled',
@ -97,6 +102,10 @@ const ANSWER_TO_CONFIG = {
[GATEWAY_REQUEST_MEM]: 'gatewayRequestMemory',
[GATEWAY_LIMIT_CPU]: 'gatewayLimitCpu',
[GATEWAY_LIMIT_MEM]: 'gatewayLimitMemory',
[POLICY_REQUEST_MEM]: 'mixerPolicyRequestMemory',
[POLICY_LIMIT_MEM]: 'mixerPolicyLimitMemory',
[POLICY_REQUEST_CPU]: 'mixerPolicyRequestCpu',
[POLICY_LIMIT_CPU]: 'mixerPolicyLimitCpu',
}
const HIDDEN_KEYS = {
@ -122,7 +131,7 @@ const NODE_PORT_KEYS = {
'gateways.istio-ingressgateway.ports[1].port': 443,
}
const WORKLOADS = ['prometheus', 'mixer', 'tracing', 'gateway', 'grafana', 'pilot']
const WORKLOADS = ['prometheus', 'mixerTelemetry', 'tracing', 'gateway', 'grafana', 'pilot', 'mixerPolicy']
export default Component.extend(CrudCatalog, ReservationCheck, {
scope: service(),
@ -135,6 +144,9 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
nsName: 'istio-system',
appVersion: APP_VERSION,
clusterLevelMinCpu: 500,
clusterLevelMinMemory: 500,
level: alias('scope.currentPageScope'),
cluster: alias('scope.currentCluster'),
@ -189,6 +201,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case TRACING_LIMIT_CPU:
case GATEWAY_REQUEST_CPU:
case GATEWAY_LIMIT_CPU:
case POLICY_REQUEST_CPU:
case POLICY_LIMIT_CPU:
answers[key] = `${ value }m`
break;
case PILOT_REQUEST_MEM:
@ -203,6 +217,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case TRACING_LIMIT_MEM:
case GATEWAY_REQUEST_MEM:
case GATEWAY_LIMIT_MEM:
case POLICY_REQUEST_MEM:
case POLICY_LIMIT_MEM:
answers[key] = `${ value }Mi`
break;
case PROMETHEUS_RETENTION:
@ -217,7 +233,7 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
this.willSavePersistence(answers, 'grafana')
}
WORKLOADS.map((component) => {
['prometheus', 'tracing', 'gateway', 'grafana', 'pilot', 'mixer'].map((component) => {
(get(this, `${ component }NodeSelectors`) || []).map((selector) => {
let { key, value } = selector
@ -251,14 +267,16 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
},
},
workloadEnabledChange: observer('config.tracingEnabled', 'config.grafanaEnabled', 'config.gatewayEnabled', function() {
workloadEnabledChange: observer('config.tracingEnabled', 'config.grafanaEnabled', 'config.gatewayEnabled', 'config.mixerPolicyEnabled', function() {
['tracing', 'grafana', 'gateway'].map((w) => {
if (!get(this, `config.${ w }Enabled`)) {
set(this, `${ w }NodeSelectors`, [])
}
})
this.notifyPropertyChange('saveDisabled')
this.notifyPropertyChange('requestsCpu')
this.notifyPropertyChange('requestsMemory')
this.notifyPropertyChange('saveDisabled')
}),
gatewayTypeContent: computed(() => {
@ -284,14 +302,16 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
return `/k8s/clusters/${ get(this, 'cluster.id') }/api/v1/namespaces/istio-system/services/http:prometheus-http:80/proxy/`
}),
saveDisabled: computed('prometheusWarning', 'mixerWarning', 'enabled', 'istioWarning', 'pilotWarning', 'tracingWarning', 'grafanaWarning', 'gatewayWarning', function() {
return WORKLOADS.reduce((out, w) => {
if (['gateway', 'tracing', 'grafana'].includes(w) && !get(this, `config.${ w }Enabled`)) {
saveDisabled: computed('prometheusWarning', 'mixerTelemetryWarning', 'enabled', 'istioWarning', 'pilotWarning', 'tracingWarning', 'grafanaWarning', 'gatewayWarning', 'mixerPolicyWarning', 'mixerWarning', function() {
return [...WORKLOADS, 'mixer'].reduce((out, w) => {
if (['gateway', 'tracing', 'grafana', 'mixerPolicy'].includes(w) && !get(this, `config.${ w }Enabled`)) {
return out || (get(this, `${ w }Warning`) || false)
} else if (w === 'mixerTelemetry') {
return out || (get(this, 'mixerTelemetryWarning') || false) || (get(this, 'mixerWarning') )
} else {
return out || (get(this, `${ w }Warning`) || false)
}
}, false) || get(this, 'istioWarning')
}, false) || (get(this, 'istioWarning') || false)
}),
istioWarning: computed('insufficientCpu', 'insufficientMemory', function() {
@ -320,40 +340,6 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}
}),
minCpu: computed('requestsCpu', 'clusterLevelMinCpu', 'projectLevelMinCpu', 'enabled', 'preRequestsCpu', function() {
let cpu = parseInt(get(this, 'requestsCpu') || 0, 10);
let preRequestsCpu = parseInt(get(this, 'preRequestsCpu') || 0, 10);
if ( isNaN(cpu) ) {
cpu = 0;
}
if ( isNaN(preRequestsCpu) ) {
preRequestsCpu = 0
}
const minCpu = (get(this, 'level') === 'cluster' ? get(this, 'clusterLevelMinCpu') : get(this, 'projectLevelMinCpu'))
return get(this, 'enabled') ? cpu - preRequestsCpu : minCpu + cpu
}),
minMemory: computed('requestsMemory', 'clusterLevelMinMemory', 'projectLevelMinMemory', 'enabled', 'preRequestsMemory', function() {
let memory = parseInt(get(this, 'requestsMemory') || 0, 10);
let preRequestsMemory = parseInt(get(this, 'preRequestsMemory') || 0, 10);
if ( isNaN(memory) ) {
memory = 0;
}
if ( isNaN(preRequestsMemory) ) {
preRequestsMemory = 0
}
const minMemory = (get(this, 'level') === 'cluster' ? get(this, 'clusterLevelMinMemory') : get(this, 'projectLevelMinMemory'))
return get(this, 'enabled') ? memory - preRequestsMemory : minMemory + memory
}),
enabled: computed('app.state', function() {
return !!get(this, 'app') && get(this, 'app.state') !== 'removing'
}),
@ -364,10 +350,10 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
return namespace.projectId !== project.id
}),
requestsCpu: computed('config.mixerRequestCpu', 'config.prometheusRequestCpu', 'config.pilotRequestCpu', 'config.gatewayRequestCpu', 'config.grafanaRequestCpu', 'config.tracingRequestCpu', function() {
requestsCpu: computed('config.mixerTelemetryRequestCpu', 'config.prometheusRequestCpu', 'config.pilotRequestCpu', 'config.gatewayRequestCpu', 'config.grafanaRequestCpu', 'config.tracingRequestCpu', 'config.mixerPolicyRequestCpu', function() {
return WORKLOADS
.filter((w) => {
if (['gateway', 'grafana', 'tracing'].includes(w) && !get(this, `config.${ w }Enabled`)) {
if (['gateway', 'grafana', 'tracing', 'mixerPolicy'].includes(w) && !get(this, `config.${ w }Enabled`)) {
return false
}
@ -378,10 +364,10 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}, 0)
}),
requestsMemory: computed('config.mixerRequestMemory', 'config.prometheusRequestMemory', 'config.pilotRequestMemory', 'config.grafanaRequestMemory', 'config.gatewayRequestMemory', 'config.tracingRequestMemory', function() {
requestsMemory: computed('config.mixerTelemetryRequestMemory', 'config.prometheusRequestMemory', 'config.pilotRequestMemory', 'config.grafanaRequestMemory', 'config.gatewayRequestMemory', 'config.tracingRequestMemory', 'config.mixerPolicyRequestMemory', function() {
return WORKLOADS
.filter((w) => {
if (['gateway', 'grafana', 'tracing'].includes(w) && !get(this, `config.${ w }Enabled`)) {
if (['gateway', 'grafana', 'tracing', 'mixerPolicy'].includes(w) && !get(this, `config.${ w }Enabled`)) {
return false
}
@ -392,10 +378,53 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
}, 0)
}),
clusterLevelMinCpu: computed(() => {
const arr = ['citadel', 'galley', 'sidecar-injector', 'kiali']
mixerSchedulableNodes: computed('mixerNodeSelectors.[]', 'cluster.nodes.@each.{allocatable,requested}', 'config.mixerPolicyEnabled', function() {
return this.getSchedulableNodes('mixer')
}),
return arr.length * 50
insufficientMixerCpu: computed('mixerSchedulableNodes.@each.{allocatable,requested}', 'config.mixerPolicyEnabled', 'config.mixerTelemetryRequestCpu', 'config.mixerPolicyRequestCpu', 'cluster.nodes.@each.{allocatable,requested}', function() {
let reservation
if (get(this, 'config.mixerPolicyEnabled')) {
reservation = Math.max(parseInt(get(this, 'config.mixerTelemetryRequestCpu') || '0'), parseInt(get(this, 'config.mixerPolicyRequestCpu') || '0'))
} else {
reservation = parseInt(get(this, 'config.mixerTelemetryRequestCpu') || '0')
}
return this.getComponentInsufficient('mixer', 'cpu', reservation)
}),
insufficientMixerMemory: computed('mixerSchedulableNodes.@each.{allocatable,requested}', 'config.mixerPolicyEnabled', 'config.mixerTelemetryRequestMemory', 'config.mixerPolicyRequestMemory', 'cluster.nodes.@each.{allocatable,requested}', function() {
let reservation
if (get(this, 'config.mixerPolicyEnabled')) {
reservation = Math.max(parseInt(get(this, 'config.mixerTelemetryRequestMemory') || '0'), parseInt(get(this, 'config.mixerPolicyRequestMemory') || '0'))
} else {
reservation = parseInt(get(this, 'config.mixerTelemetryRequestMemory') || '0')
}
return this.getComponentInsufficient('mixer', 'memory', reservation)
}),
mixerWarning: computed('insufficientMixerCpu', 'insufficientMixerMemory', 'insufficientMixerTelemetryMemory', 'insufficientMixerTelemetryCpu', 'mixerNodeSelectors.[]', 'config.mixerPolicyEnabled', function() {
if ((get(this, 'mixerNodeSelectors') || []).length === 0 ) {
return
}
const displayName = get(this, 'config.mixerPolicyEnabled') ? get(this, 'intl').t('clusterIstioPage.telemetryAndPolicy') : undefined
let componentCpu
let componentMemory
if (get(this, 'config.mixerPolicyEnabled')) {
componentCpu = Math.max(parseInt(get(this, 'config.mixerTelemetryRequestCpu') || '0'), parseInt(get(this, 'config.mixerPolicyRequestCpu') || '0'))
componentMemory = Math.max(parseInt(get(this, 'config.mixerTelemetryRequestMemory') || '0'), parseInt(get(this, 'config.mixerPolicyRequestMemory') || '0'))
} else {
componentCpu = parseInt(get(this, 'config.mixerTelemetryRequestCpu') || '0')
componentMemory = parseInt(get(this, 'config.mixerTelemetryRequestMemory') || '0')
}
return this.getComponentWarning('mixer', componentCpu, componentMemory, displayName)
}),
willSavePersistence(answers, component) {
@ -415,8 +444,42 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
validate() {
const errors = []
if (get(this, 'config.grafanaEnabled') && get(this, 'config.grafanaPersistenceEnabled')) {
errors.pushObjects(this.validatePV('grafana'))
if (get(this, 'config.grafanaEnabled')) {
errors.pushObjects(this.validateLimitAndRequest('grafana'))
if (get(this, 'config.grafanaPersistenceEnabled')) {
errors.pushObjects(this.validatePV('grafana'))
}
}
['pilot', 'mixerTelemetry', 'prometheus'].map((w) => {
errors.pushObjects(this.validateLimitAndRequest(w))
})
if (get(this, 'config.gatewayEnabled')) {
errors.pushObjects(this.validateLimitAndRequest('gateway'))
}
if (get(this, 'config.tracingEnabled')) {
errors.pushObjects(this.validateLimitAndRequest('tracing'))
}
if (get(this, 'config.mixerPolicyEnabled')) {
errors.pushObjects(this.validateLimitAndRequest('mixerPolicy'))
}
['traceSampling', 'prometheusRetention'].map((field) => {
if (!get(this, `config.${ field }`)) {
errors.pushObject(requiredError(`clusterIstioPage.config.${ field }.label`))
}
})
if (get(this, 'config.gatewayEnabled') && get(this, 'config.gatewayType') === 'NodePort') {
['http2Port', 'httpsPort'].map((field) => {
if (!get(this, `config.${ field }`)) {
errors.pushObject(requiredError(`clusterIstioPage.config.${ field }.label`))
}
})
}
return errors
@ -434,8 +497,12 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
errors.pushObject(emptyError)
}
if (!get(this, `${ component }.persistence.size`)) {
errors.pushObject(intl.t('globalRegistryPage.config.storageClass.sizeRequired', { component: ucFirst(component) }))
}
} else if (!get(this, `${ component }.persistence.existingClaim`)){
errors.pushObject(requiredError(`globalRegistryPage.config.${ component }.existingClaim.label`))
errors.pushObject(requiredError(`clusterIstioPage.existingClaim.label`, { component: ucFirst(component) }))
}
return errors
@ -443,45 +510,49 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
initConfig() {
const config = {
tracingEnabled: true,
kialiEnabled: true,
prometheusEnabled: true,
grafanaEnabled: true,
grafanaPersistenceEnabled: false,
grafanaPersistenceSize: '5Gi',
autoInject: true,
mtlsEnabled: false,
gatewayType: 'NodePort',
gatewayEnabled: false,
http2Port: DEFAULT_HTTP2_PORT,
httpsPort: DEFAULT_HTTPS_PORT,
prometheusRetention: 6,
prometheusLimitMemory: 1024,
prometheusRequestMemory: 750,
prometheusRequestCpu: 750,
prometheusLimitCpu: 1000,
mixerRequestCpu: 1000,
mixerLimitCpu: 4800,
mixerRequestMemory: 1024,
mixerLimitMemory: 4096,
traceSampling: 1,
mixerPolicyEnabled: false,
pilotRequestCpu: 500,
pilotRequestMemory: 2048,
pilotLimitCpu: 1000,
pilotLimitMemory: 4096,
grafanaRequestCpu: 100,
grafanaLimitCpu: 200,
grafanaRequestMemory: 100,
grafanaLimitMemory: 512,
gatewayRequestCpu: 100,
gatewayLimitCpu: 2000,
gatewayRequestMemory: 128,
gatewayLimitMemory: 1024,
tracingRequestCpu: 100,
tracingLimitCpu: 500,
tracingRequestMemory: 100,
tracingLimitMemory: 1024,
tracingEnabled: true,
kialiEnabled: true,
prometheusEnabled: true,
grafanaEnabled: true,
grafanaPersistenceEnabled: false,
grafanaPersistenceSize: '5Gi',
autoInject: true,
mtlsEnabled: false,
gatewayType: 'NodePort',
gatewayEnabled: false,
http2Port: DEFAULT_HTTP2_PORT,
httpsPort: DEFAULT_HTTPS_PORT,
prometheusRetention: 6,
prometheusLimitMemory: 1024,
prometheusRequestMemory: 750,
prometheusRequestCpu: 750,
prometheusLimitCpu: 1000,
mixerTelemetryRequestCpu: 1000,
mixerTelemetryLimitCpu: 4800,
mixerTelemetryRequestMemory: 1024,
mixerTelemetryLimitMemory: 4096,
traceSampling: 1,
mixerPolicyEnabled: false,
pilotRequestCpu: 500,
pilotRequestMemory: 2048,
pilotLimitCpu: 1000,
pilotLimitMemory: 4096,
grafanaRequestCpu: 100,
grafanaLimitCpu: 200,
grafanaRequestMemory: 100,
grafanaLimitMemory: 512,
gatewayRequestCpu: 100,
gatewayLimitCpu: 2000,
gatewayRequestMemory: 128,
gatewayLimitMemory: 1024,
tracingRequestCpu: 100,
tracingLimitCpu: 500,
tracingRequestMemory: 100,
tracingLimitMemory: 1024,
mixerPolicyRequestCpu: 1000,
mixerPolicyLimitCpu: 4800,
mixerPolicyRequestMemory: 1024,
mixerPolicyLimitMemory: 4096,
}
setProperties(this, {
@ -572,7 +643,7 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
loadBalancerSourceRanges.pushObject(answers[k])
})
const workloads = ['pilot', 'prometheus', 'mixer.telemetry', 'gateways.istio-ingressgateway', 'grafana', 'tracing']
const workloads = this.getEnalbedWorkloads(answers)
const preRequestsCpu = workloads.reduce((all, current) => {
const value = answers[`${ current }.resources.requests.cpu`]
@ -640,6 +711,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case TRACING_LIMIT_CPU:
case GATEWAY_REQUEST_CPU:
case GATEWAY_LIMIT_CPU:
case POLICY_REQUEST_CPU:
case POLICY_LIMIT_CPU:
value = convertToMillis(answers[key] || '0')
break;
case PILOT_REQUEST_MEM:
@ -654,6 +727,8 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
case TRACING_LIMIT_MEM:
case GATEWAY_REQUEST_MEM:
case GATEWAY_LIMIT_MEM:
case POLICY_REQUEST_MEM:
case POLICY_LIMIT_MEM:
value = parseSi(answers[key] || '0', 1024) / 1048576
break;
case PROMETHEUS_RETENTION:
@ -669,5 +744,33 @@ export default Component.extend(CrudCatalog, ReservationCheck, {
customAnswers[key] = answers[key];
setProperties(this, { customAnswers, })
});
},
getEnalbedWorkloads(answers) {
const out = []
if (answers['pilot.enabled'] === 'true') {
out.push('pilot')
}
if (answers['mixer.enabled'] === 'true') {
out.push('mixer.telemetry')
}
if (answers['mixer.policy.enabled'] === 'true') {
out.push('mixer.policy')
}
if (answers['gateways.enabled'] === 'true') {
out.push('gateways.istio-ingressgateway')
}
if (answers['tracing.enabled'] === 'true') {
out.push('tracing')
}
if (answers['prometheus.enabled'] === 'true') {
out.push('prometheus')
}
if (answers['grafana.enabled'] === 'true') {
out.push('grafana')
}
return out;
}
});

View File

@ -60,11 +60,16 @@
{{/if}}
<div class="box mb-10">
<div class="over-hr"><span>{{t "clusterIstioPage.config.header.pilot"}}</span></div>
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.pilot"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-pilot-limit-cpu">
{{t "clusterIstioPage.config.pilotLimitCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -83,6 +88,7 @@
<div class="col span-6">
<label class="acc-label" for="input-pilot-limit-memory">
{{t "clusterIstioPage.config.pilotLimitMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -103,6 +109,7 @@
<div class="col span-6">
<label class="acc-label" for="input-pilot-cpu">
{{t "clusterIstioPage.config.pilotCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -121,6 +128,7 @@
<div class="col span-6">
<label class="acc-label" for="input-pilot-memory">
{{t "clusterIstioPage.config.pilotMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -141,6 +149,7 @@
<div class="col span-6">
<label class="acc-label" for="input-trace-sampling">
{{t "clusterIstioPage.config.traceSampling.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-float
@ -173,84 +182,18 @@
</div>
</div>
<div class="over-hr"><span>{{t "clusterIstioPage.config.header.mixer"}}</span></div>
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-mixer-limit-cpu">
{{t "clusterIstioPage.config.mixerLimitCpu.label"}}
</label>
<div class="input-group">
{{input-integer
min="0"
step="100"
id="input-mixer-limit-cpu"
value=config.mixerLimitCpu
classNames="form-control"
placeholder=(t "clusterIstioPage.config.mixerLimitCpu.placeholder")
}}
<div class="input-group-addon bg-default">
{{t "units.cpu"}}
</div>
</div>
</div>
<div class="col span-6">
<label class="acc-label" for="input-mixer-limit-memory">
{{t "clusterIstioPage.config.mixerLimitMemory.label"}}
</label>
<div class="input-group">
{{input-integer
min="4"
step="1"
id="input-mixer-limit-memory"
value=config.mixerLimitMemory
classNames="form-control"
placeholder=(t "clusterIstioPage.config.mixerLimitMemory.placeholder")
}}
<div class="input-group-addon bg-default">
{{t "generic.mibibyte"}}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-mixer-request-cpu">
{{t "clusterIstioPage.config.mixerRequestCpu.label"}}
</label>
<div class="input-group">
{{input-integer
min="4"
step="1"
id="input-mixer-request-cpu"
value=config.mixerRequestCpu
classNames="form-control"
placeholder=(t "clusterIstioPage.config.mixerRequestCpu.placeholder")
}}
<div class="input-group-addon bg-default">
{{t "units.cpu"}}
</div>
</div>
</div>
<div class="col span-6">
<label class="acc-label" for="input-mixer-request-memory">
{{t "clusterIstioPage.config.mixerRequestMemory.label"}}
</label>
<div class="input-group">
{{input-integer
min="4"
step="1"
id="input-mixer-request-memory"
value=config.mixerRequestMemory
classNames="form-control"
placeholder=(t "clusterIstioPage.config.mixerRequestMemory.placeholder")
}}
<div class="input-group-addon bg-default">
{{t "generic.mibibyte"}}
</div>
</div>
</div>
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.mixer"}}
</span>
</div>
{{form-reservation
component="MixerTelemetry"
requestCpu=config.mixerTelemetryRequestCpu
requestMemory=config.mixerTelemetryRequestMemory
limitCpu=config.mixerTelemetryLimitCpu
limitMemory=config.mixerTelemetryLimitMemory
}}
<div class="row">
<div class="col span-6">
@ -265,6 +208,16 @@
</div>
</div>
{{#if config.mixerPolicyEnabled}}
{{form-reservation
component="MixerPolicy"
requestCpu=config.mixerPolicyRequestCpu
requestMemory=config.mixerPolicyRequestMemory
limitCpu=config.mixerPolicyLimitCpu
limitMemory=config.mixerPolicyLimitMemory
}}
{{/if}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
@ -279,11 +232,166 @@
</div>
</div>
<div class="over-hr"><span>{{t "clusterIstioPage.config.header.prometheus"}}</span></div>
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.tracing"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">
{{t "clusterIstioPage.config.tracingEnabled.label"}}
</label>
{{schema/input-boolean
value=config.tracingEnabled
classNames="form-control"
}}
</div>
</div>
{{#if config.tracingEnabled}}
{{form-reservation
component="Tracing"
requestCpu=config.tracingRequestCpu
requestMemory=config.tracingRequestMemory
limitCpu=config.tracingLimitCpu
limitMemory=config.tracingLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Tracing"}}
</label>
{{form-key-value
changedArray=(action (mut tracingNodeSelectors))
initialMap=tracingNodeSelector
allowEmptyValue=true
addActionLabel="clusterIstioPage.nodeSelector.addSelectorLabel"
}}
</div>
</div>
{{/if}}
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.gateway"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">
{{t "clusterIstioPage.config.gatewayEnabled.label"}}
</label>
{{schema/input-boolean
value=config.gatewayEnabled
classNames="form-control"
}}
</div>
{{#if config.gatewayEnabled}}
<div class="col span-6">
<label class="acc-label" for="input-gateway-type-select">
{{t "clusterIstioPage.config.gatewayType.label"}}
</label>
{{new-select
id="input-gateway-type-select"
class="form-control"
content=gatewayTypeContent
value=config.gatewayType
}}
</div>
{{/if}}
</div>
{{#if config.gatewayEnabled}}
{{#if (eq config.gatewayType "NodePort")}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-http2-port">
{{t "clusterIstioPage.config.http2Port.label"}}
{{field-required}}
</label>
{{input-integer
min="30000"
max="32767"
step="1"
id="input-http2-port"
value=config.http2Port
classNames="form-control"
}}
</div>
<div class="col span-6">
<label class="acc-label" for="input-https-port">
{{t "clusterIstioPage.config.httpsPort.label"}}
{{field-required}}
</label>
{{input-integer
min="30000"
max="32767"
step="1"
id="input-https-port"
value=config.httpsPort
classNames="form-control"
}}
</div>
</div>
{{else if (eq config.gatewayType "LoadBalancer")}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-load-balancer-ip">
{{t "clusterIstioPage.config.loadBalancerIP.label"}}
</label>
{{schema/input-string
value=config.loadBalancerIP
id="input-load-balancer-ip"
placeholder=(t "clusterIstioPage.config.loadBalancerIP.placeholder")
}}
</div>
<div class="col span-6">
{{form-value-array
initialValues=loadBalancerSourceRanges
addActionLabel="editDns.loadBalancerSourceRanges.addActionLabel"
valueLabel="editDns.loadBalancerSourceRanges.value"
valuePlaceholder="editDns.loadBalancerSourceRanges.placeholder"
changed=(action (mut loadBalancerSourceRanges))
addButtonClass="btn bg-link icon-btn"
}}
</div>
</div>
{{/if}}
{{form-reservation
component="IngressGateway"
requestCpu=config.gatewayRequestCpu
requestMemory=config.gatewayRequestMemory
limitCpu=config.gatewayLimitCpu
limitMemory=config.gatewayLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Gateway"}}
</label>
{{form-key-value
changedArray=(action (mut gatewayNodeSelectors))
initialMap=gatewayNodeSelector
allowEmptyValue=true
addActionLabel="clusterIstioPage.nodeSelector.addSelectorLabel"
}}
</div>
</div>
{{/if}}
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.prometheus"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-prometheus-limit-cpu">
{{t "clusterIstioPage.config.prometheusLimitCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -302,6 +410,7 @@
<div class="col span-6">
<label class="acc-label" for="input-prometheus-limit-memory">
{{t "clusterIstioPage.config.prometheusLimitMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -323,6 +432,7 @@
<div class="col span-6">
<label class="acc-label" for="input-prometheus-request-cpu">
{{t "clusterIstioPage.config.prometheusRequestCpu.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -341,6 +451,7 @@
<div class="col span-6">
<label class="acc-label" for="input-prometheus-request-memory">
{{t "clusterIstioPage.config.prometheusRequestMemory.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -362,6 +473,7 @@
<div class="col span-6">
<label class="acc-label" for="input-prometheus-retention">
{{t "clusterIstioPage.config.prometheusRetention.label"}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -388,7 +500,11 @@
</div>
</div>
<div class="over-hr"><span>{{t "clusterIstioPage.config.header.grafana"}}</span></div>
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.grafana"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">
@ -445,154 +561,6 @@
</div>
{{/if}}
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.gateway"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">
{{t "clusterIstioPage.config.gatewayEnabled.label"}}
</label>
{{schema/input-boolean
value=config.gatewayEnabled
classNames="form-control"
}}
</div>
{{#if config.gatewayEnabled}}
<div class="col span-6">
<label class="acc-label" for="input-gateway-type-select">
{{t "clusterIstioPage.config.gatewayType.label"}}
</label>
{{new-select
id="input-gateway-type-select"
class="form-control"
content=gatewayTypeContent
value=config.gatewayType
}}
</div>
{{/if}}
</div>
{{#if config.gatewayEnabled}}
{{#if (eq config.gatewayType "NodePort")}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-http2-port">
{{t "clusterIstioPage.config.http2Port.label"}}
</label>
{{input-integer
min="30000"
max="32767"
step="1"
id="input-http2-port"
value=config.http2Port
classNames="form-control"
}}
</div>
<div class="col span-6">
<label class="acc-label" for="input-https-port">
{{t "clusterIstioPage.config.httpsPort.label"}}
</label>
{{input-integer
min="30000"
max="32767"
step="1"
id="input-https-port"
value=config.httpsPort
classNames="form-control"
}}
</div>
</div>
{{else if (eq config.gatewayType "LoadBalancer")}}
<div class="row">
<div class="col span-6">
<label class="acc-label" for="input-load-balancer-ip">
{{t "clusterIstioPage.config.loadBalancerIP.label"}}
</label>
{{schema/input-string
value=config.loadBalancerIP
id="input-load-balancer-ip"
placeholder=(t "clusterIstioPage.config.loadBalancerIP.placeholder")
}}
</div>
<div class="col span-6">
{{form-value-array
initialValues=loadBalancerSourceRanges
addActionLabel="editDns.loadBalancerSourceRanges.addActionLabel"
valueLabel="editDns.loadBalancerSourceRanges.value"
valuePlaceholder="editDns.loadBalancerSourceRanges.placeholder"
changed=(action (mut loadBalancerSourceRanges))
addButtonClass="btn bg-link icon-btn"
}}
</div>
</div>
{{/if}}
{{form-reservation
component="Gateway"
requestCpu=config.gatewayRequestCpu
requestMemory=config.gatewayRequestMemory
limitCpu=config.gatewayLimitCpu
limitMemory=config.gatewayLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Gateway"}}
</label>
{{form-key-value
changedArray=(action (mut gatewayNodeSelectors))
initialMap=gatewayNodeSelector
allowEmptyValue=true
addActionLabel="clusterIstioPage.nodeSelector.addSelectorLabel"
}}
</div>
</div>
{{/if}}
<div class="over-hr">
<span>
{{t "clusterIstioPage.config.header.tracing"}}
</span>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">
{{t "clusterIstioPage.config.tracingEnabled.label"}}
</label>
{{schema/input-boolean
value=config.tracingEnabled
classNames="form-control"
}}
</div>
</div>
{{#if config.tracingEnabled}}
{{form-reservation
component="Tracing"
requestCpu=config.tracingRequestCpu
requestMemory=config.tracingRequestMemory
limitCpu=config.tracingLimitCpu
limitMemory=config.tracingLimitMemory
}}
<div class="row">
<div class="col span-12">
<label class="acc-label">
{{t "clusterIstioPage.nodeSelector.helpText" component="Tracing"}}
</label>
{{form-key-value
changedArray=(action (mut tracingNodeSelectors))
initialMap=tracingNodeSelector
allowEmptyValue=true
addActionLabel="clusterIstioPage.nodeSelector.addSelectorLabel"
}}
</div>
</div>
{{/if}}
{{#advanced-section}}
<hr/>
{{form-key-value
@ -611,7 +579,7 @@
{{/advanced-section}}
</div>
{{#if (or istioWarning pilotWarning mixerWarning prometheusWarning tracingWarning grafanaWarning gatewayWarning)}}
{{#if (or pilotWarning mixerTelemetryWarning prometheusWarning tracingWarning grafanaWarning gatewayWarning (and mixerPolicyWarning config.mixerPolicyEnabled) mixerWarning istioWarning)}}
{{#banner-message color="bg-warning"}}
{{#if istioWarning}}
<p>{{istioWarning}}</p>
@ -619,6 +587,7 @@
<p>{{pilotWarning}}</p>
<p>{{mixerWarning}}</p>
<p>{{prometheusWarning}}</p>
<p>{{mixerTelemetryWarning}}</p>
{{#if config.tracingEnabled}}
<p>{{tracingWarning}}</p>
{{/if}}
@ -628,6 +597,9 @@
{{#if config.gatewayEnabled}}
<p>{{gatewayWarning}}</p>
{{/if}}
{{#if config.mixerPolicyEnabled}}
<p>{{mixerPolicyWarning}}</p>
{{/if}}
{{/if}}
{{/banner-message}}
{{/if}}

View File

@ -18,7 +18,7 @@ clusterIstioPage:
config:
header:
grafana: GRAFANA
gateway: ISTIO GATEWAY
gateway: INGRESS GATEWAY
pilot: PILOT
prometheus: PROMETHEUS
mixer: MIXER
@ -37,11 +37,11 @@ clusterIstioPage:
unit: milli CPUs
pilotMemory:
label: Pilot Memory Reservation
placeholder: e.g. 20148
placeholder: e.g. 2048
gatewayEnabled:
label: Enabled Istio Gateway
label: Enabled Ingress Gateway
gatewayType:
label: Service Type of Istio Ingress Gateway
label: Service Type of Ingress Gateway
http2Port:
label: Http2 Port
httpsPort:
@ -64,18 +64,6 @@ clusterIstioPage:
prometheusRequestCpu:
label: Prometheus CPU Reservation
placeholder: e.g. 1000
mixerRequestCpu:
label: Mixer CPU Reservation
placeholder: e.g. 1000
mixerRequestMemory:
label: Mixer Memory Reservation
placeholder: e.g. 1000
mixerLimitCpu:
label: Mixer CPU Limit
placeholder: e.g. 1000
mixerLimitMemory:
label: Mixer Memory Limit
placeholder: e.g. 1000
traceSampling:
label: Trace sampling Percentage
placeholder: e.g. 1
@ -104,6 +92,9 @@ clusterIstioPage:
memory: Please make sure you have at least one node matches node selectors with {memory} MiB of memory available to enable {component} workload.
all: Please make sure you have at least one node matches node selectors with {cpu} milli CPUs and {memory} MiB of memory available to enable {component} workload.
unsupported: 'Node selector with value "true", "false" or number is not supported'
telemetryAndPolicy: Telemetry And Policy
existingClaim:
label: 'Existing Claim for {component}'
istio:
noData: Not enough data for graph
period: Period

View File

@ -38,6 +38,7 @@
}}
<label class="acc-label" for={{concat "input-registry-pv-size-" component}}>
{{t "globalRegistryPage.config.registryPVSize.label"}}
{{field-required}}
</label>
{{schema/input-string
value=config.size
@ -48,6 +49,7 @@
<div class="col span-6">
<label class="acc-label" for={{concat "input-registry-existing-claim-" component}}>
{{t "globalRegistryPage.config.registryExistingClaim.label"}}
{{field-required}}
</label>
{{new-select
id=(concat "input-registry-existing-claim-" component)

View File

@ -1,7 +1,8 @@
<div class="row">
<div class="col span-6">
<label class="acc-label" for={{concat "input-limit-cpu-" component}}>
{{t "formReservation.limitCpu.label" component=component}}
{{t "formReservation.limitCpu.label" component=(parse-camelcase component)}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -19,7 +20,8 @@
</div>
<div class="col span-6">
<label class="acc-label" for={{concat "input-limit-memory-" component}}>
{{t "formReservation.limitMemory.label" component=component}}
{{t "formReservation.limitMemory.label" component=(parse-camelcase component)}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -40,7 +42,8 @@
<div class="row">
<div class="col span-6">
<label class="acc-label" for={{concat "input-request-cpu-" component}}>
{{t "formReservation.requestCpu.label" component=component}}
{{t "formReservation.requestCpu.label" component=(parse-camelcase component)}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer
@ -58,7 +61,8 @@
</div>
<div class="col span-6">
<label class="acc-label" for={{concat "input-request-memory-" component}}>
{{t "formReservation.requestMemory.label" component=component}}
{{t "formReservation.requestMemory.label" component=(parse-camelcase component)}}
{{field-required}}
</label>
<div class="input-group">
{{input-integer

View File

@ -0,0 +1,9 @@
import { helper } from '@ember/component/helper';
import Util from 'ui/utils/util';
import { htmlSafe } from '@ember/string';
export function parseCamelcase(params) {
return new htmlSafe(Util.parseCamelcase(params[0]));
}
export default helper(parseCamelcase);

View File

@ -1,8 +1,9 @@
import { inject as service } from '@ember/service';
import Mixin from '@ember/object/mixin';
import { get, computed } from '@ember/object';
import { convertToMillis, ucFirst } from 'shared/utils/util';
import { parseSi } from 'shared/utils/parse-unit'
import { convertToMillis, ucFirst, parseCamelcase } from 'shared/utils/util';
import { parseSi } from 'shared/utils/parse-unit';
import { requiredError } from 'shared/utils/util';
export default Mixin.create({
scope: service(),
@ -102,7 +103,7 @@ export default Mixin.create({
return (get(this, 'level') === 'cluster' ? get(this, 'clusterLevelMinMemory') : get(this, 'projectLevelMinMemory')) + memory;
}),
getComponentInsufficient(component, type) {
getComponentInsufficient(component, type, reservation) {
const allNodes = get(this, 'cluster.nodes') || [];
if ( get(allNodes, 'length') === 0 ) {
@ -121,7 +122,7 @@ export default Mixin.create({
return left > out ? left : out
}, 0)
const request = get(this, `config.${ component }Request${ ucFirst(type) }`) || 0
const request = reservation ? reservation : get(this, `config.${ component }Request${ ucFirst(type) }`) || 0
return get(this, 'enabled') ? false : maxLeft <= request
},
@ -144,14 +145,14 @@ export default Mixin.create({
return out;
},
getComponentWarning(component) {
getComponentWarning(component, componentCpu, componentMemory, displayComponent, ) {
const insufficientCpu = get(this, `insufficient${ ucFirst(component) }Cpu`)
const insufficientMemory = get(this, `insufficient${ ucFirst(component) }Memory`)
const nodeSelectors = get(this, `${ component }NodeSelectors`) || []
const intl = get(this, 'intl')
const cpu = get(this, `config.${ component }RequestCpu`)
const memory = get(this, `config.${ component }RequestMemory`)
const cpu = componentCpu ? componentCpu : get(this, `config.${ component }RequestCpu`)
const memory = componentMemory ? componentMemory : get(this, `config.${ component }RequestMemory`)
let prefix = 'clusterIstioPage.insufficientSize.selectors'
if (nodeSelectors.length === 0) {
@ -160,7 +161,7 @@ export default Mixin.create({
const unsupportedSelectors = nodeSelectors.filter((n) => n.value === 'true' || n.value === 'false' || /^\d+$/g.test(n.value))
if (unsupportedSelectors.length > 0) {
return intl.t(`clusterIstioPage.insufficientSize.selectors.unsupported`, { component: ucFirst(component), })
return intl.t(`clusterIstioPage.insufficientSize.selectors.unsupported`, { component: displayComponent ? displayComponent : parseCamelcase(component), })
}
}
@ -168,18 +169,32 @@ export default Mixin.create({
return intl.t(`${ prefix }.all`, {
cpu,
memory,
component
component: displayComponent ? displayComponent : parseCamelcase(component),
})
} else if (insufficientCpu) {
return intl.t(`${ prefix }.cpu`, {
cpu,
component
component: displayComponent ? displayComponent : parseCamelcase(component),
})
} else if (insufficientMemory) {
return intl.t(`${ prefix }.memory`, {
memory,
component
component: displayComponent ? displayComponent : parseCamelcase(component),
})
}
},
validateLimitAndRequest(component) {
const errors = [];
['requestCpu', 'limitCpu', 'requestMemory', 'limitMemory'].map((suffix) => {
const key = `config.${ component }${ ucFirst(suffix) }`
if (!get(this, key)) {
errors.pushObject(requiredError(`formReservation.${ suffix }.label`, { component: ucFirst(component) }))
}
})
return errors
},
});

View File

@ -509,10 +509,14 @@ export function validateKeyWeakly(key) {
return valid;
}
export function requiredError(label) {
export function requiredError(label, payload = {}) {
const intl = window.l('service:intl')
return `"${ intl.t(label) }" ${ intl.t('generic.isRequired') }`
return `"${ intl.t(label, payload) }" ${ intl.t('generic.isRequired') }`
}
export function parseCamelcase(str = '') {
return ucFirst(str).replace(/([A-Z]+)*([A-Z][a-z])/g, '$1 $2')
}
var Util = {
@ -558,6 +562,7 @@ var Util = {
underlineToCamel,
validateEndpoint,
requiredError,
parseCamelcase,
};
window.Util = Util;

View File

@ -0,0 +1 @@
export { default } from 'shared/helpers/parse-camelcase';

View File

@ -30,4 +30,5 @@ export {
camelToTitle,
isNumeric,
requiredError,
parseCamelcase,
} from 'shared/utils/util';

View File

@ -1206,7 +1206,7 @@ globalRegistryPage:
dockerPush: Push an image to the registry
setting:
adminPassword:
label: Admin Password
label: Initial Admin Password
placeholder: Harobr admin password
config:
header:
@ -1226,7 +1226,7 @@ globalRegistryPage:
description: The key used for encryption. Must be a string of 16 chars
error: '"Encryption Key For Harbor" must be a string of 16 chars.'
storageType:
label: Storage backend for registry
label: Storage Backend Type
databaseType:
label: Config Database Type
redisType:
@ -1240,6 +1240,7 @@ globalRegistryPage:
pvc: Use an existing persistent volume claim
storageClass:
emptyError: 'At least one default storage class is required in "local" cluster'
sizeRequired: '"{component} Persistent Volume Size" is required'
databaseRequestCpu:
label: Database CPU Request
placeholder: e.g. 1000
@ -1295,7 +1296,7 @@ globalRegistryPage:
label: S3 Access Key
placeholder: Your S3 Access Key
secretkey:
label: Secret Key for S3
label: S3 Secret Key
placeholder: Your S3 Secret Key
regionendpoint:
label: S3 Region Endpoint
@ -1350,6 +1351,7 @@ globalRegistryPage:
nodeSelector:
addSelectorLabel: Add Selector
helpText: Select the nodes where {component} workloads will be scheduled to
notaryAndSigner: Notary server and Notary signer
globalDnsPage:
header: Global DNS Entries