github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/k8s-spec-set.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"bytes"
     8  
     9  	"github.com/juju/cmd/v3"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/gnuflag"
    12  
    13  	jujucmd "github.com/juju/juju/cmd"
    14  )
    15  
    16  // K8sSpecSetCommand implements the k8s-spec-set command.
    17  type K8sSpecSetCommand struct {
    18  	cmd.CommandBase
    19  	name string
    20  	ctx  Context
    21  
    22  	specFile     cmd.FileVar
    23  	k8sResources cmd.FileVar
    24  }
    25  
    26  // NewK8sSpecSetCommand makes a k8s-spec-set command.
    27  func NewK8sSpecSetCommand(ctx Context, name string) (cmd.Command, error) {
    28  	return &K8sSpecSetCommand{ctx: ctx, name: name}, nil
    29  }
    30  
    31  func (c *K8sSpecSetCommand) Info() *cmd.Info {
    32  	doc := `
    33  Sets configuration data to use for k8s resources.
    34  The spec applies to all units for the application.
    35  `
    36  	purpose := "set k8s spec information"
    37  	if c.name == "pod-spec-set" {
    38  		purpose += " (deprecated)"
    39  	}
    40  	return jujucmd.Info(&cmd.Info{
    41  		Name:    c.name,
    42  		Args:    "--file <core spec file> [--k8s-resources <k8s spec file>]",
    43  		Purpose: purpose,
    44  		Doc:     doc,
    45  	})
    46  }
    47  
    48  func (c *K8sSpecSetCommand) SetFlags(f *gnuflag.FlagSet) {
    49  	c.specFile.SetStdin()
    50  	c.specFile.Path = "-"
    51  	f.Var(&c.specFile, "file", "file containing pod spec")
    52  	f.Var(&c.k8sResources, "k8s-resources", "file containing k8s specific resources not yet modelled by Juju")
    53  }
    54  
    55  func (c *K8sSpecSetCommand) Init(args []string) error {
    56  	return cmd.CheckEmpty(args)
    57  }
    58  
    59  func (c *K8sSpecSetCommand) Run(ctx *cmd.Context) error {
    60  	specData, err := c.mergePodSpec(ctx)
    61  	if err != nil {
    62  		return errors.Trace(err)
    63  	}
    64  	return c.ctx.SetPodSpec(specData)
    65  }
    66  
    67  func (c *K8sSpecSetCommand) mergePodSpec(ctx *cmd.Context) (string, error) {
    68  	caasSpecData, err := c.handleSpecFile(ctx)
    69  	if err != nil {
    70  		return "", errors.Trace(err)
    71  	}
    72  	k8sSpecData, err := c.handleK8sResources(ctx)
    73  	if err != nil {
    74  		return "", errors.Trace(err)
    75  	}
    76  	return mergeFileContent(caasSpecData, k8sSpecData), nil
    77  }
    78  
    79  func mergeFileContent(contents ...string) string {
    80  	var buffer bytes.Buffer
    81  	for _, v := range contents {
    82  		if v == "" {
    83  			continue
    84  		}
    85  		buffer.WriteString(v)
    86  	}
    87  	return buffer.String()
    88  }
    89  
    90  func (c *K8sSpecSetCommand) handleSpecFile(ctx *cmd.Context) (string, error) {
    91  	specData, err := c.specFile.Read(ctx)
    92  	if err != nil {
    93  		return "", errors.Trace(err)
    94  	}
    95  	if len(specData) == 0 {
    96  		return "", errors.New("no k8s spec specified: pipe k8s spec to command, or specify a file with --file")
    97  	}
    98  	return string(specData), nil
    99  }
   100  
   101  func (c *K8sSpecSetCommand) handleK8sResources(ctx *cmd.Context) (string, error) {
   102  	if c.k8sResources.Path == "" {
   103  		return "", nil
   104  	}
   105  	k8sResourcesData, err := c.k8sResources.Read(ctx)
   106  	if err != nil {
   107  		return "", errors.Trace(err)
   108  	}
   109  	return string(k8sResourcesData), nil
   110  }