github.com/fastly/cli@v1.7.2-0.20240304164155-9d0f1d77c3bf/pkg/commands/vcl/snippet/describe.go (about)

     1  package snippet
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/fastly/go-fastly/v9/fastly"
     8  
     9  	"github.com/fastly/cli/pkg/argparser"
    10  	fsterr "github.com/fastly/cli/pkg/errors"
    11  	"github.com/fastly/cli/pkg/global"
    12  )
    13  
    14  // NewDescribeCommand returns a usable command registered under the parent.
    15  func NewDescribeCommand(parent argparser.Registerer, g *global.Data) *DescribeCommand {
    16  	c := DescribeCommand{
    17  		Base: argparser.Base{
    18  			Globals: g,
    19  		},
    20  	}
    21  	c.CmdClause = parent.Command("describe", "Get the uploaded VCL snippet for a particular service and version").Alias("get")
    22  
    23  	// Required.
    24  	c.RegisterFlag(argparser.StringFlagOpts{
    25  		Name:        argparser.FlagVersionName,
    26  		Description: argparser.FlagVersionDesc,
    27  		Dst:         &c.serviceVersion.Value,
    28  		Required:    true,
    29  	})
    30  
    31  	// Optional.
    32  	c.CmdClause.Flag("dynamic", "Whether the VCL snippet is dynamic or versioned").Action(c.dynamic.Set).BoolVar(&c.dynamic.Value)
    33  	c.RegisterFlagBool(c.JSONFlag()) // --json
    34  	c.CmdClause.Flag("name", "The name of the VCL snippet").StringVar(&c.name)
    35  	c.RegisterFlag(argparser.StringFlagOpts{
    36  		Name:        argparser.FlagServiceIDName,
    37  		Description: argparser.FlagServiceIDDesc,
    38  		Dst:         &g.Manifest.Flag.ServiceID,
    39  		Short:       's',
    40  	})
    41  	c.RegisterFlag(argparser.StringFlagOpts{
    42  		Action:      c.serviceName.Set,
    43  		Name:        argparser.FlagServiceName,
    44  		Description: argparser.FlagServiceDesc,
    45  		Dst:         &c.serviceName.Value,
    46  	})
    47  	c.CmdClause.Flag("snippet-id", "Alphanumeric string identifying a VCL Snippet").StringVar(&c.snippetID)
    48  
    49  	return &c
    50  }
    51  
    52  // DescribeCommand calls the Fastly API to describe an appropriate resource.
    53  type DescribeCommand struct {
    54  	argparser.Base
    55  	argparser.JSONOutput
    56  
    57  	dynamic        argparser.OptionalBool
    58  	name           string
    59  	serviceName    argparser.OptionalServiceNameID
    60  	serviceVersion argparser.OptionalServiceVersion
    61  	snippetID      string
    62  }
    63  
    64  // Exec invokes the application logic for the command.
    65  func (c *DescribeCommand) Exec(_ io.Reader, out io.Writer) error {
    66  	if c.Globals.Verbose() && c.JSONOutput.Enabled {
    67  		return fsterr.ErrInvalidVerboseJSONCombo
    68  	}
    69  
    70  	serviceID, serviceVersion, err := argparser.ServiceDetails(argparser.ServiceDetailsOpts{
    71  		AllowActiveLocked:  true,
    72  		APIClient:          c.Globals.APIClient,
    73  		Manifest:           *c.Globals.Manifest,
    74  		Out:                out,
    75  		ServiceNameFlag:    c.serviceName,
    76  		ServiceVersionFlag: c.serviceVersion,
    77  		VerboseMode:        c.Globals.Flags.Verbose,
    78  	})
    79  	if err != nil {
    80  		c.Globals.ErrLog.AddWithContext(err, map[string]any{
    81  			"Service ID":      serviceID,
    82  			"Service Version": fsterr.ServiceVersion(serviceVersion),
    83  		})
    84  		return err
    85  	}
    86  
    87  	serviceVersionNumber := fastly.ToValue(serviceVersion.Number)
    88  
    89  	if c.dynamic.WasSet {
    90  		input, err := c.constructDynamicInput(serviceID, serviceVersionNumber)
    91  		if err != nil {
    92  			c.Globals.ErrLog.AddWithContext(err, map[string]any{
    93  				"Service ID":      serviceID,
    94  				"Service Version": serviceVersionNumber,
    95  			})
    96  			return err
    97  		}
    98  
    99  		o, err := c.Globals.APIClient.GetDynamicSnippet(input)
   100  		if err != nil {
   101  			c.Globals.ErrLog.AddWithContext(err, map[string]any{
   102  				"Service ID":      serviceID,
   103  				"Service Version": serviceVersionNumber,
   104  			})
   105  			return err
   106  		}
   107  
   108  		if ok, err := c.WriteJSON(out, o); ok {
   109  			return err
   110  		}
   111  
   112  		return c.printDynamic(out, o)
   113  	}
   114  
   115  	input, err := c.constructInput(serviceID, serviceVersionNumber)
   116  	if err != nil {
   117  		c.Globals.ErrLog.AddWithContext(err, map[string]any{
   118  			"Service ID":      serviceID,
   119  			"Service Version": serviceVersionNumber,
   120  		})
   121  		return err
   122  	}
   123  
   124  	o, err := c.Globals.APIClient.GetSnippet(input)
   125  	if err != nil {
   126  		c.Globals.ErrLog.AddWithContext(err, map[string]any{
   127  			"Service ID":      serviceID,
   128  			"Service Version": serviceVersionNumber,
   129  		})
   130  		return err
   131  	}
   132  
   133  	if ok, err := c.WriteJSON(out, o); ok {
   134  		return err
   135  	}
   136  
   137  	return c.print(out, o)
   138  }
   139  
   140  // constructDynamicInput transforms values parsed from CLI flags into an object to be used by the API client library.
   141  func (c *DescribeCommand) constructDynamicInput(serviceID string, _ int) (*fastly.GetDynamicSnippetInput, error) {
   142  	var input fastly.GetDynamicSnippetInput
   143  
   144  	input.SnippetID = c.snippetID
   145  	input.ServiceID = serviceID
   146  
   147  	if c.snippetID == "" {
   148  		return nil, fmt.Errorf("error parsing arguments: must provide --snippet-id with a dynamic VCL snippet")
   149  	}
   150  
   151  	return &input, nil
   152  }
   153  
   154  // constructInput transforms values parsed from CLI flags into an object to be used by the API client library.
   155  func (c *DescribeCommand) constructInput(serviceID string, serviceVersion int) (*fastly.GetSnippetInput, error) {
   156  	var input fastly.GetSnippetInput
   157  
   158  	input.Name = c.name
   159  	input.ServiceID = serviceID
   160  	input.ServiceVersion = serviceVersion
   161  
   162  	if c.name == "" {
   163  		return nil, fmt.Errorf("error parsing arguments: must provide --name with a versioned VCL snippet")
   164  	}
   165  
   166  	return &input, nil
   167  }
   168  
   169  // print displays the 'dynamic' information returned from the API.
   170  func (c *DescribeCommand) printDynamic(out io.Writer, ds *fastly.DynamicSnippet) error {
   171  	fmt.Fprintf(out, "\nService ID: %s\n", fastly.ToValue(ds.ServiceID))
   172  	fmt.Fprintf(out, "ID: %s\n", fastly.ToValue(ds.SnippetID))
   173  	fmt.Fprintf(out, "Content: \n%s\n", fastly.ToValue(ds.Content))
   174  	if ds.CreatedAt != nil {
   175  		fmt.Fprintf(out, "Created at: %s\n", ds.CreatedAt)
   176  	}
   177  	if ds.UpdatedAt != nil {
   178  		fmt.Fprintf(out, "Updated at: %s\n", ds.UpdatedAt)
   179  	}
   180  	return nil
   181  }
   182  
   183  // print displays the information returned from the API.
   184  func (c *DescribeCommand) print(out io.Writer, s *fastly.Snippet) error {
   185  	if !c.Globals.Verbose() {
   186  		fmt.Fprintf(out, "\nService ID: %s\n", fastly.ToValue(s.ServiceID))
   187  	}
   188  	fmt.Fprintf(out, "Service Version: %d\n", fastly.ToValue(s.ServiceVersion))
   189  	fmt.Fprintf(out, "\nName: %s\n", fastly.ToValue(s.Name))
   190  	fmt.Fprintf(out, "ID: %s\n", fastly.ToValue(s.SnippetID))
   191  	fmt.Fprintf(out, "Priority: %d\n", fastly.ToValue(s.Priority))
   192  	fmt.Fprintf(out, "Dynamic: %t\n", argparser.IntToBool(fastly.ToValue(s.Dynamic)))
   193  	fmt.Fprintf(out, "Type: %s\n", fastly.ToValue(s.Type))
   194  	fmt.Fprintf(out, "Content: \n%s\n", fastly.ToValue(s.Content))
   195  	if s.CreatedAt != nil {
   196  		fmt.Fprintf(out, "Created at: %s\n", s.CreatedAt)
   197  	}
   198  	if s.UpdatedAt != nil {
   199  		fmt.Fprintf(out, "Updated at: %s\n", s.UpdatedAt)
   200  	}
   201  	if s.DeletedAt != nil {
   202  		fmt.Fprintf(out, "Deleted at: %s\n", s.DeletedAt)
   203  	}
   204  	return nil
   205  }