Skip to content

Instantly share code, notes, and snippets.

@leecalcote
Last active January 29, 2025 00:50
Show Gist options
  • Save leecalcote/51623fcf157d3113f3893af8c8f4ba7f to your computer and use it in GitHub Desktop.
Save leecalcote/51623fcf157d3113f3893af8c8f4ba7f to your computer and use it in GitHub Desktop.
YAML file type detectors
// Ideally, the detectors here utilize the very same mechanism that each infrastructure has code tool uses to determine whether or not they have a valid manifest.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"helm.sh/helm/v3/pkg/chart/loader"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/api/krusty"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
func main() {
// Replace with the path to your YAML file
filePath := "weaveworks-gitops-enterprise-design.yaml"
fileContent, err := ioutil.ReadFile(filePath)
if err != nil {
fmt.Println("Error reading file:", err)
return
}
// Convert fileContent to string for debugging
// content := string(fileContent)
// fmt.Printf("File content: %s\n", content)
// Correct switch statement - no := here
switch identifyYAML(filePath, fileContent) {
case "DockerCompose":
fmt.Println("Docker Compose file detected.")
case "Kubernetes":
fmt.Println("Kubernetes manifest detected.")
case "Helm":
fmt.Println("Helm chart detected.")
case "Kustomize":
fmt.Println("Kustomize file detected.")
default:
fmt.Println("Unknown YAML format.")
}
}
func identifyYAML(filePath string, fileContent []byte) string {
// Check if it's a Kubernetes manifest
if isKubernetesManifest(fileContent) {
return "Kubernetes"
}
// Check if it's a Helm chart
if isHelmChart(filePath) {
return "Helm"
}
// Check if it's a Kustomize file
if isKustomizeFile(filePath) {
return "Kustomize"
}
// If none of the above, assume it's a Docker Compose file
// (especially if it has a.yml or.yaml extension and is in the project root)
return "DockerCompose"
}
func isKubernetesManifest(fileContent []byte) bool {
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(fileContent), 4096)
var typeMeta metav1.TypeMeta
if err := decoder.Decode(&typeMeta); err != nil {
return false
}
// Check for required Kubernetes fields
return typeMeta.APIVersion != "" && typeMeta.Kind != ""
}
func isHelmChart(filePath string) bool {
// Verification Criteria:
// 1. Check if there is a Chart.yaml file in the directory
// 2. Attempt to load the chart using loader.Load
chartPath := filepath.Dir(filePath)
if _, err := os.Stat(filepath.Join(chartPath, "Chart.yaml")); err == nil {
// Use loader.Load instead of chart.Load
_, err := loader.Load(chartPath)
if err == nil {
return true
}
}
return false
}
func isKustomizeFile(filePath string) bool {
// Verification Criteria:
// 1. Check if the filename is kustomization.yaml or kustomization.yml
// 2. Creates a krusty.Kustomizer instance with default options using krusty.MakeDefaultOptions().
// 2.a. Calls the k.Run() method with the file system and file path to attempt to load and process the file as a Kustomize file.
// 2.b. If k.Run() returns an error, it indicates that the file is not a valid Kustomize file. Otherwise, it's considered a Kustomize file.
if filepath.Base(filePath) == "kustomization.yaml" || filepath.Base(filePath) == "kustomization.yml" {
// Attempt to decode the kustomization file
fSys := filesys.MakeFsOnDisk()
k := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
_, err := k.Run(fSys, filepath.Dir(filePath))
if err == nil {
return true
}
}
return false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment