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 }