Skip to content

Conversation

Greyeye
Copy link
Collaborator

@Greyeye Greyeye commented Jan 31, 2025

  1. instead of performing addFile, addDir inside kustomize package, it will return lists of files and dir thats used in kustomization.yaml
  2. add and updated unit tests
  3. several MR tests are now using outdated ingress api version, this is now updated)
  4. tool-version is now updated

1. instead of performing addFile, addDir inside kustomize package, it will return lists of files and dir thats used in kustomization.yaml
2. add and updated unit tests
3. several MR tests are now using outdated ingress api version, this is now updated)
4. tool-version is now updated
@zapier-sre-bot
Copy link
Collaborator

Mergecat's Review

Click to read mergecats review!

😼 Mergecat review of .tool-versions

@@ -5,6 +5,6 @@ helm 3.16.3
 helm-cr 1.6.1
 helm-ct 3.11.0
 kubeconform 0.6.7
-kustomize 5.5.0
+kustomize 5.6.0
 mockery 2.46.3
 tilt 0.33.2

Feedback & Suggestions:

  • 🛡️ Compatibility Check: Ensure that the new version of kustomize (5.6.0) is compatible with the rest of your toolchain and any scripts or configurations that depend on it. Version upgrades can sometimes introduce breaking changes.

  • 📄 Documentation Update: If this version change affects any documentation or setup instructions, make sure to update those as well to reflect the new version.

  • 🔄 Testing: After updating the version, run your tests to ensure that everything works as expected with the new version of kustomize.


😼 Mergecat review of localdev/terraform/modules/vcs_files/mr3_files/apps/httpbin/base/external-ingress.yaml

@@ -1,4 +1,4 @@
-apiVersion: networking.k8s.io/v1beta1
+apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   name: httpbin-external
@@ -11,5 +11,8 @@ spec:
         paths:
           - path: /httpbin/(.*)
             backend:
-              serviceName: httpbin
-              servicePort: 8080
\ No newline at end of file
+              service:
+                name: httpbin
+                port:
+                  name: http
+            pathType: ImplementationSpecific

Feedback & Suggestions:

  1. API Version Update: 👍 Great job updating the apiVersion from v1beta1 to v1. This is necessary as v1beta1 is deprecated in newer Kubernetes versions.

  2. Backend Service Specification: The change from serviceName and servicePort to the nested service structure is correct for v1. Ensure that the service port name http is correctly defined in the service manifest. If the port is defined by number, consider using port.number instead of port.name.

  3. Path Type: The addition of pathType: ImplementationSpecific is a good move, but be aware that this can lead to non-portable configurations. Consider using pathType: Prefix or pathType: Exact if you want more predictable behavior.

  4. Newline at End of File: 🚨 It's a good practice to ensure there is a newline at the end of the file. This can prevent potential issues with certain tools and version control systems.


😼 Mergecat review of localdev/terraform/modules/vcs_files/mr6_files/apps/httpdump/base/external-ingress.yaml

@@ -1,4 +1,4 @@
-apiVersion: networking.k8s.io/v1beta1
+apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   name: httpdump-external
@@ -9,8 +9,10 @@ spec:
   rules:
     - http:
         paths:
-          - path: /httpdump/(.*)
-            pathType: ImplementationSpecific
+          - path: /httpbin/(.*)
             backend:
-              serviceName: httpdump
-              servicePort: 8080
\ No newline at end of file
+              service:
+                name: httpbin
+                port:
+                  name: http
+            pathType: ImplementationSpecific

Feedback & Suggestions:

  1. API Version Update: 🎉 Great job updating the apiVersion from v1beta1 to v1. This is important for compatibility with newer Kubernetes versions.

  2. Service Backend Specification: The change from serviceName and servicePort to the new service block is a good move towards using the newer API structure. However, ensure that the service named httpbin and the port named http are correctly defined in your Kubernetes service configuration to avoid runtime errors.

  3. Path Change: The path has been changed from /httpdump/(.*) to /httpbin/(.*). Make sure this change is intentional and that all related configurations and documentation are updated accordingly to prevent any unexpected behavior.

  4. Newline at End of File: 🚨 Consider adding a newline at the end of the file. This is a common convention that can prevent issues with some tools and version control systems.


😼 Mergecat review of localdev/terraform/modules/vcs_files/mr3_files/apps/httpbin/base/internal-ingress.yaml

@@ -11,5 +11,8 @@ spec:
         paths:
           - path: /helloworld/(.*)
             backend:
-              serviceName: helloworld-svc
-              servicePort: 8080
\ No newline at end of file
+              service:
+                name: helloworld-svc
+                port:
+                  name: http
+            pathType: ImplementationSpecific

Feedback & Suggestions:

  1. PathType Specification: The addition of pathType: ImplementationSpecific is a good move as it makes the path matching behavior explicit. However, consider using Prefix or Exact if you want more predictable behavior, as ImplementationSpecific can vary between ingress controllers. 🔍

  2. Service Port Naming: Changing from servicePort: 8080 to port: name: http is a good practice if the service port is named in the service definition. Ensure that the service definition indeed uses http as the port name to avoid runtime errors. 🔄

  3. Newline at End of File: It's a good practice to ensure there is a newline at the end of the file. This can prevent potential issues with some tools that process files. 📝


😼 Mergecat review of localdev/terraform/modules/vcs_files/mr6_files/apps/httpdump/base/internal-ingress.yaml

@@ -9,8 +9,10 @@ spec:
   rules:
     - http:
         paths:
-          - path: /helloworld/(.*)
-            pathType: ImplementationSpecific
+          - path: /httpbin/(.*)
             backend:
-              serviceName: helloworld-svc
-              servicePort: 8080
\ No newline at end of file
+              service:
+                name: httpbin
+                port:
+                  name: http
+            pathType: ImplementationSpecific

Feedback & Suggestions:

  • 🛠️ Path Update: The path has been changed from /helloworld/(.*) to /httpbin/(.*). Ensure that this change aligns with your application's routing logic and that the new path is correctly handled by your backend service.
  • 🔄 Backend Service Update: The backend service configuration has been updated to use the new Kubernetes service API format. This is a good practice for future compatibility. However, ensure that the service name httpbin and port http are correctly defined in your Kubernetes service configuration.
  • 📄 Newline at End of File: Consider adding a newline at the end of the file. This is a common convention and can prevent potential issues with some tools that process YAML files.

😼 Mergecat review of pkg/argo_client/manifests.go

@@ -379,15 +379,17 @@ func packageApp(
 	relKustPath := filepath.Join(source.Path, "kustomization.yaml")
 	absKustPath := filepath.Join(destDir, relKustPath)
 	if fsIface.Exists(absKustPath) {
-		p := processor{
-			repoRoot: repo.Directory,
-			tempDir:  destDir,
-			repoFS:   fsIface,
-		}
 
-		if err := kustomize.ProcessKustomizationFile(sourceFS, relKustPath, &p); err != nil {
+		files, _, err := kustomize.ProcessKustomizationFile(sourceFS, relKustPath)
+		if err != nil {
 			return "", errors.Wrap(err, "failed to process kustomization dependencies")
 		}
+		for _, file := range files {
+			err := addFile(repo.Directory, destDir, file)
+			if err != nil {
+				return "", errors.Wrap(err, "failed to add file")
+			}
+		}
 	}
 
 	if source.Helm != nil {

Feedback & Suggestions:

  1. Error Handling Consistency: The error handling for addFile is consistent with the rest of the function, which is good. However, consider logging the specific file that failed to be added for better traceability. This can be done by including the file variable in the error message.

  2. Function Documentation: If addFile is a new function introduced in this diff, ensure it is well-documented, especially if it involves file operations that might have side effects or specific requirements.

  3. Performance Consideration: The loop iterating over files could potentially be optimized if the list is large. Consider whether parallel processing is feasible and beneficial here, but be cautious of concurrency issues with file operations.

  4. Security Consideration: Ensure that addFile properly handles file paths to avoid directory traversal vulnerabilities. This is especially important if any part of the file path is influenced by user input or external sources.

  5. Testing: Ensure that there are adequate tests covering the new logic, especially edge cases where addFile might fail. This will help maintain robustness and reliability.


😼 Mergecat review of pkg/argo_client/kustomize.go

@@ -6,32 +6,21 @@ import (
 	"path/filepath"
 
 	"github.com/pkg/errors"
-	"github.com/zapier/kubechecks/pkg/kustomize"
-	"sigs.k8s.io/kustomize/kyaml/filesys"
 )
 
-type processor struct {
-	repoRoot string
-	tempDir  string
-	repoFS   filesys.FileSystem
-}
-
-func (p processor) AddDir(s string) error {
-	return nil
-}
-
-func (p processor) AddFile(relPath string) error {
-	absDepPath := filepath.Clean(filepath.Join(p.repoRoot, relPath))
+// addFile copies a file from the repository to the temp directory to prepare to be sent to the ArgoCD API.
+func addFile(repoRoot string, tempDir string, relPath string) error {
+	absDepPath := filepath.Clean(filepath.Join(repoRoot, relPath))
 
 	// Get relative path from repo root
-	relPath, err := filepath.Rel(p.repoRoot, absDepPath)
+	relPath, err := filepath.Rel(repoRoot, absDepPath)
 	if err != nil {
 		return errors.Wrapf(err, "failed to get relative path for %s", absDepPath)
 	}
 
 	// check if the file exists in the temp directory
 	// skip copying if it exists
-	tempPath := filepath.Join(p.tempDir, relPath)
+	tempPath := filepath.Join(tempDir, relPath)
 	if _, err := os.Stat(tempPath); err == nil {
 		return nil
 	}
@@ -63,5 +52,3 @@ func (p processor) AddFile(relPath string) error {
 	_, err = io.Copy(w, r)
 	return errors.Wrap(err, "failed to copy file")
 }
-
-var _ kustomize.Processor = new(processor)

Feedback & Suggestions:

  1. Function Signature Change: The AddFile method was changed to a standalone function addFile. This change removes the encapsulation provided by the processor struct. If the processor struct is no longer needed, this is fine, but if you plan to maintain state or extend functionality, consider keeping the struct-based approach. 🏗️

  2. Interface Implementation: The removal of the kustomize.Processor interface implementation check (var _ kustomize.Processor = new(processor)) suggests that the processor no longer implements this interface. Ensure that this change aligns with your design goals and that the interface is no longer needed. If the interface is still required, consider refactoring to maintain the implementation. 🔄

  3. Error Handling: The error handling in the defer function for closing the file writer (w.Close()) is correct, but ensure that this pattern is consistently applied throughout your codebase for reliability. 🛠️

  4. Documentation: The comment added to the addFile function is helpful. Ensure that all public functions and methods are similarly documented to improve code readability and maintainability. 📚

  5. Security Considerations: Ensure that the paths being handled are properly sanitized to prevent path traversal vulnerabilities. The use of filepath.Clean is a good start, but additional validation may be necessary depending on the context in which this function is used. 🔒


😼 Mergecat review of pkg/appdir/vcstoargomap.go

@@ -63,8 +63,6 @@ func (v2a VcsToArgoMap) GetAppSetsInRepo(repoCloneUrl string) *AppSetDirectory {
 
 func (v2a VcsToArgoMap) WalkKustomizeApps(cloneURL string, rootFS fs.FS) *AppDirectory {
 	var (
-		err error
-
 		result = NewAppDirectory()
 		appdir = v2a.GetAppsInRepo(cloneURL)
 		apps   = appdir.GetApps(nil)
@@ -73,14 +71,16 @@ func (v2a VcsToArgoMap) WalkKustomizeApps(cloneURL string, rootFS fs.FS) *AppDir
 	for _, app := range apps {
 		appPath := app.Spec.GetSource().Path
 
-		p := processor{
-			appName: app.Name,
-			result:  result,
-		}
-
-		if err = kustomize.ProcessKustomizationFile(rootFS, appPath, &p); err != nil {
+		kustomizeFiles, kustomizeDir, err := kustomize.ProcessKustomizationFile(rootFS, appPath)
+		if err != nil {
 			log.Error().Err(err).Msgf("failed to parse kustomize.yaml in %s", appPath)
 		}
+		for _, file := range kustomizeFiles {
+			result.addFile(app.Name, file)
+		}
+		for _, dir := range kustomizeDir {
+			result.addDir(app.Name, dir)
+		}
 	}
 
 	return result

Feedback & Suggestions:

  1. Error Handling: The error variable err was removed from the declaration but is still used in the if err != nil check. Ensure that err is declared within the loop or before the for loop to avoid compilation errors. 🐛

  2. Function Return Values: The kustomize.ProcessKustomizationFile function now returns multiple values. Ensure that the function signature and its usage are updated accordingly in the kustomize package to prevent runtime errors. 🔄

  3. Code Clarity: The removal of the processor struct simplifies the code, but make sure that the addFile and addDir methods on result are correctly implemented to handle the new logic. This ensures that the functionality remains consistent with the original intent. 📚

  4. Performance Consideration: If kustomize.ProcessKustomizationFile is a computationally expensive operation, consider whether it can be optimized or if its results can be cached to improve performance. 🚀


😼 Mergecat review of pkg/kustomize/process.go

@@ -12,36 +12,32 @@ import (
 	"sigs.k8s.io/kustomize/kyaml/yaml"
 )
 
-type Processor interface {
-	AddDir(string) error
-	AddFile(string) error
-}
-
-func ProcessKustomizationFile(sourceFS fs.FS, relKustomizationPath string, processor Processor) error {
+// ProcessKustomizationFile processes a kustomization file and returns all the files and directories it references.
+func ProcessKustomizationFile(sourceFS fs.FS, relKustomizationPath string) (files []string, dirs []string, err error) {
 	dirName := filepath.Dir(relKustomizationPath)
-	return processDir(sourceFS, dirName, processor)
+	return processDir(sourceFS, dirName)
 }
 
-func processDir(sourceFS fs.FS, relBase string, processor Processor) error {
+func processDir(sourceFS fs.FS, relBase string) (files []string, dirs []string, err error) {
 	absKustPath := filepath.Join(relBase, "kustomization.yaml")
 
 	// Parse using official Kustomization type
 	file, err := sourceFS.Open(absKustPath)
 	if err != nil {
 		if os.IsNotExist(err) {
-			return nil // No kustomization.yaml in this directory
+			return nil, nil, nil // No kustomization.yaml in this directory
 		}
-		return errors.Wrap(err, "failed to open file")
+		return nil, nil, errors.Wrapf(err, "failed to open file %q", absKustPath)
 	}
 
 	content, err := io.ReadAll(file)
 	if err != nil {
-		return errors.Wrap(err, "failed to read file")
+		return nil, nil, errors.Wrapf(err, "failed to read file kustomization.yam")
 	}
 
 	var kust types.Kustomization
 	if err := yaml.Unmarshal(content, &kust); err != nil {
-		return errors.Wrap(err, "failed to parse kustomization.yaml")
+		return nil, nil, errors.Wrapf(err, "failed to parse %q", absKustPath)
 	}
 
 	// collect all the possible files and directories that kustomize can contain
@@ -52,7 +48,7 @@ func processDir(sourceFS fs.FS, relBase string, processor Processor) error {
 	var directories []string
 	directories = append(directories, kust.Components...)
 
-	files := []string{"kustomization.yaml"}
+	files = []string{"kustomization.yaml"}
 	files = append(files, kust.Configurations...)
 	files = append(files, kust.Crds...)
 	files = append(files, kust.Transformers...)
@@ -85,36 +81,33 @@ func processDir(sourceFS fs.FS, relBase string, processor Processor) error {
 	for _, fileOrDirectory := range filesOrDirectories {
 		file, err := sourceFS.Open(fileOrDirectory)
 		if err != nil {
-			return errors.Wrapf(err, "failed to stat %s", fileOrDirectory)
+			return nil, nil, errors.Wrapf(err, "failed to stat %s", fileOrDirectory)
 		}
 
 		if stat, err := file.Stat(); err != nil {
-			return errors.Wrapf(err, "failed to stat %s", fileOrDirectory)
+			return nil, nil, errors.Wrapf(err, "failed to stat %s", fileOrDirectory)
 		} else if stat.IsDir() {
 			directories = append(directories, fileOrDirectory)
 		} else {
 			files = append(files, fileOrDirectory)
 		}
 	}
 
-	// add files
-	for _, relResource := range files {
-		if err := processor.AddFile(relResource); err != nil {
-			return errors.Wrapf(err, "failed to add resource %q", relResource)
-		}
-	}
+	// We now know this directory has a kustomization.yaml, so add it to "dirs".
+	allDirs := append([]string(nil), relBase)
+	allFiles := append([]string(nil), files...)
 
 	// process directories and add them
 	for _, relResource := range directories {
-		if err = processor.AddDir(relResource); err != nil {
-			return errors.Wrapf(err, "failed to add directory %q", relResource)
-		}
-		if err = processDir(sourceFS, relResource, processor); err != nil {
-			return errors.Wrapf(err, "failed to process %q", relResource)
+		subFiles, subDirs, err := processDir(sourceFS, relResource)
+		if err != nil {
+			return nil, nil, errors.Wrapf(err, "failed to process %q", relResource)
 		}
+		allFiles = append(allFiles, subFiles...)
+		allDirs = append(allDirs, subDirs...)
 	}
 
-	return nil
+	return allFiles, allDirs, nil
 }
 
 func cleanPaths(relativeBase string, paths []string) []string {

Feedback & Suggestions:

  1. Error Message Consistency: There's a typo in the error message for reading the file: "failed to read file kustomization.yam". It should be "failed to read file kustomization.yaml". 🐛

  2. Function Signature Change: The change from using a Processor interface to returning slices of files and directories directly is a significant design change. Ensure that this change aligns with the overall architecture and usage of the function. If other parts of the codebase rely on the Processor interface, they will need to be updated accordingly. 🔄

  3. Resource Management: Ensure that the file opened with sourceFS.Open(absKustPath) is closed after its usage to prevent resource leaks. Consider using defer file.Close() right after opening the file. 🔒

  4. Variable Initialization: The initialization of allDirs and allFiles could be simplified by directly appending relBase and files without creating new slices. This would slightly improve performance by reducing unnecessary allocations. 🚀

  5. Documentation: The comment for ProcessKustomizationFile is a good addition. Ensure that similar comments are added to other functions to maintain consistency and improve code readability. 📚



Dependency Review

Click to read mergecats review!

No suggestions found

Copy link

github-actions bot commented Jan 31, 2025

Temporary image deleted.

Copy link
Collaborator

@djeebus djeebus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

@djeebus djeebus merged commit 1b2c10d into central-kustomize Jan 31, 2025
3 checks passed
@djeebus djeebus deleted the separate-kustomize-discovery-file-handling branch January 31, 2025 14:33
djeebus added a commit that referenced this pull request Feb 3, 2025
* centralize the kustomize walking logic, upgrade linting

* staticcheck is part of golangci-lint, no reason to run it seperately

* simplify kustomize walk (#361)

1. instead of performing addFile, addDir inside kustomize package, it will return lists of files and dir thats used in kustomization.yaml
2. add and updated unit tests
3. several MR tests are now using outdated ingress api version, this is now updated)
4. tool-version is now updated

---------

Co-authored-by: James Hong <james.hong@zapier.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants