mirror of https://github.com/kubevela/velaux.git
Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
|
d3710a66ca | |
|
cedb5774bc | |
|
74695e5d4f | |
|
108069563d | |
|
b959214ca7 | |
|
a61257617a | |
|
d342b28cd0 |
|
@ -165,7 +165,6 @@ export const ComponentNode = (props: ComponentNodeProps) => {
|
|||
</Balloon>
|
||||
);
|
||||
};
|
||||
|
||||
const graphNode = (
|
||||
<div
|
||||
className={classNames('graph-node', 'graph-node-resource', {
|
||||
|
@ -203,7 +202,7 @@ export const ComponentNode = (props: ComponentNodeProps) => {
|
|||
|
||||
<If condition={traits.length > 0}>
|
||||
<div className={classNames('label-traits')}>
|
||||
{traits && (
|
||||
{traits && traits.length > 0 && traits[0] && (
|
||||
<Tag animation={true}>
|
||||
<span
|
||||
className={classNames('circle', {
|
||||
|
|
|
@ -34,7 +34,7 @@ class MemoryNumber extends React.Component<Props, State> {
|
|||
id={id}
|
||||
min="0"
|
||||
disabled={disabled}
|
||||
addonTextAfter="MB"
|
||||
addonTextAfter="Mi"
|
||||
htmlType="number"
|
||||
onChange={this.onChange}
|
||||
value={initValue && initValue}
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
"Policies": "策略",
|
||||
"Policy": "策略",
|
||||
"New Policy": "新增策略",
|
||||
"Policy Type": "策略类型",
|
||||
"Update Policy": "编辑策略",
|
||||
"Warning": "部署异常",
|
||||
"EnvironmentPlan": "环境规划",
|
||||
"BasisConfig": "基准配置",
|
||||
|
|
|
@ -467,7 +467,8 @@ class PolicyDialog extends React.Component<Props, State> {
|
|||
this.uiSchemaRef.current?.validate(callback);
|
||||
};
|
||||
const init = this.field.init;
|
||||
const span = selectedPolicyItem && selectedPolicyItem?.name == 'custom' ? 8 : 12;
|
||||
const showType = (selectedPolicyItem && selectedPolicyItem?.name == 'custom') || policy != undefined;
|
||||
const span = showType ? 8 : 12;
|
||||
return (
|
||||
<DrawerWithFooter
|
||||
title={policy ? i18n.t('Update Policy') : i18n.t('New Policy')}
|
||||
|
@ -478,7 +479,7 @@ class PolicyDialog extends React.Component<Props, State> {
|
|||
>
|
||||
<Form field={this.field}>
|
||||
<Card contentHeight="auto" title={i18n.t('Select a policy type').toString()}>
|
||||
<If condition={!policy}>
|
||||
{!policy && (
|
||||
<Row wrap={true}>
|
||||
{items.map((item) => {
|
||||
return (
|
||||
|
@ -496,12 +497,12 @@ class PolicyDialog extends React.Component<Props, State> {
|
|||
);
|
||||
})}
|
||||
</Row>
|
||||
</If>
|
||||
<If condition={selectedPolicyItem}>
|
||||
)}
|
||||
{selectedPolicyItem && (
|
||||
<Row wrap={true}>
|
||||
{selectedPolicyItem && selectedPolicyItem?.name == 'custom' && (
|
||||
{showType && (
|
||||
<Col span={span} style={{ padding: '0 8px' }}>
|
||||
<Form.Item label="Policy Type" required>
|
||||
<Form.Item label={i18n.t('Policy Type')} required>
|
||||
<Select
|
||||
{...init('type', {
|
||||
rules: [
|
||||
|
@ -569,7 +570,7 @@ class PolicyDialog extends React.Component<Props, State> {
|
|||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</If>
|
||||
)}
|
||||
<If condition={selectedPolicyItem?.properties}>
|
||||
<Message style={{ marginTop: '8px' }} type="success">
|
||||
<Translation>This policy already have the default properties</Translation>
|
||||
|
|
|
@ -27,6 +27,8 @@ import type { Endpoint } from '../../../../interface/observation';
|
|||
import type { Target } from '../../../../interface/target';
|
||||
import { locale } from '../../../../utils/locale';
|
||||
import { getLink } from '../../../../utils/utils';
|
||||
import { checkPermission } from '../../../../utils/permission';
|
||||
import { LoginUserInfo } from '../../../../interface/user';
|
||||
|
||||
export type GatewayIP = {
|
||||
ip: string;
|
||||
|
@ -47,6 +49,7 @@ type Props = {
|
|||
disableStatusShow?: boolean;
|
||||
refresh: () => void;
|
||||
dispatch: ({}) => void;
|
||||
userInfo?: LoginUserInfo;
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -162,11 +165,23 @@ class Header extends Component<Props, State> {
|
|||
};
|
||||
|
||||
compareCurrentWithCluster = (appName: string, envName: string) => {
|
||||
const { applicationStatus } = this.props;
|
||||
const { applicationStatus, applicationDetail, userInfo } = this.props;
|
||||
if (!applicationStatus) {
|
||||
this.setState({ compare: undefined });
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!checkPermission(
|
||||
{
|
||||
resource: `project:${applicationDetail?.project?.name}/application:${applicationDetail?.name}`,
|
||||
action: 'compare',
|
||||
},
|
||||
applicationDetail?.project?.name,
|
||||
userInfo
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
compareApplication(appName, { compareLatestWithRunning: { env: envName } }).then(
|
||||
(res: ApplicationCompareResponse) => {
|
||||
this.setState({ compare: res });
|
||||
|
|
|
@ -466,6 +466,7 @@ class ApplicationInstanceList extends React.Component<Props, State> {
|
|||
<div>
|
||||
<Header
|
||||
envbinding={envbinding}
|
||||
userInfo={userInfo}
|
||||
targets={this.getTargets()}
|
||||
components={components}
|
||||
envName={envName}
|
||||
|
|
|
@ -306,6 +306,7 @@ class ApplicationStatusPage extends React.Component<Props, State> {
|
|||
<div className="application-status-wrapper">
|
||||
<Loading visible={loading && endpointLoading} style={{ width: '100%' }}>
|
||||
<Header
|
||||
userInfo={userInfo}
|
||||
envbinding={this.getEnvbindingByName()}
|
||||
targets={this.getTargets()}
|
||||
envName={envName}
|
||||
|
|
|
@ -24,6 +24,7 @@ import { beautifyTime } from '../../utils/common';
|
|||
import { locale } from '../../utils/locale';
|
||||
|
||||
import ApplicationWorkflowRecord from './components/WorkflowRecord';
|
||||
import { LoginUserInfo } from '../../interface/user';
|
||||
|
||||
const { Row, Col } = Grid;
|
||||
|
||||
|
@ -34,6 +35,7 @@ type Props = {
|
|||
applicationStatus?: ApplicationStatus;
|
||||
envbinding: EnvBinding[];
|
||||
workflows: Workflow[];
|
||||
userInfo?: LoginUserInfo;
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -49,7 +51,7 @@ type State = {
|
|||
};
|
||||
|
||||
@connect((store: any) => {
|
||||
return { ...store.application };
|
||||
return { ...store.application, ...store.user };
|
||||
})
|
||||
class ApplicationWorkflow extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
|
@ -136,7 +138,7 @@ class ApplicationWorkflow extends React.Component<Props, State> {
|
|||
runApplicationWorkflow = () => {};
|
||||
|
||||
render() {
|
||||
const { applicationDetail, dispatch, applicationStatus, workflows } = this.props;
|
||||
const { applicationDetail, dispatch, applicationStatus, workflows, userInfo } = this.props;
|
||||
const {
|
||||
params: { record, appName, envName },
|
||||
} = this.props.match;
|
||||
|
@ -177,6 +179,7 @@ class ApplicationWorkflow extends React.Component<Props, State> {
|
|||
return (
|
||||
<div className="run-layout">
|
||||
<Header
|
||||
userInfo={userInfo}
|
||||
envbinding={this.getEnvbindingByName()}
|
||||
envName={envName}
|
||||
appName={appName}
|
||||
|
|
|
@ -3,7 +3,6 @@ import React from 'react';
|
|||
|
||||
import { createUser, updateUser } from '../../../../api/users';
|
||||
import DrawerWithFooter from '../../../../components/Drawer';
|
||||
import { If } from '../../../../components/If';
|
||||
import { Translation } from '../../../../components/Translation';
|
||||
import i18n from '../../../../i18n';
|
||||
import type { RolesBase } from '../../../../interface/roles';
|
||||
|
@ -196,7 +195,7 @@ class CreateUser extends React.Component<Props, State> {
|
|||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<If condition={!isEditUser}>
|
||||
{!isEditUser && (
|
||||
<Col span={12} style={{ padding: '0 8px' }}>
|
||||
<FormItem label={<Translation>Password</Translation>} required>
|
||||
<Input
|
||||
|
@ -220,7 +219,7 @@ class CreateUser extends React.Component<Props, State> {
|
|||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
</If>
|
||||
)}
|
||||
<Col span={12} style={{ padding: '0 8px' }}>
|
||||
<FormItem label={<Translation>Email</Translation>} required>
|
||||
<Input
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
velaerr "github.com/oam-dev/kubevela/pkg/utils/errors"
|
||||
|
||||
"github.com/kubevela/velaux/pkg/server/domain/model"
|
||||
"github.com/kubevela/velaux/pkg/server/infrastructure/datastore"
|
||||
|
@ -38,28 +37,15 @@ func CreateTargetNamespace(ctx context.Context, k8sClient client.Client, cluster
|
|||
if clusterName == "" || namespace == "" {
|
||||
return bcode.ErrTargetInvalidWithEmptyClusterOrNamespace
|
||||
}
|
||||
err := utils.CreateOrUpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace, utils.MergeOverrideLabels(map[string]string{
|
||||
return utils.CreateOrUpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace, utils.MergeOverrideLabels(map[string]string{
|
||||
oam.LabelRuntimeNamespaceUsage: oam.VelaNamespaceUsageTarget,
|
||||
}), utils.MergeNoConflictLabels(map[string]string{
|
||||
oam.LabelNamespaceOfTargetName: targetName,
|
||||
}))
|
||||
if velaerr.IsLabelConflict(err) {
|
||||
klog.Errorf("update namespace for target err %v", err)
|
||||
return bcode.ErrTargetNamespaceAlreadyBound
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteTargetNamespace delete the namespace of the target
|
||||
func DeleteTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error {
|
||||
err := utils.UpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace,
|
||||
// check no conflict label first to make sure the namespace belong to the target, then override it
|
||||
utils.MergeNoConflictLabels(map[string]string{
|
||||
oam.LabelNamespaceOfTargetName: targetName,
|
||||
}),
|
||||
utils.MergeOverrideLabels(map[string]string{
|
||||
oam.LabelRuntimeNamespaceUsage: "",
|
||||
oam.LabelNamespaceOfTargetName: "",
|
||||
|
|
|
@ -492,8 +492,14 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) {
|
|||
klog.Errorf("failed to get the system info %s", err.Error())
|
||||
}
|
||||
user := &model.User{
|
||||
Email: claims.Email,
|
||||
Name: strings.ToLower(claims.Sub),
|
||||
Email: claims.Email,
|
||||
Name: func() string {
|
||||
sub := strings.ToLower(claims.Sub)
|
||||
if len(sub) > datastore.PrimaryKeyMaxLength {
|
||||
return sub[:datastore.PrimaryKeyMaxLength]
|
||||
}
|
||||
return sub
|
||||
}(),
|
||||
DexSub: claims.Sub,
|
||||
Alias: claims.Name,
|
||||
LastLoginTime: time.Now(),
|
||||
|
|
|
@ -46,6 +46,9 @@ var (
|
|||
ErrEntityInvalid = NewDBError(fmt.Errorf("entity is invalid"))
|
||||
)
|
||||
|
||||
// PrimaryKeyMaxLength The primary key length should be limited when the datastore is kube-api
|
||||
var PrimaryKeyMaxLength = 31
|
||||
|
||||
// DBError datastore error
|
||||
type DBError struct {
|
||||
err error
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/go-playground/validator/v10"
|
||||
|
||||
"github.com/kubevela/velaux/pkg/server/domain/service"
|
||||
"github.com/kubevela/velaux/pkg/server/infrastructure/datastore"
|
||||
)
|
||||
|
||||
var validate = validator.New()
|
||||
|
@ -72,7 +73,7 @@ func ValidatePayloadType(fl validator.FieldLevel) bool {
|
|||
// ValidateName custom check name field
|
||||
func ValidateName(fl validator.FieldLevel) bool {
|
||||
value := fl.Field().String()
|
||||
if len(value) > 31 || len(value) < 2 {
|
||||
if len(value) > datastore.PrimaryKeyMaxLength || len(value) < 2 {
|
||||
return false
|
||||
}
|
||||
return nameRegexp.MatchString(value)
|
||||
|
|
Loading…
Reference in New Issue