github.com/fastly/cli@v1.7.2-0.20240304164155-9d0f1d77c3bf/pkg/commands/logging/kinesis/create.go (about)

     1  package kinesis
     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  	"github.com/fastly/cli/pkg/commands/logging/common"
    11  	"github.com/fastly/cli/pkg/errors"
    12  	"github.com/fastly/cli/pkg/global"
    13  	"github.com/fastly/cli/pkg/manifest"
    14  	"github.com/fastly/cli/pkg/text"
    15  )
    16  
    17  // CreateCommand calls the Fastly API to create an Amazon Kinesis logging endpoint.
    18  type CreateCommand struct {
    19  	argparser.Base
    20  	Manifest manifest.Data
    21  
    22  	// Required.
    23  	ServiceName    argparser.OptionalServiceNameID
    24  	ServiceVersion argparser.OptionalServiceVersion
    25  
    26  	// mutual exclusions
    27  	// AccessKey + SecretKey or IAMRole must be provided
    28  	AccessKey argparser.OptionalString
    29  	SecretKey argparser.OptionalString
    30  	IAMRole   argparser.OptionalString
    31  
    32  	// Optional.
    33  	AutoClone         argparser.OptionalAutoClone
    34  	EndpointName      argparser.OptionalString // Can't shadow argparser.Base method Name().
    35  	Format            argparser.OptionalString
    36  	FormatVersion     argparser.OptionalInt
    37  	Placement         argparser.OptionalString
    38  	Region            argparser.OptionalString
    39  	ResponseCondition argparser.OptionalString
    40  	StreamName        argparser.OptionalString
    41  }
    42  
    43  // NewCreateCommand returns a usable command registered under the parent.
    44  func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateCommand {
    45  	c := CreateCommand{
    46  		Base: argparser.Base{
    47  			Globals: g,
    48  		},
    49  	}
    50  	c.CmdClause = parent.Command("create", "Create an Amazon Kinesis logging endpoint on a Fastly service version").Alias("add")
    51  
    52  	// Required.
    53  	c.CmdClause.Flag("name", "The name of the Kinesis logging object. Used as a primary key for API access").Short('n').Action(c.EndpointName.Set).StringVar(&c.EndpointName.Value)
    54  	c.RegisterFlag(argparser.StringFlagOpts{
    55  		Name:        argparser.FlagVersionName,
    56  		Description: argparser.FlagVersionDesc,
    57  		Dst:         &c.ServiceVersion.Value,
    58  		Required:    true,
    59  	})
    60  
    61  	// required, but mutually exclusive
    62  	c.CmdClause.Flag("access-key", "The access key associated with the target Amazon Kinesis stream").Action(c.AccessKey.Set).StringVar(&c.AccessKey.Value)
    63  	c.CmdClause.Flag("secret-key", "The secret key associated with the target Amazon Kinesis stream").Action(c.SecretKey.Set).StringVar(&c.SecretKey.Value)
    64  	c.CmdClause.Flag("iam-role", "The IAM role ARN for logging").Action(c.IAMRole.Set).StringVar(&c.IAMRole.Value)
    65  
    66  	// Optional.
    67  	c.RegisterAutoCloneFlag(argparser.AutoCloneFlagOpts{
    68  		Action: c.AutoClone.Set,
    69  		Dst:    &c.AutoClone.Value,
    70  	})
    71  	common.Format(c.CmdClause, &c.Format)
    72  	common.FormatVersion(c.CmdClause, &c.FormatVersion)
    73  	c.CmdClause.Flag("region", "The AWS region where the Kinesis stream exists").Action(c.Region.Set).StringVar(&c.Region.Value)
    74  	common.ResponseCondition(c.CmdClause, &c.ResponseCondition)
    75  	common.Placement(c.CmdClause, &c.Placement)
    76  	c.CmdClause.Flag("stream-name", "The Amazon Kinesis stream to send logs to").Action(c.StreamName.Set).StringVar(&c.StreamName.Value)
    77  	c.RegisterFlag(argparser.StringFlagOpts{
    78  		Name:        argparser.FlagServiceIDName,
    79  		Description: argparser.FlagServiceIDDesc,
    80  		Dst:         &g.Manifest.Flag.ServiceID,
    81  		Short:       's',
    82  	})
    83  	c.RegisterFlag(argparser.StringFlagOpts{
    84  		Action:      c.ServiceName.Set,
    85  		Name:        argparser.FlagServiceName,
    86  		Description: argparser.FlagServiceDesc,
    87  		Dst:         &c.ServiceName.Value,
    88  	})
    89  
    90  	return &c
    91  }
    92  
    93  // ConstructInput transforms values parsed from CLI flags into an object to be used by the API client library.
    94  func (c *CreateCommand) ConstructInput(serviceID string, serviceVersion int) (*fastly.CreateKinesisInput, error) {
    95  	var input fastly.CreateKinesisInput
    96  
    97  	input.ServiceID = serviceID
    98  	if c.EndpointName.WasSet {
    99  		input.Name = &c.EndpointName.Value
   100  	}
   101  	if c.StreamName.WasSet {
   102  		input.StreamName = &c.StreamName.Value
   103  	}
   104  	if c.Region.WasSet {
   105  		input.Region = &c.Region.Value
   106  	}
   107  	input.ServiceVersion = serviceVersion
   108  
   109  	// The following block checks for invalid permutations of the ways in
   110  	// which the AccessKey + SecretKey and IAMRole flags can be
   111  	// provided. This is necessary because either the AccessKey and
   112  	// SecretKey or the IAMRole is required, but they are mutually
   113  	// exclusive. The kingpin library lacks a way to express this constraint
   114  	// via the flag specification API so we enforce it manually here.
   115  	switch {
   116  	case !c.AccessKey.WasSet && !c.SecretKey.WasSet && !c.IAMRole.WasSet:
   117  		return nil, fmt.Errorf("error parsing arguments: the --access-key and --secret-key flags or the --iam-role flag must be provided")
   118  	case (c.AccessKey.WasSet || c.SecretKey.WasSet) && c.IAMRole.WasSet:
   119  		// Enforce mutual exclusion
   120  		return nil, fmt.Errorf("error parsing arguments: the --access-key and --secret-key flags are mutually exclusive with the --iam-role flag")
   121  	case c.AccessKey.WasSet && !c.SecretKey.WasSet:
   122  		return nil, fmt.Errorf("error parsing arguments: required flag --secret-key not provided")
   123  	case !c.AccessKey.WasSet && c.SecretKey.WasSet:
   124  		return nil, fmt.Errorf("error parsing arguments: required flag --access-key not provided")
   125  	}
   126  
   127  	if c.AccessKey.WasSet {
   128  		input.AccessKey = &c.AccessKey.Value
   129  	}
   130  
   131  	if c.SecretKey.WasSet {
   132  		input.SecretKey = &c.SecretKey.Value
   133  	}
   134  
   135  	if c.IAMRole.WasSet {
   136  		input.IAMRole = &c.IAMRole.Value
   137  	}
   138  
   139  	if c.Format.WasSet {
   140  		input.Format = &c.Format.Value
   141  	}
   142  
   143  	if c.FormatVersion.WasSet {
   144  		input.FormatVersion = &c.FormatVersion.Value
   145  	}
   146  
   147  	if c.ResponseCondition.WasSet {
   148  		input.ResponseCondition = &c.ResponseCondition.Value
   149  	}
   150  
   151  	if c.Placement.WasSet {
   152  		input.Placement = &c.Placement.Value
   153  	}
   154  
   155  	return &input, nil
   156  }
   157  
   158  // Exec invokes the application logic for the command.
   159  func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error {
   160  	serviceID, serviceVersion, err := argparser.ServiceDetails(argparser.ServiceDetailsOpts{
   161  		AutoCloneFlag:      c.AutoClone,
   162  		APIClient:          c.Globals.APIClient,
   163  		Manifest:           *c.Globals.Manifest,
   164  		Out:                out,
   165  		ServiceNameFlag:    c.ServiceName,
   166  		ServiceVersionFlag: c.ServiceVersion,
   167  		VerboseMode:        c.Globals.Flags.Verbose,
   168  	})
   169  	if err != nil {
   170  		c.Globals.ErrLog.AddWithContext(err, map[string]any{
   171  			"Service ID":      serviceID,
   172  			"Service Version": errors.ServiceVersion(serviceVersion),
   173  		})
   174  		return err
   175  	}
   176  
   177  	input, err := c.ConstructInput(serviceID, fastly.ToValue(serviceVersion.Number))
   178  	if err != nil {
   179  		c.Globals.ErrLog.Add(err)
   180  		return err
   181  	}
   182  
   183  	d, err := c.Globals.APIClient.CreateKinesis(input)
   184  	if err != nil {
   185  		c.Globals.ErrLog.Add(err)
   186  		return err
   187  	}
   188  
   189  	text.Success(out,
   190  		"Created Kinesis logging endpoint %s (service %s version %d)",
   191  		fastly.ToValue(d.Name),
   192  		fastly.ToValue(d.ServiceID),
   193  		fastly.ToValue(d.ServiceVersion),
   194  	)
   195  	return nil
   196  }