Skip to content

Commit

Permalink
[release-3.3] fix: Missing openelb annotation hint when creating serv…
Browse files Browse the repository at this point in the history
…ice of type loadbalancer (#3499)

fix: Missing openelb annotation hint when creating service of type loadbalancer

Signed-off-by: TheYoungManLi <cjl@kubesphere.io>

Co-authored-by: TheYoungManLi <cjl@kubesphere.io>
  • Loading branch information
ks-ci-bot and weili520 authored Aug 2, 2022
1 parent 2df3af7 commit 8018aca
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ module.exports = {
// List > Create > Service Settings > Workload Selector > View Details
TOTAL_WORKLOADS_VALUE: 'Total Workloads: {count}',
// List > Create > Advanced Settings
OPENELB_NOT_READY: "OpenELB not ready, can't use it",
SESSION_PERSISTENCE: 'Session Persistence',
MAXIMUM_STICKINESS_DURATION: 'Maximum Stickiness Duration (s)',
SESSION_PERSISTENCE_DESC: 'Set the system to forward all requests from the same client to the same pod within a specified duration.',
Expand Down
140 changes: 110 additions & 30 deletions src/components/Forms/Service/AdvanceSettings/InternetAccess/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,38 @@
* along with KubeSphere Console. If not, see <https://www.gnu.org/licenses/>.
*/

import { get, set, unset } from 'lodash'
import { get, unset } from 'lodash'
import React from 'react'
import { Form, Select } from '@kube-design/components'
import { PropertiesInput } from 'components/Inputs'
import {
Form,
Select,
Icon,
Tooltip,
Columns,
Column,
} from '@kube-design/components'
import { AnnotationsInput } from 'components/Inputs'
import { CLUSTER_PROVIDERS_ANNOTATIONS } from 'pages/projects/components/Modals/GatewaySetting/contants'
import { updateFederatedAnnotations } from 'utils'
import { CLUSTER_PROVIDERS } from 'utils/constants'

import OpenELBStore from 'stores/openelb'
import styles from './index.scss'

const defaultProvider = 'QingCloud Kubernetes Engine'
export default class InternetAccess extends React.Component {
constructor(props) {
super(props)

this.state = {
mode: get(this.formTemplate, 'spec.type', 'ClusterIP'),
provider: defaultProvider,
openELBOpened: true,
}
}

openELBStore = new OpenELBStore()

get fedPreifx() {
return this.props.isFederated ? 'spec.template.' : ''
}
Expand All @@ -56,20 +71,38 @@ export default class InternetAccess extends React.Component {
]
}

get providerOptions() {
const { provider } = this.state
return provider === ''
? []
: Object.keys(CLUSTER_PROVIDERS_ANNOTATIONS[provider])
}

async componentDidMount() {
this.checkOpenELBStatus()
}

checkOpenELBStatus = async () => {
const { clusters, namespace } = this.props
const isOpened = await this.openELBStore.isActive({ clusters, namespace })
if (!isOpened) {
this.setState({
openELBOpened: isOpened,
})
}
}

handleAccessModeChange = mode => {
if (mode === 'LoadBalancer') {
let annotations = get(this.formTemplate, 'metadata.annotations', {})
annotations = {
...globals.config.loadBalancerDefaultAnnotations,
...annotations,
}
set(this.formTemplate, 'metadata.annotations', annotations)
} else {
if (mode !== 'LoadBalancer') {
Object.keys(globals.config.loadBalancerDefaultAnnotations).forEach(
key => {
unset(this.formTemplate, `metadata.annotations["${key}"]`)
}
)

this.providerOptions.forEach(key => {
unset(this.formTemplate, `metadata.annotations["${key}"]`)
})
}

if (this.props.isFederated) {
Expand All @@ -92,29 +125,76 @@ export default class InternetAccess extends React.Component {
</div>
)

render() {
const { mode } = this.state
providerOptionRenderer = option => (
<div className={styles.selectOption}>
<Icon className="margin-r8" name={option.icon} type="light" size={20} />
<span className={styles.text}>{option.label}</span>
{option.disabled && (
<Tooltip content={t('OPENELB_NOT_READY')}>
<Icon name={'question'} size="16"></Icon>
</Tooltip>
)}
</div>
)

handleProvideChange = provider => {
this.setState({
provider,
})
}

render() {
const { mode, provider, openELBOpened } = this.state
const options = [
...CLUSTER_PROVIDERS,
{
label: 'OpenELB',
value: 'OpenELB',
icon: 'kubernetes',
disabled: !openELBOpened,
tip: '',
},
]
return (
<>
<Form.Item label={t('ACCESS_MODE')}>
<Select
name={`Service.${this.fedPreifx}spec.type`}
options={this.accessModes}
onChange={this.handleAccessModeChange}
optionRenderer={this.optionRenderer}
placeholder=" "
/>
</Form.Item>
<Columns>
<Column>
<Form.Item label={t('ACCESS_MODE')}>
<Select
name={`Service.${this.fedPreifx}spec.type`}
options={this.accessModes}
onChange={this.handleAccessModeChange}
></Select>
</Form.Item>
</Column>
{mode === 'LoadBalancer' && (
<Column>
<Form.Item label={t('LOAD_BALANCER_PROVIDER')}>
<Select
options={options}
placeholder=" "
optionRenderer={this.providerOptionRenderer}
onChange={this.handleProvideChange}
value={provider}
></Select>
</Form.Item>
</Column>
)}
</Columns>
{mode === 'LoadBalancer' && (
<Form.Item label={t('ANNOTATION_PL')}>
<PropertiesInput
name="Service.metadata.annotations"
hiddenKeys={globals.config.preservedAnnotations}
onChange={this.handleAnnotationsChange}
addText={t('ADD')}
/>
</Form.Item>
<Columns>
<Column>
<Form.Item label={t('ANNOTATION_PL')}>
<AnnotationsInput
name="Service.metadata.annotations"
options={this.providerOptions}
hiddenKeys={globals.config.preservedAnnotations}
onChange={this.handleAnnotationsChange}
addText={t('ADD')}
/>
</Form.Item>
</Column>
</Columns>
)}
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,12 @@
@include TypographyParagraph($dark-color01);
}
}

.selectOption {
display: flex;

.text {
display: inline-block;
flex: 1;
}
}
9 changes: 9 additions & 0 deletions src/components/Forms/Service/AdvanceSettings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { Form } from '@kube-design/components'
import { NumberInput } from 'components/Inputs'
import PodIPRange from 'components/Forms/Workload/AdvanceSettings/PodIPRange'

import { toJS } from 'mobx'
import Metadata from './Metadata'
import NodeSchedule from './NodeSchedule'
import InternetAccess from './InternetAccess'
Expand All @@ -42,6 +43,13 @@ export default class AdvancedSettings extends React.Component {
return MODULE_KIND_MAP[module]
}

get clusters() {
const { projectDetail, cluster, isFederated } = this.props
return isFederated
? toJS(projectDetail.clusters).map(item => item.name)
: [cluster]
}

handleLabelsChange = labels => {
const { formTemplate, noWorkload } = this.props
if (!noWorkload) {
Expand Down Expand Up @@ -105,6 +113,7 @@ export default class AdvancedSettings extends React.Component {
<InternetAccess
formTemplate={formTemplate}
isFederated={isFederated}
clusters={this.clusters}
/>
</Form.Group>
)}
Expand Down
44 changes: 44 additions & 0 deletions src/stores/openelb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This file is part of KubeSphere Console.
* Copyright (C) 2019 The KubeSphere Console Authors.
*
* KubeSphere Console is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KubeSphere Console is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with KubeSphere Console. If not, see <https://www.gnu.org/licenses/>.
*/

import Base from './base'

export default class OpenELBStore extends Base {
get apiVersion() {
return 'kapis/openelb.kubesphere.io/v1alpha2'
}

isActive = async ({ clusters }) => {
const req = []
clusters.forEach(cluster => {
req.push(
request.get(
`${this.apiVersion}${this.getPath({ cluster })}/detect`,
{},
{},
() => {
return false
}
)
)
})

const res = await Promise.all(req)
return res.every(item => !!item)
}
}

0 comments on commit 8018aca

Please sign in to comment.