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

     1  package kafka
     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 a Kafka 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  	// Optional.
    27  	AuthMethod        argparser.OptionalString
    28  	AutoClone         argparser.OptionalAutoClone
    29  	Brokers           argparser.OptionalString
    30  	CompressionCodec  argparser.OptionalString
    31  	EndpointName      argparser.OptionalString // Can't shadow argparser.Base method Name().
    32  	Format            argparser.OptionalString
    33  	FormatVersion     argparser.OptionalInt
    34  	ParseLogKeyvals   argparser.OptionalBool
    35  	Password          argparser.OptionalString
    36  	Placement         argparser.OptionalString
    37  	RequestMaxBytes   argparser.OptionalInt
    38  	RequiredACKs      argparser.OptionalString
    39  	ResponseCondition argparser.OptionalString
    40  	TLSCACert         argparser.OptionalString
    41  	TLSClientCert     argparser.OptionalString
    42  	TLSClientKey      argparser.OptionalString
    43  	TLSHostname       argparser.OptionalString
    44  	Topic             argparser.OptionalString
    45  	User              argparser.OptionalString
    46  	UseSASL           argparser.OptionalBool
    47  	UseTLS            argparser.OptionalBool
    48  }
    49  
    50  // NewCreateCommand returns a usable command registered under the parent.
    51  func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateCommand {
    52  	c := CreateCommand{
    53  		Base: argparser.Base{
    54  			Globals: g,
    55  		},
    56  	}
    57  	c.CmdClause = parent.Command("create", "Create a Kafka logging endpoint on a Fastly service version").Alias("add")
    58  
    59  	// Required.
    60  	c.CmdClause.Flag("name", "The name of the Kafka logging object. Used as a primary key for API access").Short('n').Action(c.EndpointName.Set).StringVar(&c.EndpointName.Value)
    61  	c.RegisterFlag(argparser.StringFlagOpts{
    62  		Name:        argparser.FlagVersionName,
    63  		Description: argparser.FlagVersionDesc,
    64  		Dst:         &c.ServiceVersion.Value,
    65  		Required:    true,
    66  	})
    67  
    68  	// Optional.
    69  	c.RegisterAutoCloneFlag(argparser.AutoCloneFlagOpts{
    70  		Action: c.AutoClone.Set,
    71  		Dst:    &c.AutoClone.Value,
    72  	})
    73  	c.CmdClause.Flag("auth-method", "SASL authentication method. Valid values are: plain, scram-sha-256, scram-sha-512").Action(c.AuthMethod.Set).HintOptions("plain", "scram-sha-256", "scram-sha-512").EnumVar(&c.AuthMethod.Value, "plain", "scram-sha-256", "scram-sha-512")
    74  	c.CmdClause.Flag("brokers", "A comma-separated list of IP addresses or hostnames of Kafka brokers").Action(c.Brokers.Set).StringVar(&c.Brokers.Value)
    75  	c.CmdClause.Flag("compression-codec", "The codec used for compression of your logs. One of: gzip, snappy, lz4").Action(c.CompressionCodec.Set).StringVar(&c.CompressionCodec.Value)
    76  	common.Format(c.CmdClause, &c.Format)
    77  	common.FormatVersion(c.CmdClause, &c.FormatVersion)
    78  	c.CmdClause.Flag("max-batch-size", "The maximum size of the log batch in bytes").Action(c.RequestMaxBytes.Set).IntVar(&c.RequestMaxBytes.Value)
    79  	c.CmdClause.Flag("parse-log-keyvals", "Parse key-value pairs within the log format").Action(c.ParseLogKeyvals.Set).BoolVar(&c.ParseLogKeyvals.Value)
    80  	c.CmdClause.Flag("password", "SASL authentication password. Required if --auth-method is specified").Action(c.Password.Set).StringVar(&c.Password.Value)
    81  	common.Placement(c.CmdClause, &c.Placement)
    82  	c.CmdClause.Flag("required-acks", "The Number of acknowledgements a leader must receive before a write is considered successful. One of: 1 (default) One server needs to respond. 0	No servers need to respond. -1	Wait for all in-sync replicas to respond").Action(c.RequiredACKs.Set).StringVar(&c.RequiredACKs.Value)
    83  	common.ResponseCondition(c.CmdClause, &c.ResponseCondition)
    84  	c.RegisterFlag(argparser.StringFlagOpts{
    85  		Name:        argparser.FlagServiceIDName,
    86  		Description: argparser.FlagServiceIDDesc,
    87  		Dst:         &g.Manifest.Flag.ServiceID,
    88  		Short:       's',
    89  	})
    90  	c.RegisterFlag(argparser.StringFlagOpts{
    91  		Action:      c.ServiceName.Set,
    92  		Name:        argparser.FlagServiceName,
    93  		Description: argparser.FlagServiceDesc,
    94  		Dst:         &c.ServiceName.Value,
    95  	})
    96  	common.TLSCACert(c.CmdClause, &c.TLSCACert)
    97  	common.TLSClientCert(c.CmdClause, &c.TLSClientCert)
    98  	common.TLSClientKey(c.CmdClause, &c.TLSClientKey)
    99  	common.TLSHostname(c.CmdClause, &c.TLSHostname)
   100  	c.CmdClause.Flag("topic", "The Kafka topic to send logs to").Action(c.Topic.Set).StringVar(&c.Topic.Value)
   101  	c.CmdClause.Flag("use-sasl", "Enable SASL authentication. Requires --auth-method, --username, and --password to be specified").Action(c.UseSASL.Set).BoolVar(&c.UseSASL.Value)
   102  	c.CmdClause.Flag("use-tls", "Whether to use TLS for secure logging. Can be either true or false").Action(c.UseTLS.Set).BoolVar(&c.UseTLS.Value)
   103  	c.CmdClause.Flag("username", "SASL authentication username. Required if --auth-method is specified").Action(c.User.Set).StringVar(&c.User.Value)
   104  	return &c
   105  }
   106  
   107  // ConstructInput transforms values parsed from CLI flags into an object to be used by the API client library.
   108  func (c *CreateCommand) ConstructInput(serviceID string, serviceVersion int) (*fastly.CreateKafkaInput, error) {
   109  	var input fastly.CreateKafkaInput
   110  
   111  	if c.UseSASL.WasSet && c.UseSASL.Value && (c.AuthMethod.Value == "" || c.User.Value == "" || c.Password.Value == "") {
   112  		return nil, fmt.Errorf("the --auth-method, --username, and --password flags must be present when using the --use-sasl flag")
   113  	}
   114  
   115  	if !c.UseSASL.Value && (c.AuthMethod.Value != "" || c.User.Value != "" || c.Password.Value != "") {
   116  		return nil, fmt.Errorf("the --auth-method, --username, and --password options are only valid when the --use-sasl flag is specified")
   117  	}
   118  
   119  	input.ServiceID = serviceID
   120  	input.ServiceVersion = serviceVersion
   121  	if c.EndpointName.WasSet {
   122  		input.Name = &c.EndpointName.Value
   123  	}
   124  	if c.Topic.WasSet {
   125  		input.Topic = &c.Topic.Value
   126  	}
   127  	if c.Brokers.WasSet {
   128  		input.Brokers = &c.Brokers.Value
   129  	}
   130  
   131  	if c.CompressionCodec.WasSet {
   132  		input.CompressionCodec = &c.CompressionCodec.Value
   133  	}
   134  
   135  	if c.RequiredACKs.WasSet {
   136  		input.RequiredACKs = &c.RequiredACKs.Value
   137  	}
   138  
   139  	if c.UseTLS.WasSet {
   140  		input.UseTLS = fastly.ToPointer(fastly.Compatibool(c.UseTLS.Value))
   141  	}
   142  
   143  	if c.TLSCACert.WasSet {
   144  		input.TLSCACert = &c.TLSCACert.Value
   145  	}
   146  
   147  	if c.TLSClientCert.WasSet {
   148  		input.TLSClientCert = &c.TLSClientCert.Value
   149  	}
   150  
   151  	if c.TLSClientKey.WasSet {
   152  		input.TLSClientKey = &c.TLSClientKey.Value
   153  	}
   154  
   155  	if c.TLSHostname.WasSet {
   156  		input.TLSHostname = &c.TLSHostname.Value
   157  	}
   158  
   159  	if c.Format.WasSet {
   160  		input.Format = &c.Format.Value
   161  	}
   162  
   163  	if c.FormatVersion.WasSet {
   164  		input.FormatVersion = &c.FormatVersion.Value
   165  	}
   166  
   167  	if c.ResponseCondition.WasSet {
   168  		input.ResponseCondition = &c.ResponseCondition.Value
   169  	}
   170  
   171  	if c.Placement.WasSet {
   172  		input.Placement = &c.Placement.Value
   173  	}
   174  
   175  	if c.ParseLogKeyvals.WasSet {
   176  		input.ParseLogKeyvals = fastly.ToPointer(fastly.Compatibool(c.ParseLogKeyvals.Value))
   177  	}
   178  
   179  	if c.RequestMaxBytes.WasSet {
   180  		input.RequestMaxBytes = &c.RequestMaxBytes.Value
   181  	}
   182  
   183  	if c.AuthMethod.WasSet {
   184  		input.AuthMethod = &c.AuthMethod.Value
   185  	}
   186  
   187  	if c.User.WasSet {
   188  		input.User = &c.User.Value
   189  	}
   190  
   191  	if c.Password.WasSet {
   192  		input.Password = &c.Password.Value
   193  	}
   194  
   195  	return &input, nil
   196  }
   197  
   198  // Exec invokes the application logic for the command.
   199  func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error {
   200  	serviceID, serviceVersion, err := argparser.ServiceDetails(argparser.ServiceDetailsOpts{
   201  		AutoCloneFlag:      c.AutoClone,
   202  		APIClient:          c.Globals.APIClient,
   203  		Manifest:           *c.Globals.Manifest,
   204  		Out:                out,
   205  		ServiceNameFlag:    c.ServiceName,
   206  		ServiceVersionFlag: c.ServiceVersion,
   207  		VerboseMode:        c.Globals.Flags.Verbose,
   208  	})
   209  	if err != nil {
   210  		c.Globals.ErrLog.AddWithContext(err, map[string]any{
   211  			"Service ID":      serviceID,
   212  			"Service Version": errors.ServiceVersion(serviceVersion),
   213  		})
   214  		return err
   215  	}
   216  
   217  	input, err := c.ConstructInput(serviceID, fastly.ToValue(serviceVersion.Number))
   218  	if err != nil {
   219  		c.Globals.ErrLog.Add(err)
   220  		return err
   221  	}
   222  
   223  	d, err := c.Globals.APIClient.CreateKafka(input)
   224  	if err != nil {
   225  		c.Globals.ErrLog.Add(err)
   226  		return err
   227  	}
   228  
   229  	text.Success(out,
   230  		"Created Kafka logging endpoint %s (service %s version %d)",
   231  		fastly.ToValue(d.Name),
   232  		fastly.ToValue(d.ServiceID),
   233  		fastly.ToValue(d.ServiceVersion),
   234  	)
   235  	return nil
   236  }