Skip to content

Commit

Permalink
feat: Add imagebuilder in DevOps module (#4203)
Browse files Browse the repository at this point in the history
add imagebuilder in DevOps module
  • Loading branch information
Ganbingkun authored Oct 31, 2023
1 parent dfbb490 commit dd46756
Show file tree
Hide file tree
Showing 29 changed files with 2,291 additions and 29 deletions.
6 changes: 4 additions & 2 deletions locales/en/l10n-projects-imageBuilders-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ module.exports = {
IMAGE_NAME_EMPTY_DESC: 'Please enter an image name.',
IMAGE_TAG_EMPTY_DESC: 'Please enter an image tag.',
TARGET_IMAGE_REPOSITORY_EMPTY_DESC: 'Please set a target image registry.',
// List > Edit Information
// List > Delete
VALIDATE_SUCCESS: 'Validation succeeded',
VALIDATE_FAILED: 'Validation failed',
RUN_SUCCESSFUL: 'Run succeeded',
RUN_FAILED: 'Run failed',
}
6 changes: 5 additions & 1 deletion locales/zh/l10n-projects-imageBuilders-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,9 @@ module.exports = {
WRONG_FILE_EXTENSION_NAME: '选择的文件类型不匹配,请选择 {type} 类型。',
IMAGE_NAME_EMPTY_DESC: '请输入镜像名称。',
IMAGE_TAG_EMPTY_DESC: '请输入镜像标签。',
TARGET_IMAGE_REPOSITORY_EMPTY_DESC: '请设置目标镜像服务。'
TARGET_IMAGE_REPOSITORY_EMPTY_DESC: '请设置目标镜像服务。',
VALIDATE_SUCCESS: '校验成功',
VALIDATE_FAILED: '校验失败',
RUN_SUCCESSFUL: '运行成功',
RUN_FAILED: '运行失败',
};
6 changes: 6 additions & 0 deletions server/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,12 @@ client:
authKey: "gitrepositories",
requiredClusterVersion: v3.3.0,
}
- {
name: imageBuilders,
title: IMAGE_BUILDER_PL,
icon: vnas,
clusterModule: imagebuilds,
}
- name: management
title: DEVOPS_PROJECT_SETTINGS
icon: cogwheel
Expand Down
97 changes: 97 additions & 0 deletions src/actions/devopsImageBuilder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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 { Notify } from '@kube-design/components'
import { Modal } from 'components/Base'

import CreateModal from 'components/Modals/Create'
import EditBasicInfoModal from 'components/Modals/EditBasicInfo'
import FORM_STEPS from 'configs/steps/devopsImageBuilder'
import { get, set } from 'lodash'
import moment from 'moment-mini'

export default {
'devops.imagebuilder.create': {
on({ store, cluster, namespace, module, success, ...props }) {
const formTemplate = store.getFormTemplate({
namespace,
})

const modal = Modal.open({
onOk: data => {
if (!data) {
return
}

set(data, 'spec.source.revisionId', undefined)
set(
data,
'spec.output.image',
`${get(data, 'spec.output.image')}:${get(data, 'spec.output.tag')}`
)
const now = moment().format('YYYYMMDDHHmmss')
set(
data,
'metadata.name',
`${get(
data,
'metadata.annotations.languageType',
'image-builder'
)}-${now}-${Math.random()
.toString(32)
.slice(2)}`
)
store.create(data, { cluster, namespace }).then(() => {
Modal.close(modal)
Notify.success({ content: t('CREATE_SUCCESSFUL') })
success && success()
})
},
module,
cluster,
namespace,
hideB2i: true,
hideAdvanced: true,
name: 'IMAGE_BUILDER',
formTemplate,
steps: FORM_STEPS,
modal: CreateModal,
noCodeEdit: true,
store,
...props,
})
},
},
'devops.imagebuilder.baseinfo.edit': {
on({ store, detail, success, ...props }) {
const modal = Modal.open({
onOk: _data => {
store.update(detail, _data).then(() => {
Modal.close(modal)
Notify.success({ content: t('UPDATE_SUCCESSFUL') })
success && success()
})
},
detail,
modal: EditBasicInfoModal,
store,
...props,
})
},
},
}
137 changes: 137 additions & 0 deletions src/components/Forms/DevopsImageBuilder/LanguageSelect/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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 React from 'react'
import { set, get, unset } from 'lodash'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { Form, Icon, Alert, Input } from '@kube-design/components'
import S2iBuilderStore from 'stores/devops/imgBuilder'
import { getLanguageIcon } from 'utils/devops'

import S2IForm from '../S2IForm'
import styles from './index.scss'

export default class LanguageSelect extends React.Component {
constructor(props) {
super(props)
this.store = new S2iBuilderStore()
this.state = {
s2i: [],
b2i: [],
}
}

static contextTypes = {
setSteps: PropTypes.func,
}

componentDidMount() {
this.fetchData()
}

fetchData = async () => {
const { cluster } = this.props
const supportS2iLanguage = await this.store.getS2iSupportLanguage({
cluster,
})
this.setState(supportS2iLanguage)
}

handleLanguageSelect = languageType => () => {
const { steps } = this.props

set(steps, '[1].component', S2IForm)
set(
this.props.formTemplate,
'metadata.labels["s2i-type.kubesphere.io"]',
's2i'
)
unset(this.props.formTemplate, 'spec.config.isBinaryURL')
this.context.setSteps(steps)

set(
this.props.formTemplate,
'metadata.annotations.languageType',
languageType
)

unset(this.props.formTemplate, 'spec.config.builderImage')

this.forceUpdate()
}

renderSupportTip = () => {
if (globals.runtime.toLowerCase() === 'containerd') {
return (
<Alert
className={styles.margin_b_10}
type="warning"
message={t('CONTAINERD_RUNTIME_NOT_SUPPORTED')}
/>
)
}
}

render() {
const { formTemplate, formRef } = this.props
const languageType = get(
this.props.formTemplate,
'metadata.annotations.languageType'
)
const buildType = get(
this.props.formTemplate,
'metadata.labels["s2i-type.kubesphere.io"]',
's2i'
)
return (
<Form ref={formRef} data={formTemplate}>
{this.renderSupportTip()}

<div className={styles.header}>
<p>{t('IMAGE_FROM_S2I')}</p>
<p>{t('S2I_DESC')}</p>
</div>
<ul className={styles.content}>
{this.state.s2i.map(type => (
<li
key={type}
className={classnames(styles.item, {
[styles.item_select]:
languageType === type && buildType === 's2i',
})}
onClick={this.handleLanguageSelect(type)}
>
<Icon name={getLanguageIcon(type, 'radio')} size={48} />
<p>{t(type.toUpperCase())}</p>
</li>
))}
</ul>
<Form.Item
rules={[{ required: true, message: t('EMPTY_IMAGE_TYPE_DESC') }]}
>
<Input
style={{ display: 'none' }}
readOnly
name="metadata.annotations.languageType"
></Input>
</Form.Item>
</Form>
)
}
}
52 changes: 52 additions & 0 deletions src/components/Forms/DevopsImageBuilder/LanguageSelect/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@import '~scss/variables';
@import '~scss/mixins';

.header {
margin-bottom: 12px;
p:first-child {
height: 20px;
@include TypographyTitleH6;
}
p:last-child {
height: 20px;
@include TypographyParagraph($dark-color01);
}
}

.content {
display: flex;
margin-bottom: 20px;

li {
margin-right: 12px;
padding: 14px;
width: 134px;
height: 100px;
border-radius: 4px;
border: solid 1px $border-color;
background-color: #ffffff;
text-align: center;

&:hover {
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.2);
border: solid 1px $dark-color01;
}

img {
width: 46px;
}
p {
height: 20px;
@include TypographyTitleH6;
}
}
}

.item_select {
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.2);
border: solid 1px $dark-color01 !important;
}

.margin_b_10 {
margin-bottom: 10px;
}
Loading

0 comments on commit dd46756

Please sign in to comment.