Răsfoiți Sursa

deploy from template

sunguroku 5 ani în urmă
părinte
comite
f76a54bf3b

+ 46 - 1
dashboard/src/main/home/templates/expanded-template/LaunchTemplate.tsx

@@ -19,11 +19,13 @@ type PropsType = {
 type StateType = {
   currentView: string,
   clusterOptions: { label: string, value: string }[],
+  selectedNamespace: string,
   selectedCluster: string,
   selectedImageUrl: string | null,
   selectedTag: string | null,
   tabOptions: ChoiceType[],
   tabContents: any
+  namespaceOptions: { label: string, value: string }[],
 };
 
 export default class LaunchTemplate extends Component<PropsType, StateType> {
@@ -31,10 +33,12 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
     currentView: 'repo',
     clusterOptions: [] as { label: string, value: string }[],
     selectedCluster: this.context.currentCluster.name,
+    selectedNamespace: "default",
     selectedImageUrl: '' as string | null,
     selectedTag: '' as string | null,
     tabOptions: [] as ChoiceType[],
     tabContents: [] as any,
+    namespaceOptions: [] as { label: string, value: string }[],
   };
 
   onSubmit = (formValues: any) => {
@@ -44,6 +48,8 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
       imageURL: "index.docker.io/bitnami/redis",
       storage: StorageType.Secret,
       formValues,
+      namespace: this.state.selectedNamespace,
+      name: "random",
     }, {
       id: currentProject.id,
       cluster_id: currentCluster.id,
@@ -81,17 +87,33 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
     this.refreshTabs();
 
     // TODO: query with selected filter once implemented
-    let { currentProject } = this.context;
+    let { currentProject, currentCluster } = this.context;
     api.getClusters('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
       if (err) {
         // console.log(err)
       } else if (res.data) {
+        console.log(res.data)
         let clusterOptions = res.data.map((x: Cluster) => { return { label: x.name, value: x.name } });
         if (res.data.length > 0) {
           this.setState({ clusterOptions });
         }
       }
     });
+
+    api.getNamespaces('<token>', {
+      cluster_id: currentCluster.id,
+    }, { id: currentProject.id }, (err: any, res: any) => {
+      if (err) {
+        console.log(err)
+      } else if (res.data) {
+        let namespaceOptions = res.data.items.map((x: { metadata: {name: string}}) => { 
+          return { label: x.metadata.name, value: x.metadata.name } 
+        });
+        if (res.data.items.length > 0) {
+          this.setState({ namespaceOptions });
+        }
+      }
+    });
   }
 
   componentDidUpdate(prevProps: PropsType, prevState: StateType) {
@@ -142,6 +164,18 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
             dropdownWidth='335px'
             closeOverlay={true}
           />
+          <NamespaceLabel>
+            <i className="material-icons">view_list</i>Namespace
+          </NamespaceLabel>
+          <Selector
+            key={'namespace'}
+            activeValue={this.state.selectedNamespace}
+            setActiveValue={(namespace: string) => this.setState({ selectedNamespace: namespace })}
+            options={this.state.namespaceOptions}
+            width='250px'
+            dropdownWidth='335px'
+            closeOverlay={true}
+          />
         </ClusterSection>
 
         <Subtitle>Select the container image you would like to connect to this template.</Subtitle>
@@ -199,6 +233,17 @@ const ClusterLabel = styled.div`
   }
 `;
 
+const NamespaceLabel = styled.div`
+  margin-left: 15px;
+  margin-right: 10px;
+  display: flex;
+  align-items: center;
+  > i {
+    font-size: 16px;
+    margin-right: 6px;
+  }
+`;
+
 const Icon = styled.img`
   width: 21px;
   margin-right: 10px;

+ 2 - 0
dashboard/src/shared/api.tsx

@@ -158,6 +158,8 @@ const deployTemplate = baseApi<{
   imageURL: string,
   formValues: any,
   storage: StorageType,
+  namespace: string,
+  name: string,
 }, { id: number, cluster_id: number }>('POST', pathParams => {
   let { cluster_id, id } = pathParams;
   return `/api/projects/${id}/deploy?cluster_id=${cluster_id}`;

+ 1 - 0
internal/forms/release.go

@@ -119,6 +119,7 @@ type ChartTemplateForm struct {
 	TemplateName string                 `json:"templateName" form:"required"`
 	ImageURL     string                 `json:"imageURL" form:"required"`
 	FormValues   map[string]interface{} `json:"formValues"`
+	Name         string                 `json:"name"`
 }
 
 // InstallChartTemplateForm represents the accepted values for installing a new chart from a template.

+ 12 - 2
internal/helm/agent.go

@@ -88,8 +88,17 @@ func (a *Agent) UpgradeRelease(
 func (a *Agent) InstallChart(
 	cp string,
 	values []byte,
+	name string,
+	namespace string,
 ) (*release.Release, error) {
-	cmd := action.NewInstall(a.ActionConfig)
+	client := action.NewInstall(a.ActionConfig)
+
+	if client.Version == "" && client.Devel {
+		client.Version = ">0.0.0-0"
+	}
+
+	client.ReleaseName = name
+	client.Namespace = namespace
 	valuesYaml, err := chartutil.ReadValues(values)
 
 	if err != nil {
@@ -99,6 +108,7 @@ func (a *Agent) InstallChart(
 	// Only supports filepaths for now, URL option WIP.
 	// Check chart dependencies to make sure all are present in /charts
 	chartRequested, err := loader.Load(cp)
+
 	if err != nil {
 		return nil, err
 	}
@@ -118,7 +128,7 @@ func (a *Agent) InstallChart(
 		}
 	}
 
-	return cmd.Run(chartRequested, valuesYaml)
+	return client.Run(chartRequested, valuesYaml)
 }
 
 // RollbackRelease rolls a release back to a specified revision/version

+ 16 - 2
server/api/deploy_handler.go

@@ -22,6 +22,7 @@ import (
 // HandleDeployTemplate triggers a chart deployment from a template
 func (app *App) HandleDeployTemplate(w http.ResponseWriter, r *http.Request) {
 	vals, err := url.ParseQuery(r.URL.RawQuery)
+
 	if err != nil {
 		app.handleErrorFormDecoding(err, ErrReleaseDecode, w)
 		return
@@ -98,13 +99,26 @@ func (app *App) HandleDeployTemplate(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	var tgz string
+	switch form.ChartTemplateForm.TemplateName {
+	case "react":
+		tgz = "react-0.1.5.tgz"
+	case "docker":
+		tgz = "docker-0.0.1.tgz"
+	}
+
 	// Output values.yaml string
-	_, err = agent.InstallChart("./internal/local_templates/react-0.1.5.tgz", v)
+	_, err = agent.InstallChart(
+		"./internal/local_templates/"+tgz,
+		v,
+		form.ChartTemplateForm.Name,
+		form.ReleaseForm.Form.Namespace,
+	)
 
 	if err != nil {
 		app.sendExternalError(err, http.StatusInternalServerError, HTTPError{
 			Code:   ErrReleaseDeploy,
-			Errors: []string{"error installing a new chart" + err.Error()},
+			Errors: []string{"error installing a new chart: " + err.Error()},
 		}, w)
 
 		return