mirror of https://github.com/portainer/portainer
feat(edge): add EnvVar to stack details [EE-5463] (#9036)
parent
1a9a564553
commit
f5e09618f0
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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[];
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue