feat(edge): add EnvVar to stack details [EE-5463] (#9036)

pull/9150/head
Chaim Lev-Ari 2023-07-04 11:14:35 +07:00 committed by GitHub
parent 1a9a564553
commit f5e09618f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 59 additions and 6 deletions

View File

@ -1,6 +1,9 @@
package edge
import "github.com/portainer/portainer/api/filesystem"
import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/filesystem"
)
type (
@ -40,6 +43,9 @@ type (
SupportRelativePath bool
// Mount point for relative path
FilesystemPath string
// Used only for EE
// EnvVars is a list of environment variables to inject into the stack
EnvVars []portainer.Pair
}
// RegistryCredentials holds the credentials for a Docker registry.

View File

@ -4,6 +4,7 @@ import { STACK_NAME_VALIDATION_REGEX } from '@/react/constants';
import { confirmWebEditorDiscard } from '@@/modals/confirm';
import { baseEdgeStackWebhookUrl } from '@/portainer/helpers/webhookHelper';
import { EnvironmentType } from '@/react/portainer/environments/types';
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
export default class CreateEdgeStackViewController {
/* @ngInject */
@ -19,16 +20,17 @@ export default class CreateEdgeStackViewController {
RepositoryAuthentication: false,
RepositoryUsername: '',
RepositoryPassword: '',
Env: [],
ComposeFilePathInRepository: '',
Groups: [],
DeploymentType: 0,
UseManifestNamespaces: false,
TLSSkipVerify: false,
envVars: [],
};
this.EditorType = EditorType;
this.EnvironmentType = EnvironmentType;
this.isBE = isBE;
this.state = {
Method: 'editor',
@ -54,6 +56,13 @@ export default class CreateEdgeStackViewController {
this.onChangeGroups = this.onChangeGroups.bind(this);
this.hasType = this.hasType.bind(this);
this.onChangeDeploymentType = this.onChangeDeploymentType.bind(this);
this.onEnvVarChange = this.onEnvVarChange.bind(this);
}
onEnvVarChange(envVars) {
return this.$scope.$evalAsync(() => {
this.formValues.envVars = envVars;
});
}
buildAnalyticsProperties() {
@ -183,7 +192,7 @@ export default class CreateEdgeStackViewController {
}
createStackFromFileContent(name) {
const { StackFileContent, Groups, DeploymentType, UseManifestNamespaces } = this.formValues;
const { StackFileContent, Groups, DeploymentType, UseManifestNamespaces, envVars } = this.formValues;
return this.EdgeStackService.createStackFromFileContent({
name,
@ -191,24 +200,26 @@ export default class CreateEdgeStackViewController {
EdgeGroups: Groups,
DeploymentType,
UseManifestNamespaces,
envVars,
});
}
createStackFromFileUpload(name) {
const { StackFile, Groups, DeploymentType, UseManifestNamespaces } = this.formValues;
const { StackFile, Groups, DeploymentType, UseManifestNamespaces, envVars } = this.formValues;
return this.EdgeStackService.createStackFromFileUpload(
{
Name: name,
EdgeGroups: Groups,
DeploymentType,
UseManifestNamespaces,
envVars,
},
StackFile
);
}
createStackFromGitRepository(name) {
const { Groups, DeploymentType, UseManifestNamespaces } = this.formValues;
const { Groups, DeploymentType, UseManifestNamespaces, envVars } = this.formValues;
const repositoryOptions = {
RepositoryURL: this.formValues.RepositoryURL,
RepositoryReferenceName: this.formValues.RepositoryReferenceName,
@ -224,6 +235,7 @@ export default class CreateEdgeStackViewController {
EdgeGroups: Groups,
DeploymentType,
UseManifestNamespaces,
envVars,
},
repositoryOptions
);

View File

@ -66,6 +66,10 @@
state="$ctrl.state"
></edge-stacks-kube-manifest-form>
<div ng-if="$ctrl.isBE">
<environment-variables-panel values="$ctrl.formValues.envVars" on-change="($ctrl.onEnvVarChange)"></environment-variables-panel>
</div>
<!-- actions -->
<div class="col-sm-12 form-section-title"> Actions </div>
<div class="form-group">

View File

@ -102,6 +102,7 @@ export class EditEdgeStackViewController {
deploymentType: values.deploymentType,
updateVersion,
webhook: values.webhookEnabled ? this.stack.Webhook || createWebhookId() : '',
envVars: values.envVars,
});
this.Notifications.success('Success', 'Stack successfully deployed');
this.state.isStackDeployed = true;

View File

@ -111,12 +111,13 @@ angular.module('portainer.app').factory('FileUploadService', [
});
};
service.createEdgeStack = function createEdgeStack({ EdgeGroups, ...payload }, file) {
service.createEdgeStack = function createEdgeStack({ EdgeGroups, envVars, ...payload }, file) {
return Upload.upload({
url: `api/edge_stacks/create/file`,
data: {
file,
EdgeGroups: Upload.json(EdgeGroups),
EnvVars: Upload.json(envVars),
...payload,
},
ignoreLoadingBar: true,

View File

@ -15,6 +15,10 @@ import { TextTip } from '@@/Tip/TextTip';
import { SwitchField } from '@@/form-components/SwitchField';
import { LoadingButton } from '@@/buttons';
import { FormError } from '@@/form-components/FormError';
import {
EnvironmentVariablesPanel,
envVarValidation,
} from '@@/form-components/EnvironmentVariablesFieldset';
import { PrivateRegistryFieldsetWrapper } from './PrivateRegistryFieldsetWrapper';
import { FormValues } from './types';
@ -61,6 +65,7 @@ export function EditEdgeStackForm({
prePullImage: edgeStack.PrePullImage,
retryDeploy: edgeStack.RetryDeploy,
webhookEnabled: !!edgeStack.Webhook,
envVars: edgeStack.EnvVars || [],
};
return (
@ -181,6 +186,13 @@ function InnerForm({
onFieldError={(error) => setFieldError('privateRegistryId', error)}
error={errors.privateRegistryId}
/>
<EnvironmentVariablesPanel
onChange={(value) => setFieldValue('envVars', value)}
values={values.envVars}
errors={errors.envVars}
/>
{values.deploymentType === DeploymentType.Compose && (
<>
<div className="form-group">
@ -271,5 +283,6 @@ function formValidation(): SchemaOf<FormValues> {
.required()
.min(1, 'At least one edge group is required'),
webhookEnabled: boolean().default(false),
envVars: envVarValidation(),
});
}

View File

@ -31,6 +31,8 @@ import { LoadingButton } from '@@/buttons';
import { FormSection } from '@@/form-components/FormSection';
import { TextTip } from '@@/Tip/TextTip';
import { FormError } from '@@/form-components/FormError';
import { EnvironmentVariablesPanel } from '@@/form-components/EnvironmentVariablesFieldset';
import { EnvVar } from '@@/form-components/EnvironmentVariablesFieldset/types';
import { useValidateEnvironmentTypes } from '../useEdgeGroupHasType';
import { atLeastTwo } from '../atLeastTwo';
@ -43,6 +45,7 @@ interface FormValues {
autoUpdate: AutoUpdateModel;
refName: string;
authentication: GitAuthModel;
envVars: EnvVar[];
}
export function GitForm({ stack }: { stack: EdgeStack }) {
@ -63,6 +66,7 @@ export function GitForm({ stack }: { stack: EdgeStack }) {
autoUpdate: parseAutoUpdateResponse(stack.AutoUpdate),
refName: stack.GitConfig.ReferenceName,
authentication: parseAuthResponse(stack.GitConfig.Authentication),
envVars: stack.EnvVars || [],
};
const webhookId = stack.AutoUpdate?.Webhook || createWebhookId();
@ -253,6 +257,12 @@ function InnerForm({
}
errors={errors.authentication}
/>
<EnvironmentVariablesPanel
onChange={(value) => setFieldValue('envVars', value)}
values={values.envVars}
errors={errors.envVars}
/>
</FormSection>
<FormSection title="Actions">

View File

@ -1,6 +1,8 @@
import { EdgeGroup } from '@/react/edge/edge-groups/types';
import { DeploymentType } from '@/react/edge/edge-stacks/types';
import { EnvVar } from '@@/form-components/EnvironmentVariablesFieldset/types';
export interface FormValues {
edgeGroups: EdgeGroup['Id'][];
deploymentType: DeploymentType;
@ -10,4 +12,5 @@ export interface FormValues {
prePullImage: boolean;
retryDeploy: boolean;
webhookEnabled: boolean;
envVars: EnvVar[];
}

View File

@ -5,6 +5,8 @@ import {
} from '@/react/portainer/gitops/types';
import { RegistryId } from '@/react/portainer/registries/types';
import { EnvVar } from '@@/form-components/EnvironmentVariablesFieldset/types';
import { EdgeGroup } from '../edge-groups/types';
interface EdgeStackStatusDetails {
@ -57,6 +59,7 @@ export type EdgeStack = {
Prune: boolean;
RetryDeploy: boolean;
Webhook?: string;
EnvVars?: EnvVar[];
};
export enum EditorType {