github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/secret-info-get.go (about)

     1  // Copyright 2022 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"time"
     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  	"github.com/juju/juju/core/secrets"
    15  )
    16  
    17  type secretInfoGetCommand struct {
    18  	cmd.CommandBase
    19  	ctx Context
    20  	out cmd.Output
    21  
    22  	secretUri *secrets.URI
    23  	label     string
    24  }
    25  
    26  // NewSecretInfoGetCommand returns a command to get secret metadata.
    27  func NewSecretInfoGetCommand(ctx Context) (cmd.Command, error) {
    28  	return &secretInfoGetCommand{ctx: ctx}, nil
    29  }
    30  
    31  // Info implements cmd.Command.
    32  func (c *secretInfoGetCommand) Info() *cmd.Info {
    33  	doc := `
    34  Get the metadata of a secret with a given secret ID.
    35  Either the ID or label can be used to identify the secret.
    36  
    37  Examples
    38      secret-info-get secret:9m4e2mr0ui3e8a215n4g
    39      secret-info-get --label db-password
    40  `
    41  	return jujucmd.Info(&cmd.Info{
    42  		Name:    "secret-info-get",
    43  		Args:    "<ID>",
    44  		Purpose: "get a secret's metadata info",
    45  		Doc:     doc,
    46  	})
    47  }
    48  
    49  // SetFlags implements cmd.Command.
    50  func (c *secretInfoGetCommand) SetFlags(f *gnuflag.FlagSet) {
    51  	c.out.AddFlags(f, "yaml", map[string]cmd.Formatter{
    52  		"yaml": cmd.FormatYaml,
    53  		"json": cmd.FormatJson,
    54  	})
    55  	f.StringVar(&c.label, "label", "", "a label used to identify the secret")
    56  }
    57  
    58  // Init implements cmd.Command.
    59  func (c *secretInfoGetCommand) Init(args []string) (err error) {
    60  	if len(args) > 0 {
    61  		c.secretUri, err = secrets.ParseURI(args[0])
    62  		if err != nil {
    63  			return errors.NotValidf("secret URI %q", args[0])
    64  		}
    65  		args = args[1:]
    66  	}
    67  
    68  	if c.secretUri == nil && c.label == "" {
    69  		return errors.New("require either a secret URI or label")
    70  	}
    71  	if c.secretUri != nil && c.label != "" {
    72  		return errors.New("specify either a secret URI or label but not both")
    73  	}
    74  	return cmd.CheckEmpty(args)
    75  }
    76  
    77  type metadataDisplay struct {
    78  	LatestRevision   int                  `yaml:"revision" json:"revision"`
    79  	Label            string               `yaml:"label" json:"label"`
    80  	Owner            string               `yaml:"owner" json:"owner"`
    81  	Description      string               `yaml:"description,omitempty" json:"description,omitempty"`
    82  	RotatePolicy     secrets.RotatePolicy `yaml:"rotation,omitempty" json:"rotation,omitempty"`
    83  	LatestExpireTime *time.Time           `yaml:"expiry,omitempty" json:"expiry,omitempty"`
    84  	NextRotateTime   *time.Time           `yaml:"rotates,omitempty" json:"rotates,omitempty"`
    85  	Access           []accessInfo         `yaml:"access,omitempty" json:"access,omitempty"`
    86  }
    87  
    88  // accessInfo holds info about a secret access information.
    89  type accessInfo struct {
    90  	Target string             `yaml:"target" json:"target"`
    91  	Scope  string             `yaml:"scope" json:"scope"`
    92  	Role   secrets.SecretRole `yaml:"role" json:"role"`
    93  }
    94  
    95  func toAccessInfo(grants []secrets.AccessInfo) []accessInfo {
    96  	result := make([]accessInfo, len(grants))
    97  	for i, grant := range grants {
    98  		result[i] = accessInfo{
    99  			Target: grant.Target,
   100  			Scope:  grant.Scope,
   101  			Role:   grant.Role,
   102  		}
   103  	}
   104  	return result
   105  }
   106  
   107  // Run implements cmd.Command.
   108  func (c *secretInfoGetCommand) Run(ctx *cmd.Context) error {
   109  	all, err := c.ctx.SecretMetadata()
   110  	if err != nil {
   111  		return err
   112  	}
   113  	print := func(id string, md SecretMetadata) error {
   114  		return c.out.Write(ctx, map[string]metadataDisplay{
   115  			id: {
   116  				LatestRevision:   md.LatestRevision,
   117  				Label:            md.Label,
   118  				Owner:            md.Owner.Kind(),
   119  				Description:      md.Description,
   120  				RotatePolicy:     md.RotatePolicy,
   121  				LatestExpireTime: md.LatestExpireTime,
   122  				NextRotateTime:   md.NextRotateTime,
   123  				Access:           toAccessInfo(md.Access),
   124  			}})
   125  	}
   126  	var want string
   127  	if c.secretUri != nil {
   128  		want = c.secretUri.ID
   129  		if md, found := all[want]; found {
   130  			return print(want, md)
   131  		}
   132  
   133  	} else {
   134  		want = c.label
   135  		for id, md := range all {
   136  			if md.Label == want {
   137  				return print(id, md)
   138  			}
   139  		}
   140  	}
   141  	return errors.NotFoundf("secret %q", want)
   142  }