From 3f700f1b266c98bc01a77e9534c5582cb8d628c3 Mon Sep 17 00:00:00 2001 From: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Date: Wed, 9 Jun 2021 15:02:47 +1200 Subject: [PATCH] feat(stack): UI updates in git repo deployment method for k8s EE-640. (#5097) * feat(stack): UI updates in git repo deployment method for k8s EE-640. * feat(stack): supports the combination of GIT + COMPOSE. * feat(stack): rename variable --- app/kubernetes/models/deploy.js | 10 + app/kubernetes/views/deploy/deploy.html | 185 +++++++++++++++--- .../views/deploy/deployController.js | 39 +++- app/portainer/services/api/stackService.js | 13 +- 4 files changed, 201 insertions(+), 46 deletions(-) diff --git a/app/kubernetes/models/deploy.js b/app/kubernetes/models/deploy.js index d9e0d8363..34fe609fe 100644 --- a/app/kubernetes/models/deploy.js +++ b/app/kubernetes/models/deploy.js @@ -2,3 +2,13 @@ export const KubernetesDeployManifestTypes = Object.freeze({ KUBERNETES: 1, COMPOSE: 2, }); + +export const KubernetesDeployBuildMethods = Object.freeze({ + GIT: 1, + WEB_EDITOR: 2, +}); + +export const KubernetesDeployRequestMethods = Object.freeze({ + REPOSITORY: 'repository', + STRING: 'string', +}); diff --git a/app/kubernetes/views/deploy/deploy.html b/app/kubernetes/views/deploy/deploy.html index ceed8c17e..549dc93eb 100644 --- a/app/kubernetes/views/deploy/deploy.html +++ b/app/kubernetes/views/deploy/deploy.html @@ -52,41 +52,162 @@ - + +
- Web editor + Build method
-
- -

- - Portainer uses Kompose to convert your Compose manifest to a Kubernetes compliant manifest. Be wary that not - all the Compose format options are supported by Kompose at the moment. -

-

- You can get more information about Compose file format in the - official documentation. -

-
- -

- - This feature allows you to deploy any kind of Kubernetes resource in this environment (Deployment, Secret, ConfigMap...). -

-

- You can get more information about Kubernetes file format in the - official documentation. -

-
+
+
+
+
+ + +
+
+ + +
+
-
-
- + + + + +
+
+ Git repository +
+
+ + You can use the URL of a git repository. + +
+
+ +
+ +
+
+
+ + Specify a reference of the repository using the following syntax: branches with + refs/heads/branch_name or tags with refs/tags/tag_name. If not specified, will use the default HEAD reference normally + the master branch. + +
+
+ +
+ +
+
+
+ + Indicate the path to the yaml file from the root of your repository. + +
+
+ +
+ +
+
+
+
+ + +
+
+
+ + If your git account has 2FA enabled, you may receive an + authentication required error when deploying your stack. In this case, you will need to provide a personal-access token instead of your password. + +
+
+ +
+ +
+ +
+ +
+
+
+ + + +
+
+ Web editor +
+
+ +

+ + Portainer uses Kompose to convert your Compose manifest to a Kubernetes compliant manifest. Be wary that + not all the Compose format options are supported by Kompose at the moment. +

+

+ You can get more information about Compose file format in the + official documentation. +

+
+ +

+ + This feature allows you to deploy any kind of Kubernetes resource in this environment (Deployment, Secret, ConfigMap...). +

+

+ You can get more information about Kubernetes file format in the + official documentation. +

+
+
+ +
+
+ +
diff --git a/app/kubernetes/views/deploy/deployController.js b/app/kubernetes/views/deploy/deployController.js index b2695399e..4ba2db976 100644 --- a/app/kubernetes/views/deploy/deployController.js +++ b/app/kubernetes/views/deploy/deployController.js @@ -1,7 +1,7 @@ import angular from 'angular'; import _ from 'lodash-es'; import stripAnsi from 'strip-ansi'; -import { KubernetesDeployManifestTypes } from 'Kubernetes/models/deploy'; +import { KubernetesDeployManifestTypes, KubernetesDeployBuildMethods, KubernetesDeployRequestMethods } from 'Kubernetes/models/deploy'; class KubernetesDeployController { /* @ngInject */ @@ -23,7 +23,15 @@ class KubernetesDeployController { } disableDeploy() { - return _.isEmpty(this.formValues.EditorContent) || _.isEmpty(this.formValues.Namespace) || this.state.actionInProgress; + const isGitFormInvalid = + this.state.BuildMethod === KubernetesDeployBuildMethods.GIT && + (!this.formValues.RepositoryURL || + !this.formValues.RepositoryReferenceName || + !this.formValues.FilePathInRepository || + (this.formValues.RepositoryAuthentication && (!this.formValues.RepositoryUsername || !this.formValues.RepositoryPassword))); + const isWebEditorInvalid = this.state.BuildMethod === KubernetesDeployBuildMethods.WEB_EDITOR && _.isEmpty(this.formValues.EditorContent); + + return isGitFormInvalid || isWebEditorInvalid || _.isEmpty(this.formValues.Namespace) || this.state.actionInProgress; } async editorUpdateAsync(cm) { @@ -46,8 +54,28 @@ class KubernetesDeployController { this.state.actionInProgress = true; try { - const compose = this.state.DeployType === this.ManifestDeployTypes.COMPOSE; - await this.StackService.kubernetesDeploy(this.endpointId, this.formValues.Namespace, this.formValues.EditorContent, compose); + const method = this.state.BuildMethod === this.BuildMethods.GIT ? KubernetesDeployRequestMethods.REPOSITORY : KubernetesDeployRequestMethods.STRING; + + const payload = { + ComposeFormat: this.state.DeployType === this.ManifestDeployTypes.COMPOSE, + Namespace: this.formValues.Namespace, + }; + + if (method === KubernetesDeployRequestMethods.REPOSITORY) { + payload.RepositoryURL = this.formValues.RepositoryURL; + payload.RepositoryReferenceName = this.formValues.RepositoryReferenceName; + payload.RepositoryAuthentication = this.formValues.RepositoryAuthentication ? true : false; + if (payload.RepositoryAuthentication) { + payload.RepositoryUsername = this.formValues.RepositoryUsername; + payload.RepositoryPassword = this.formValues.RepositoryPassword; + } + payload.FilePathInRepository = this.formValues.FilePathInRepository; + } else { + payload.StackFileContent = this.formValues.EditorContent; + } + + await this.StackService.kubernetesDeploy(this.endpointId, method, payload); + this.Notifications.success('Manifest successfully deployed'); this.state.isEditorDirty = false; this.$state.go('kubernetes.applications'); @@ -92,10 +120,10 @@ class KubernetesDeployController { return this.ModalService.confirmWebEditorDiscard(); } } - async onInit() { this.state = { DeployType: KubernetesDeployManifestTypes.KUBERNETES, + BuildMethod: KubernetesDeployBuildMethods.GIT, tabLogsDisabled: true, activeTab: 0, viewReady: false, @@ -104,6 +132,7 @@ class KubernetesDeployController { this.formValues = {}; this.ManifestDeployTypes = KubernetesDeployManifestTypes; + this.BuildMethods = KubernetesDeployBuildMethods; this.endpointId = this.EndpointProvider.endpointID(); await this.getNamespaces(); diff --git a/app/portainer/services/api/stackService.js b/app/portainer/services/api/stackService.js index 477740725..6a13494c6 100644 --- a/app/portainer/services/api/stackService.js +++ b/app/portainer/services/api/stackService.js @@ -322,21 +322,16 @@ angular.module('portainer.app').factory('StackService', [ return action(name, stackFileContent, env, endpointId); }; - async function kubernetesDeployAsync(endpointId, namespace, content, compose) { + async function kubernetesDeployAsync(endpointId, method, payload) { try { - const payload = { - StackFileContent: content, - ComposeFormat: compose, - Namespace: namespace, - }; - await Stack.create({ method: 'undefined', type: 3, endpointId: endpointId }, payload).$promise; + await Stack.create({ endpointId: endpointId, method: method, type: 3 }, payload).$promise; } catch (err) { throw { err: err }; } } - service.kubernetesDeploy = function (endpointId, namespace, content, compose) { - return $async(kubernetesDeployAsync, endpointId, namespace, content, compose); + service.kubernetesDeploy = function (endpointId, method, payload) { + return $async(kubernetesDeployAsync, endpointId, method, payload); }; service.start = start;