Ver Fonte

Fix services not showing after deployment (#2974)

* fixing service not showing up after deployment

* reverting logging
Feroze Mohideen há 3 anos atrás
pai
commit
b5cd18a2e9

+ 13 - 7
api/server/handlers/stacks/create.go

@@ -63,13 +63,19 @@ func (c *CreateStackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	imageInfo := request.ImageInfo
-	chart, values, err := parse(porterYaml, imageInfo, c.Config(), cluster.ProjectID, SubdomainCreateOpts{
-		k8sAgent:       k8sAgent,
-		dnsRepo:        c.Repo().DNSRecord(),
-		powerDnsClient: c.Config().PowerDNSClient,
-		appRootDomain:  c.Config().ServerConf.AppRootDomain,
-		stackName:      stackName,
-	})
+	chart, values, err := parse(porterYaml,
+		imageInfo,
+		c.Config(),
+		cluster.ProjectID,
+		nil,
+		nil,
+		SubdomainCreateOpts{
+			k8sAgent:       k8sAgent,
+			dnsRepo:        c.Repo().DNSRecord(),
+			powerDnsClient: c.Config().PowerDNSClient,
+			appRootDomain:  c.Config().ServerConf.AppRootDomain,
+			stackName:      stackName,
+		})
 	if err != nil {
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error parsing porter yaml into chart and values: %w", err)))
 		return

+ 94 - 9
api/server/handlers/stacks/parse.go

@@ -48,7 +48,15 @@ type SubdomainCreateOpts struct {
 	stackName      string
 }
 
-func parse(porterYaml []byte, imageInfo types.ImageInfo, config *config.Config, projectID uint, opts SubdomainCreateOpts) (*chart.Chart, map[string]interface{}, error) {
+func parse(
+	porterYaml []byte,
+	imageInfo types.ImageInfo,
+	config *config.Config,
+	projectID uint,
+	existingValues map[string]interface{},
+	existingDependencies []*chart.Dependency,
+	opts SubdomainCreateOpts,
+) (*chart.Chart, map[string]interface{}, error) {
 	parsed := &PorterStackYAML{}
 
 	err := yaml.Unmarshal(porterYaml, parsed)
@@ -56,13 +64,13 @@ func parse(porterYaml []byte, imageInfo types.ImageInfo, config *config.Config,
 		return nil, nil, fmt.Errorf("%s: %w", "error parsing porter.yaml", err)
 	}
 
-	values, err := buildStackValues(parsed, imageInfo, opts)
+	values, err := buildStackValues(parsed, imageInfo, existingValues, opts)
 	if err != nil {
 		return nil, nil, fmt.Errorf("%s: %w", "error building values from porter.yaml", err)
 	}
 	convertedValues := convertMap(values).(map[string]interface{})
 
-	chart, err := buildStackChart(parsed, config, projectID)
+	chart, err := buildStackChart(parsed, config, projectID, existingDependencies)
 	if err != nil {
 		return nil, nil, fmt.Errorf("%s: %w", "error building chart from porter.yaml", err)
 	}
@@ -70,7 +78,7 @@ func parse(porterYaml []byte, imageInfo types.ImageInfo, config *config.Config,
 	return chart, convertedValues, nil
 }
 
-func buildStackValues(parsed *PorterStackYAML, imageInfo types.ImageInfo, opts SubdomainCreateOpts) (map[string]interface{}, error) {
+func buildStackValues(parsed *PorterStackYAML, imageInfo types.ImageInfo, existingValues map[string]interface{}, opts SubdomainCreateOpts) (map[string]interface{}, error) {
 	values := make(map[string]interface{})
 
 	for name, app := range parsed.Apps {
@@ -82,7 +90,24 @@ func buildStackValues(parsed *PorterStackYAML, imageInfo types.ImageInfo, opts S
 		if err != nil {
 			return nil, err
 		}
-		values[name] = helm_values
+
+		// required to identify the chart type because of https://github.com/helm/helm/issues/9214
+		helmName := getHelmName(name, appType)
+		if existingValues != nil {
+			if existingValues[helmName] != nil {
+				existingValuesMap := existingValues[helmName].(map[string]interface{})
+				helm_values = utils.DeepCoalesceValues(existingValuesMap, helm_values)
+			}
+		}
+
+		values[helmName] = helm_values
+	}
+
+	// add back in the existing values that were not overwritten
+	for k, v := range existingValues {
+		if values[k] == nil {
+			values[k] = v
+		}
 	}
 
 	if imageInfo.Repository != "" && imageInfo.Tag != "" {
@@ -138,24 +163,52 @@ func getDefaultValues(app *App, env map[string]string, appType string) map[strin
 	return defaultValues
 }
 
-func buildStackChart(parsed *PorterStackYAML, config *config.Config, projectID uint) (*chart.Chart, error) {
+func buildStackChart(parsed *PorterStackYAML, config *config.Config, projectID uint, existingDependencies []*chart.Dependency) (*chart.Chart, error) {
 	deps := make([]*chart.Dependency, 0)
-
 	for alias, app := range parsed.Apps {
-		appType := getType(alias, app)
+		var appType string
+		if existingDependencies != nil {
+			for _, dep := range existingDependencies {
+				// this condition checks that the dependency is of the form <alias>-web or <alias>-wkr or <alias>-job, meaning it already exists in the chart
+				if strings.HasPrefix(dep.Alias, fmt.Sprintf("%s-", alias)) && (strings.HasSuffix(dep.Alias, "-web") || strings.HasSuffix(dep.Alias, "-wkr") || strings.HasSuffix(dep.Alias, "-job")) {
+					appType = getChartTypeFromHelmName(dep.Alias)
+					if appType == "" {
+						return nil, fmt.Errorf("unable to determine type of existing dependency")
+					}
+				}
+			}
+			// this is a new app, so we need to get the type from the app name or type
+			if appType == "" {
+				appType = getType(alias, app)
+			}
+		} else {
+			appType = getType(alias, app)
+		}
 		selectedRepo := config.ServerConf.DefaultApplicationHelmRepoURL
 		selectedVersion, err := getLatestTemplateVersion(appType, config, projectID)
 		if err != nil {
 			return nil, err
 		}
+		helmName := getHelmName(alias, appType)
 		deps = append(deps, &chart.Dependency{
 			Name:       appType,
-			Alias:      alias,
+			Alias:      helmName,
 			Version:    selectedVersion,
 			Repository: selectedRepo,
 		})
 	}
 
+	// add in the existing dependencies that were not overwritten
+	for _, dep := range existingDependencies {
+		if !dependencyExists(deps, dep) {
+			// have to repair the dependency name because of https://github.com/helm/helm/issues/9214
+			if strings.HasSuffix(dep.Name, "-web") || strings.HasSuffix(dep.Name, "-wkr") || strings.HasSuffix(dep.Name, "-job") {
+				dep.Name = getChartTypeFromHelmName(dep.Name)
+			}
+			deps = append(deps, dep)
+		}
+	}
+
 	chart, err := createChartFromDependencies(deps)
 	if err != nil {
 		return nil, err
@@ -164,6 +217,15 @@ func buildStackChart(parsed *PorterStackYAML, config *config.Config, projectID u
 	return chart, nil
 }
 
+func dependencyExists(deps []*chart.Dependency, dep *chart.Dependency) bool {
+	for _, d := range deps {
+		if d.Alias == dep.Alias {
+			return true
+		}
+	}
+	return false
+}
+
 func createChartFromDependencies(deps []*chart.Dependency) (*chart.Chart, error) {
 	metadata := &chart.Metadata{
 		Name:        "umbrella",
@@ -354,3 +416,26 @@ func getNestedMap(obj map[string]interface{}, fields ...string) (map[string]inte
 
 	return res, nil
 }
+
+func getHelmName(alias string, t string) string {
+	var suffix string
+	if t == "web" {
+		suffix = "-web"
+	} else if t == "worker" {
+		suffix = "-wkr"
+	} else if t == "job" {
+		suffix = "-job"
+	}
+	return fmt.Sprintf("%s%s", alias, suffix)
+}
+
+func getChartTypeFromHelmName(name string) string {
+	if strings.HasSuffix(name, "-web") {
+		return "web"
+	} else if strings.HasSuffix(name, "-wkr") {
+		return "worker"
+	} else if strings.HasSuffix(name, "-job") {
+		return "job"
+	}
+	return ""
+}

+ 20 - 7
api/server/handlers/stacks/update.go

@@ -50,6 +50,12 @@ func (c *UpdateStackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	helmRelease, _ := helmAgent.GetRelease(stackName, 0, false)
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error getting latest release: %w", err)))
+		return
+	}
+
 	k8sAgent, err := c.GetAgent(r, cluster, namespace)
 	if err != nil {
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error getting k8s agent: %w", err)))
@@ -63,13 +69,20 @@ func (c *UpdateStackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	imageInfo := request.ImageInfo
-	chart, values, err := parse(porterYaml, imageInfo, c.Config(), cluster.ProjectID, SubdomainCreateOpts{
-		k8sAgent:       k8sAgent,
-		dnsRepo:        c.Repo().DNSRecord(),
-		powerDnsClient: c.Config().PowerDNSClient,
-		appRootDomain:  c.Config().ServerConf.AppRootDomain,
-		stackName:      stackName,
-	})
+	chart, values, err := parse(
+		porterYaml,
+		imageInfo,
+		c.Config(),
+		cluster.ProjectID,
+		helmRelease.Config,
+		helmRelease.Chart.Metadata.Dependencies,
+		SubdomainCreateOpts{
+			k8sAgent:       k8sAgent,
+			dnsRepo:        c.Repo().DNSRecord(),
+			powerDnsClient: c.Config().PowerDNSClient,
+			appRootDomain:  c.Config().ServerConf.AppRootDomain,
+			stackName:      stackName,
+		})
 	if err != nil {
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error parsing porter yaml into chart and values: %w", err)))
 		return

+ 5 - 5
cli/cmd/stack/apply.go

@@ -22,11 +22,6 @@ type StackConf struct {
 }
 
 func CreateV1BuildResources(client *api.Client, raw []byte, stackName string, projectID uint, clusterID uint) (*switchboardTypes.ResourceGroup, error) {
-	stackConf, err := createStackConf(client, raw, stackName, projectID, clusterID)
-	if err != nil {
-		return nil, err
-	}
-
 	v1File := &switchboardTypes.ResourceGroup{
 		Version: "v1",
 		Resources: []*switchboardTypes.Resource{
@@ -37,6 +32,11 @@ func CreateV1BuildResources(client *api.Client, raw []byte, stackName string, pr
 		},
 	}
 
+	stackConf, err := createStackConf(client, raw, stackName, projectID, clusterID)
+	if err != nil {
+		return nil, err
+	}
+
 	var bi, pi *switchboardTypes.Resource
 
 	if stackConf.parsed.Build != nil {

+ 3 - 3
dashboard/src/main/home/app-dashboard/expanded-app/BuildSettingsTabStack.tsx

@@ -83,7 +83,7 @@ const BuildSettingsTabStack: React.FC<Props> = ({
     "loading" | "successful" | string
   >("");
   const [imageUrl, setImageUrl] = useState(appData.chart.image_uri);
-  
+
   const triggerWorkflow = async () => {
     try {
       await api.reRunGHWorkflow(
@@ -136,7 +136,7 @@ const BuildSettingsTabStack: React.FC<Props> = ({
         }
         setCurrentError(
           'The workflow is still running. You can "Save" the current build settings for the next workflow run and view the current status of the workflow here: ' +
-            tmpError.response.data
+          tmpError.response.data
         );
         return;
       }
@@ -373,7 +373,7 @@ const StyledAdvancedBuildSettings = styled.div`
     cursor: pointer;
     border-radius: 20px;
     transform: ${(props: { showSettings: boolean; isCurrent: boolean }) =>
-      props.showSettings ? "" : "rotate(-90deg)"};
+    props.showSettings ? "" : "rotate(-90deg)"};
   }
 `;
 const StyledSourceBox = styled.div`

+ 23 - 24
dashboard/src/main/home/app-dashboard/expanded-app/ExpandedApp.tsx

@@ -164,7 +164,6 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
           }
         }
       }
-
       const newAppData = {
         app: resPorterApp?.data,
         chart: resChartData?.data,
@@ -325,7 +324,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
       (defaultValues && Object.keys(defaultValues).length > 0) ||
       (helmValues && Object.keys(helmValues).length > 0)
     ) {
-      const svcs = Service.deserialize(helmValues, defaultValues);
+      const svcs = Service.deserialize(helmValues, defaultValues, porterJson);
       setServices(svcs);
       if (helmValues && Object.keys(helmValues).length > 0) {
         const envs = Service.retrieveEnvFromHelmValues(helmValues);
@@ -497,13 +496,13 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                 </Fieldset>
               </>
             )}
-            <Services 
+            <Services
               setServices={(x) => {
                 if (buttonStatus !== "") {
                   setButtonStatus("");
                 }
                 setServices(x);
-              }} 
+              }}
               services={services} />
             <Spacer y={1} />
             <Button
@@ -689,7 +688,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                     shouldUpdate={
                       appData.chart.latest_version &&
                       appData.chart.latest_version !==
-                        appData.chart.chart.metadata.version
+                      appData.chart.chart.metadata.version
                     }
                     latestVersion={appData.chart.latest_version}
                     upgradeVersion={appUpgradeVersion}
@@ -703,33 +702,33 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                   appData.app.git_repo_id
                     ? hasBuiltImage
                       ? [
-                          { label: "Logs", value: "logs" },
-                          { label: "Overview", value: "overview" },
-                          {
-                            label: "Environment variables",
-                            value: "environment-variables",
-                          },
-                          { label: "Build settings", value: "build-settings" },
-                          { label: "Settings", value: "settings" },
-                        ]
-                      : [
-                          { label: "Overview", value: "overview" },
-                          {
-                            label: "Environment variables",
-                            value: "environment-variables",
-                          },
-                          { label: "Build settings", value: "build-settings" },
-                          { label: "Settings", value: "settings" },
-                        ]
-                    : [
                         { label: "Logs", value: "logs" },
                         { label: "Overview", value: "overview" },
                         {
                           label: "Environment variables",
                           value: "environment-variables",
                         },
+                        { label: "Build settings", value: "build-settings" },
                         { label: "Settings", value: "settings" },
                       ]
+                      : [
+                        { label: "Overview", value: "overview" },
+                        {
+                          label: "Environment variables",
+                          value: "environment-variables",
+                        },
+                        { label: "Build settings", value: "build-settings" },
+                        { label: "Settings", value: "settings" },
+                      ]
+                    : [
+                      { label: "Logs", value: "logs" },
+                      { label: "Overview", value: "overview" },
+                      {
+                        label: "Environment variables",
+                        value: "environment-variables",
+                      },
+                      { label: "Settings", value: "settings" },
+                    ]
                 }
                 currentTab={tab}
                 setCurrentTab={(tab: string) => {

+ 1 - 2
dashboard/src/main/home/app-dashboard/new-app-flow/schema.tsx

@@ -107,8 +107,7 @@ const createApps = (
                 porterJson.apps[service.name].config
             );
         }
-        // required because of https://github.com/helm/helm/issues/9214
-        apps[Service.toHelmName(service)] = {
+        apps[service.name] = {
             type: service.type,
             run: service.startCommand.value,
             config,