...

Source file src/edge-infra.dev/hack/build/rules/kustomize/gazelle/language/generators.go

Documentation: edge-infra.dev/hack/build/rules/kustomize/gazelle/language

     1  package kustomize
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/bazelbuild/bazel-gazelle/language"
    10  	"github.com/bazelbuild/bazel-gazelle/resolve"
    11  	"sigs.k8s.io/kustomize/api/filters/fsslice"
    12  	"sigs.k8s.io/kustomize/api/types"
    13  	"sigs.k8s.io/kustomize/kyaml/kio"
    14  	"sigs.k8s.io/kustomize/kyaml/yaml"
    15  
    16  	"edge-infra.dev/pkg/k8s/eyaml/fieldspecs"
    17  )
    18  
    19  type filter struct {
    20  	FsSlice types.FsSlice
    21  }
    22  
    23  var filteredImages = []string{}
    24  
    25  // GenerateBases generates (deprecated) base references to file srcs as well as
    26  // Kustomization dependencies
    27  func GenerateBases(args language.GenerateArgs, bases []string) ([]string, []resolve.ImportSpec, error) {
    28  	var kustomizeImports []resolve.ImportSpec
    29  	var srcs []string
    30  
    31  	for _, b := range bases {
    32  		absPath := filepath.Join(args.Dir, b)
    33  		fi, err := os.Stat(absPath)
    34  		if err != nil {
    35  			fmt.Println(err)
    36  			return nil, nil, err
    37  		}
    38  
    39  		if fi.IsDir() {
    40  			kustomizeImports = append(kustomizeImports, toImportSpec(args.Rel, b))
    41  		} else {
    42  			srcs = append(srcs, b)
    43  		}
    44  	}
    45  	return srcs, kustomizeImports, nil
    46  }
    47  
    48  // GenerateComponents returns a list of resolve.ImportSpecs referring to any Component
    49  // dependencies
    50  func GenerateComponents(args language.GenerateArgs, components []string) []resolve.ImportSpec {
    51  	var kustomizeImports []resolve.ImportSpec
    52  	for _, d := range components {
    53  		kustomizeImports = append(kustomizeImports, toImportSpec(args.Rel, d))
    54  	}
    55  
    56  	return kustomizeImports
    57  }
    58  
    59  // GenerateConfigmapGenerators
    60  func GenerateConfigmapGenerators(args language.GenerateArgs, cmGens []types.ConfigMapArgs) []string {
    61  	var srcs []string
    62  	for _, cmga := range cmGens {
    63  		// cmga.EnvSource is a single source
    64  		if cmga.EnvSource != "" {
    65  			if filepath.IsLocal(cmga.EnvSource) {
    66  				srcs = append(srcs, cmga.EnvSource)
    67  			} else {
    68  				srcs = append(srcs, toRemoteSrc(args.Rel, cmga.EnvSource))
    69  			}
    70  			continue
    71  		}
    72  
    73  		// cmga.EnvSources is a list of sources
    74  		if len(cmga.EnvSources) > 0 {
    75  			for _, f := range cmga.EnvSources {
    76  				if filepath.IsLocal(f) {
    77  					srcs = append(srcs, f)
    78  				} else {
    79  					srcs = append(srcs, toRemoteSrc(args.Rel, f))
    80  				}
    81  			}
    82  		}
    83  
    84  		// cmga.FileSources is a list of file sources
    85  		if len(cmga.FileSources) > 0 {
    86  			for _, f := range cmga.FileSources {
    87  				if filepath.IsLocal(f) {
    88  					srcs = append(srcs, f)
    89  				} else {
    90  					srcs = append(srcs, toRemoteSrc(args.Rel, f))
    91  				}
    92  			}
    93  		}
    94  	}
    95  
    96  	return srcs
    97  }
    98  
    99  // GenerateConfigurations takes a Kustomization's configurations attributes and returns
   100  // a list of file srcs
   101  func GenerateConfigurations(args language.GenerateArgs, configurations []string) []string {
   102  	var srcs []string
   103  	for _, c := range configurations {
   104  		if filepath.IsLocal(c) {
   105  			srcs = append(srcs, c)
   106  			continue
   107  		}
   108  
   109  		srcs = append(srcs, toRemoteSrc(args.Rel, c))
   110  	}
   111  
   112  	return srcs
   113  }
   114  
   115  // GeneratePatches returns a list of file srcs for Patch items
   116  func GeneratePatches(args language.GenerateArgs, patches []types.Patch) []string {
   117  	var srcs []string
   118  
   119  	for _, p := range patches {
   120  		if p.Path != "" {
   121  			if filepath.IsLocal(p.Path) {
   122  				srcs = append(srcs, p.Path)
   123  				continue
   124  			}
   125  
   126  			srcs = append(srcs, toRemoteSrc(args.Rel, p.Path))
   127  		}
   128  	}
   129  
   130  	return srcs
   131  }
   132  
   133  // GeneratePatchesJSON6902 returns a list of file srcs for PatchesJSON6902
   134  func GeneratePatchesJSON6902(args language.GenerateArgs, patchesJSON6902 []types.Patch) []string {
   135  	var srcs []string
   136  
   137  	for _, p := range patchesJSON6902 {
   138  		if p.Path != "" {
   139  			if filepath.IsLocal(p.Path) {
   140  				srcs = append(srcs, p.Path)
   141  				continue
   142  			}
   143  
   144  			srcs = append(srcs, toRemoteSrc(args.Rel, p.Path))
   145  		}
   146  	}
   147  
   148  	return srcs
   149  }
   150  
   151  // GeneratePatchesStrategicMerge returns a list of file srcs for PatchStrategicMerge items
   152  func GeneratePatchesStrategicMerge(args language.GenerateArgs, patchesStrategicMerge []types.Patch) ([]string, []resolve.ImportSpec, error) {
   153  	var kustomizeImports []resolve.ImportSpec
   154  	var srcs []string
   155  
   156  	for _, psm := range patchesStrategicMerge {
   157  		psmStr := psm.Patch
   158  		absPath := filepath.Join(args.Dir, psmStr)
   159  		fi, err := os.Stat(absPath)
   160  		if err != nil {
   161  			fmt.Println(err)
   162  			return nil, nil, err
   163  		}
   164  
   165  		if fi.IsDir() {
   166  			kustomizeImports = append(kustomizeImports, toImportSpec(args.Rel, psmStr))
   167  		} else {
   168  			srcs = append(srcs, psmStr)
   169  		}
   170  	}
   171  
   172  	return srcs, kustomizeImports, nil
   173  }
   174  
   175  // GenerateResources takes a Kustomization's resource attributes and returns a list of
   176  // file srcs and Kustomization dependencies as resolve.ImportSpecs
   177  func GenerateResources(args language.GenerateArgs, resources []string) ([]string, []string, []resolve.ImportSpec, error) {
   178  	var kustomizeImports []resolve.ImportSpec
   179  	var srcs []string
   180  
   181  	// imgs := make(map[string]string)
   182  	imgs := []string{}
   183  
   184  	for _, r := range resources {
   185  		rPath := filepath.Join(args.Dir, r)
   186  		fi, err := os.Stat(rPath)
   187  		if err != nil {
   188  			fmt.Println(err)
   189  			return nil, nil, nil, err
   190  		}
   191  
   192  		// Resources that are dirs must be Kustomizations
   193  		if fi.IsDir() {
   194  			kustomizeImports = append(kustomizeImports, toImportSpec(args.Rel, r))
   195  			continue
   196  		}
   197  
   198  		// If resource is a file reference, check if it can be directly referenced
   199  		if filepath.IsLocal(r) {
   200  			imgs, err = GenerateImages(rPath, imgs)
   201  			if err != nil {
   202  				fmt.Println(err)
   203  				return nil, nil, nil, err
   204  			}
   205  			srcs = append(srcs, r)
   206  			continue
   207  		}
   208  
   209  		// If it lives in another package, create a remote src reference
   210  		srcs = append(srcs, toRemoteSrc(args.Rel, r))
   211  	}
   212  
   213  	return srcs, imgs, kustomizeImports, nil
   214  }
   215  
   216  func GenerateImages(resource string, imgs []string) ([]string, error) {
   217  	f, err := os.Open(resource)
   218  	if err != nil {
   219  		return nil, fmt.Errorf("failed to open file at %s: %w", resource, err)
   220  	}
   221  	rdr := kio.ByteReader{Reader: f}
   222  	rns, err := rdr.Read()
   223  	if err != nil {
   224  		return nil, fmt.Errorf("failed to read with ByteReader: %w", err)
   225  	}
   226  
   227  	// Leverage a filter so that refs can be found with the same fieldspecs
   228  	// used in rules_kustomize
   229  	fltr := filter{
   230  		FsSlice: fieldspecs.Images,
   231  	}
   232  
   233  	_, err = kio.FilterAll(fltr).Filter(rns)
   234  	if err != nil {
   235  		return nil, fmt.Errorf("filter failed: %w", err)
   236  	}
   237  
   238  	for _, img := range filteredImages {
   239  		// If the workloads or third_party repo is found, it points to an image reference
   240  		// to be resolved by kustomizations
   241  		if strings.HasPrefix(img, "us-east1-docker.pkg.dev/ret-edge-pltf-infra/workloads") || strings.HasPrefix(img, "us-east1-docker.pkg.dev/ret-edge-pltf-infra/thirdparty") || strings.HasPrefix(img, "us-east1-docker.pkg.dev/ret-edge-f8ngang2/f8n-sandbox") {
   242  			imgs = append(imgs, img)
   243  		}
   244  	}
   245  
   246  	// Reset slice for next generation
   247  	filteredImages = []string{}
   248  
   249  	return imgs, nil
   250  }
   251  
   252  // TODO(wc185097_ncrvoyix): refactor, can likely just use a fsslice.Filter
   253  func (f filter) Filter(node *yaml.RNode) (*yaml.RNode, error) {
   254  	return node.Pipe(fsslice.Filter{
   255  		FsSlice:  f.FsSlice,
   256  		SetValue: f.getRef,
   257  	})
   258  }
   259  
   260  func (f filter) getRef(rn *yaml.RNode) error {
   261  	// TODO(wc185097_ncrvoyix): is this check necessary?
   262  	if err := yaml.ErrorIfInvalid(rn, yaml.ScalarNode); err != nil {
   263  		return err
   264  	}
   265  	value := rn.YNode().Value
   266  	filteredImages = append(filteredImages, value)
   267  	return nil
   268  }
   269  

View as plain text