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

     1  package sftp
     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 SFTP 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  	Address           argparser.OptionalString
    28  	AutoClone         argparser.OptionalAutoClone
    29  	CompressionCodec  argparser.OptionalString
    30  	EndpointName      argparser.OptionalString // Can't shadow argparser.Base method Name().
    31  	Format            argparser.OptionalString
    32  	FormatVersion     argparser.OptionalInt
    33  	GzipLevel         argparser.OptionalInt
    34  	MessageType       argparser.OptionalString
    35  	Password          argparser.OptionalString
    36  	Path              argparser.OptionalString
    37  	Period            argparser.OptionalInt
    38  	Placement         argparser.OptionalString
    39  	Port              argparser.OptionalInt
    40  	PublicKey         argparser.OptionalString
    41  	ResponseCondition argparser.OptionalString
    42  	SecretKey         argparser.OptionalString
    43  	SSHKnownHosts     argparser.OptionalString
    44  	TimestampFormat   argparser.OptionalString
    45  	User              argparser.OptionalString
    46  }
    47  
    48  // NewCreateCommand returns a usable command registered under the parent.
    49  func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateCommand {
    50  	c := CreateCommand{
    51  		Base: argparser.Base{
    52  			Globals: g,
    53  		},
    54  	}
    55  	c.CmdClause = parent.Command("create", "Create an SFTP logging endpoint on a Fastly service version").Alias("add")
    56  
    57  	// Required.
    58  	c.CmdClause.Flag("name", "The name of the SFTP logging object. Used as a primary key for API access").Short('n').Action(c.EndpointName.Set).StringVar(&c.EndpointName.Value)
    59  	c.RegisterFlag(argparser.StringFlagOpts{
    60  		Name:        argparser.FlagVersionName,
    61  		Description: argparser.FlagVersionDesc,
    62  		Dst:         &c.ServiceVersion.Value,
    63  		Required:    true,
    64  	})
    65  
    66  	// Optional.
    67  	c.RegisterAutoCloneFlag(argparser.AutoCloneFlagOpts{
    68  		Action: c.AutoClone.Set,
    69  		Dst:    &c.AutoClone.Value,
    70  	})
    71  	c.CmdClause.Flag("address", "The hostname or IPv4 address").Action(c.Address.Set).StringVar(&c.Address.Value)
    72  	common.CompressionCodec(c.CmdClause, &c.CompressionCodec)
    73  	common.Format(c.CmdClause, &c.Format)
    74  	common.FormatVersion(c.CmdClause, &c.FormatVersion)
    75  	common.GzipLevel(c.CmdClause, &c.GzipLevel)
    76  	common.MessageType(c.CmdClause, &c.MessageType)
    77  	c.CmdClause.Flag("password", "The password for the server. If both password and secret_key are passed, secret_key will be used in preference").Action(c.Password.Set).StringVar(&c.Password.Value)
    78  	c.CmdClause.Flag("path", "The path to upload logs to. The directory must exist on the SFTP server before logs can be saved to it").Action(c.Path.Set).StringVar(&c.Path.Value)
    79  	common.Period(c.CmdClause, &c.Period)
    80  	common.Placement(c.CmdClause, &c.Placement)
    81  	c.CmdClause.Flag("port", "The port number").Action(c.Port.Set).IntVar(&c.Port.Value)
    82  	common.PublicKey(c.CmdClause, &c.PublicKey)
    83  	common.ResponseCondition(c.CmdClause, &c.ResponseCondition)
    84  	c.CmdClause.Flag("secret-key", "The SSH private key for the server. If both password and secret_key are passed, secret_key will be used in preference").Action(c.SecretKey.Set).StringVar(&c.SecretKey.Value)
    85  	c.RegisterFlag(argparser.StringFlagOpts{
    86  		Name:        argparser.FlagServiceIDName,
    87  		Description: argparser.FlagServiceIDDesc,
    88  		Dst:         &g.Manifest.Flag.ServiceID,
    89  		Short:       's',
    90  	})
    91  	c.RegisterFlag(argparser.StringFlagOpts{
    92  		Action:      c.ServiceName.Set,
    93  		Name:        argparser.FlagServiceName,
    94  		Description: argparser.FlagServiceDesc,
    95  		Dst:         &c.ServiceName.Value,
    96  	})
    97  	c.CmdClause.Flag("ssh-known-hosts", "A list of host keys for all hosts we can connect to over SFTP").Action(c.SSHKnownHosts.Set).StringVar(&c.SSHKnownHosts.Value)
    98  	common.TimestampFormat(c.CmdClause, &c.TimestampFormat)
    99  	c.CmdClause.Flag("user", "The username for the server").Action(c.User.Set).StringVar(&c.User.Value)
   100  	return &c
   101  }
   102  
   103  // ConstructInput transforms values parsed from CLI flags into an object to be used by the API client library.
   104  func (c *CreateCommand) ConstructInput(serviceID string, serviceVersion int) (*fastly.CreateSFTPInput, error) {
   105  	var input fastly.CreateSFTPInput
   106  
   107  	input.ServiceID = serviceID
   108  	input.ServiceVersion = serviceVersion
   109  	if c.EndpointName.WasSet {
   110  		input.Name = &c.EndpointName.Value
   111  	}
   112  	if c.Address.WasSet {
   113  		input.Address = &c.Address.Value
   114  	}
   115  	if c.User.WasSet {
   116  		input.User = &c.User.Value
   117  	}
   118  	if c.SSHKnownHosts.WasSet {
   119  		input.SSHKnownHosts = &c.SSHKnownHosts.Value
   120  	}
   121  
   122  	// The following blocks enforces the mutual exclusivity of the
   123  	// CompressionCodec and GzipLevel flags.
   124  	if c.CompressionCodec.WasSet && c.GzipLevel.WasSet {
   125  		return nil, fmt.Errorf("error parsing arguments: the --compression-codec flag is mutually exclusive with the --gzip-level flag")
   126  	}
   127  
   128  	if c.Port.WasSet {
   129  		input.Port = &c.Port.Value
   130  	}
   131  
   132  	if c.Password.WasSet {
   133  		input.Password = &c.Password.Value
   134  	}
   135  
   136  	if c.PublicKey.WasSet {
   137  		input.PublicKey = &c.PublicKey.Value
   138  	}
   139  
   140  	if c.SecretKey.WasSet {
   141  		input.SecretKey = &c.SecretKey.Value
   142  	}
   143  
   144  	if c.Path.WasSet {
   145  		input.Path = &c.Path.Value
   146  	}
   147  
   148  	if c.Period.WasSet {
   149  		input.Period = &c.Period.Value
   150  	}
   151  
   152  	if c.Format.WasSet {
   153  		input.Format = &c.Format.Value
   154  	}
   155  
   156  	if c.FormatVersion.WasSet {
   157  		input.FormatVersion = &c.FormatVersion.Value
   158  	}
   159  
   160  	if c.GzipLevel.WasSet {
   161  		input.GzipLevel = &c.GzipLevel.Value
   162  	}
   163  
   164  	if c.MessageType.WasSet {
   165  		input.MessageType = &c.MessageType.Value
   166  	}
   167  
   168  	if c.ResponseCondition.WasSet {
   169  		input.ResponseCondition = &c.ResponseCondition.Value
   170  	}
   171  
   172  	if c.TimestampFormat.WasSet {
   173  		input.TimestampFormat = &c.TimestampFormat.Value
   174  	}
   175  
   176  	if c.Placement.WasSet {
   177  		input.Placement = &c.Placement.Value
   178  	}
   179  
   180  	if c.CompressionCodec.WasSet {
   181  		input.CompressionCodec = &c.CompressionCodec.Value
   182  	}
   183  
   184  	return &input, nil
   185  }
   186  
   187  // Exec invokes the application logic for the command.
   188  func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error {
   189  	serviceID, serviceVersion, err := argparser.ServiceDetails(argparser.ServiceDetailsOpts{
   190  		AutoCloneFlag:      c.AutoClone,
   191  		APIClient:          c.Globals.APIClient,
   192  		Manifest:           *c.Globals.Manifest,
   193  		Out:                out,
   194  		ServiceNameFlag:    c.ServiceName,
   195  		ServiceVersionFlag: c.ServiceVersion,
   196  		VerboseMode:        c.Globals.Flags.Verbose,
   197  	})
   198  	if err != nil {
   199  		c.Globals.ErrLog.AddWithContext(err, map[string]any{
   200  			"Service ID":      serviceID,
   201  			"Service Version": errors.ServiceVersion(serviceVersion),
   202  		})
   203  		return err
   204  	}
   205  
   206  	input, err := c.ConstructInput(serviceID, fastly.ToValue(serviceVersion.Number))
   207  	if err != nil {
   208  		c.Globals.ErrLog.Add(err)
   209  		return err
   210  	}
   211  
   212  	d, err := c.Globals.APIClient.CreateSFTP(input)
   213  	if err != nil {
   214  		c.Globals.ErrLog.Add(err)
   215  		return err
   216  	}
   217  
   218  	text.Success(out,
   219  		"Created SFTP logging endpoint %s (service %s version %d)",
   220  		fastly.ToValue(d.Name),
   221  		fastly.ToValue(d.ServiceID),
   222  		fastly.ToValue(d.ServiceVersion),
   223  	)
   224  	return nil
   225  }