...

Source file src/edge-infra.dev/pkg/f8n/warehouse/lift/cmd/pallet/init.go

Documentation: edge-infra.dev/pkg/f8n/warehouse/lift/cmd/pallet

     1  package pallet
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"os"
     7  	"path"
     8  	"strings"
     9  
    10  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  	ktypes "sigs.k8s.io/kustomize/api/types"
    12  	"sigs.k8s.io/yaml"
    13  
    14  	"edge-infra.dev/pkg/f8n/warehouse/capability"
    15  	"edge-infra.dev/pkg/f8n/warehouse/cluster"
    16  	"edge-infra.dev/pkg/f8n/warehouse/lift/pack/types"
    17  	"edge-infra.dev/pkg/lib/cli/rags"
    18  	"edge-infra.dev/pkg/lib/cli/sink"
    19  )
    20  
    21  // TODO: should scaffold more complete file structure based on cluster providers
    22  // TODO: add capabilities flag
    23  // TODO: autodetect
    24  // TODO: dir of files
    25  // TODO: resolve pallet
    26  
    27  var (
    28  	initCmd *sink.Command
    29  )
    30  
    31  const (
    32  	// palletFilename the file name for the pallet
    33  	palletFilename = "pallet.yaml"
    34  	// kustomizationFilename the file name for the kustomization
    35  	kustomizationFilename = "kustomization.yaml"
    36  	// defaultPath the default path that the pallet will be generated
    37  	defaultPath = "config/pallets"
    38  	// gcpProjectIDAnnotation gcp project id annotation
    39  	gcpProjectIDAnnotation = "cnrm.cloud.google.com/project-id"
    40  	// edgePlatformLabel platform component annotation
    41  	edgePlatformLabel = "platform.edge.ncr.com/component"
    42  )
    43  
    44  // TODO: update to use declarative flags + clean up
    45  func NewInitCmd() *sink.Command {
    46  	var (
    47  		name                    string
    48  		namespace               string
    49  		outputPath              string
    50  		providers               cluster.Providers
    51  		capabilities            capability.Capabilities
    52  		team                    string
    53  		vendor                  string
    54  		description             string
    55  		kustomization           bool
    56  		kustomizationResources  string
    57  		kustomizationComponents string
    58  	)
    59  
    60  	fs := rags.New("lift pallet init", flag.ContinueOnError)
    61  	fs.StringVar(&name, "name", "",
    62  		"the name of the pallet")
    63  	fs.StringVar(&namespace, "namespace", "",
    64  		"the namespace of the pallet")
    65  	fs.StringVar(&outputPath, "output", defaultPath,
    66  		"the output location to create the pallet file")
    67  	fs.Var(&providers, "cluster-providers",
    68  		"comma separated list of cluster providers the Pallet will define variants "+
    69  			"for. accumulates values if provided multiple times")
    70  	fs.Var(&capabilities, "runtime-capabilities",
    71  		"comma separated list of runtime capabilities by package name the Pallet "+
    72  			"will integrate with accumulates values if provided multiple times.")
    73  	fs.StringVar(&team, "team", "",
    74  		"the team responsible for the pallet")
    75  	fs.StringVar(&vendor, "vendor", "",
    76  		"the pallet vendor")
    77  	fs.StringVar(&description, "description", "",
    78  		"the pallet description")
    79  	fs.BoolVar(&kustomization, "create-kustomization", false,
    80  		"should a companion kustomization file be created")
    81  	fs.StringVar(&kustomizationResources, "resources", "",
    82  		"the comma separated list of kustomization resources")
    83  	fs.StringVar(&kustomizationComponents, "components", "",
    84  		"the comma separated list of kustomization components")
    85  
    86  	initCmd = &sink.Command{
    87  		Use:   "init <flags>",
    88  		Short: "Scaffold the source for a Warehouse package",
    89  		Flags: fs.Rags(),
    90  		Exec: func(_ context.Context, _ sink.Run) error {
    91  			resources := parseResources(kustomizationResources)
    92  			components := parseResources(kustomizationComponents)
    93  			pllet := &types.Pallet{
    94  				TypeMeta: v1.TypeMeta{
    95  					Kind:       types.PalletKind,
    96  					APIVersion: types.APIVersion,
    97  				},
    98  				ObjectMeta: v1.ObjectMeta{
    99  					Name: name,
   100  				},
   101  				PalletSpec: types.PalletSpec{
   102  					Capabilities: capabilities,
   103  					Description:  description,
   104  					Providers:    providers,
   105  					Team:         team,
   106  					Vendor:       vendor,
   107  				},
   108  			}
   109  			palletYAML, err := yaml.Marshal(pllet)
   110  			if err != nil {
   111  				return err
   112  			}
   113  			if _, err := os.Stat(path.Join(outputPath, name)); os.IsNotExist(err) {
   114  				err := os.MkdirAll(path.Join(outputPath, name), 0755)
   115  				if err != nil {
   116  					return err
   117  				}
   118  			}
   119  			if err := writeFile(outputPath, name, palletFilename, palletYAML); err != nil {
   120  				return err
   121  			}
   122  			if kustomization {
   123  				yaml, err := createKustomization(name, namespace, resources, components)
   124  				if err != nil {
   125  					return err
   126  				}
   127  				return writeFile(outputPath, name, kustomizationFilename, yaml)
   128  			}
   129  			return nil
   130  		},
   131  	}
   132  	return initCmd
   133  }
   134  
   135  // createKustomization generates the k8s kustomization file.
   136  func createKustomization(name, namespace string, resources, components []string) ([]byte, error) {
   137  	kusto := &ktypes.Kustomization{
   138  		TypeMeta: ktypes.TypeMeta{
   139  			Kind:       ktypes.KustomizationKind,
   140  			APIVersion: ktypes.KustomizationVersion,
   141  		},
   142  		// TODO: add --infra flag and only add this to the infra-specific kustomization
   143  		CommonAnnotations: map[string]string{
   144  			gcpProjectIDAnnotation: "${gcp_project_id}",
   145  		},
   146  		CommonLabels: map[string]string{
   147  			edgePlatformLabel: name,
   148  		},
   149  		Namespace: namespace,
   150  		// TODO: need to normalie path?
   151  		Resources:  resources,
   152  		Components: components,
   153  	}
   154  	kustoYaml, err := yaml.Marshal(kusto)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	return kustoYaml, nil
   159  }
   160  
   161  // writeFile utility func to write file to provided path.
   162  func writeFile(outDir, name, fileName string, yamlData []byte) error {
   163  	err := os.WriteFile(path.Join(outDir, name, fileName), yamlData, 0644)
   164  	return err
   165  }
   166  
   167  // parseResources parses the comma separated string of resources and components.
   168  func parseResources(value string) []string {
   169  	return strings.Split(value, ",")
   170  }
   171  

View as plain text