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

     1  package sftp_test
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     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/sftp"
    11  	"github.com/fastly/cli/pkg/config"
    12  	"github.com/fastly/cli/pkg/errors"
    13  	"github.com/fastly/cli/pkg/global"
    14  	"github.com/fastly/cli/pkg/manifest"
    15  	"github.com/fastly/cli/pkg/mock"
    16  	"github.com/fastly/cli/pkg/testutil"
    17  )
    18  
    19  func TestCreateSFTPInput(t *testing.T) {
    20  	for _, testcase := range []struct {
    21  		name      string
    22  		cmd       *sftp.CreateCommand
    23  		want      *fastly.CreateSFTPInput
    24  		wantError string
    25  	}{
    26  		{
    27  			name: "required values set flag serviceID",
    28  			cmd:  createCommandRequired(),
    29  			want: &fastly.CreateSFTPInput{
    30  				ServiceID:      "123",
    31  				ServiceVersion: 4,
    32  				Name:           fastly.ToPointer("log"),
    33  				Address:        fastly.ToPointer("127.0.0.1"),
    34  				User:           fastly.ToPointer("user"),
    35  				SSHKnownHosts:  fastly.ToPointer(knownHosts()),
    36  			},
    37  		},
    38  		{
    39  			name: "all values set flag serviceID",
    40  			cmd:  createCommandAll(),
    41  			want: &fastly.CreateSFTPInput{
    42  				ServiceID:         "123",
    43  				ServiceVersion:    4,
    44  				Name:              fastly.ToPointer("log"),
    45  				Address:           fastly.ToPointer("127.0.0.1"),
    46  				Port:              fastly.ToPointer(80),
    47  				User:              fastly.ToPointer("user"),
    48  				Password:          fastly.ToPointer("password"),
    49  				PublicKey:         fastly.ToPointer(pgpPublicKey()),
    50  				SecretKey:         fastly.ToPointer(sshPrivateKey()),
    51  				SSHKnownHosts:     fastly.ToPointer(knownHosts()),
    52  				Path:              fastly.ToPointer("/log"),
    53  				Period:            fastly.ToPointer(3600),
    54  				FormatVersion:     fastly.ToPointer(2),
    55  				Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
    56  				ResponseCondition: fastly.ToPointer("Prevent default logging"),
    57  				MessageType:       fastly.ToPointer("classic"),
    58  				TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
    59  				Placement:         fastly.ToPointer("none"),
    60  				CompressionCodec:  fastly.ToPointer("zstd"),
    61  			},
    62  		},
    63  		{
    64  			name:      "error missing serviceID",
    65  			cmd:       createCommandMissingServiceID(),
    66  			want:      nil,
    67  			wantError: errors.ErrNoServiceID.Error(),
    68  		},
    69  	} {
    70  		t.Run(testcase.name, func(t *testing.T) {
    71  			var bs []byte
    72  			out := bytes.NewBuffer(bs)
    73  			verboseMode := true
    74  
    75  			serviceID, serviceVersion, err := argparser.ServiceDetails(argparser.ServiceDetailsOpts{
    76  				AutoCloneFlag:      testcase.cmd.AutoClone,
    77  				APIClient:          testcase.cmd.Globals.APIClient,
    78  				Manifest:           testcase.cmd.Manifest,
    79  				Out:                out,
    80  				ServiceVersionFlag: testcase.cmd.ServiceVersion,
    81  				VerboseMode:        verboseMode,
    82  			})
    83  
    84  			switch {
    85  			case err != nil && testcase.wantError == "":
    86  				t.Fatalf("unexpected error getting service details: %v", err)
    87  				return
    88  			case err != nil && testcase.wantError != "":
    89  				testutil.AssertErrorContains(t, err, testcase.wantError)
    90  				return
    91  			case err == nil && testcase.wantError != "":
    92  				t.Fatalf("expected error, have nil (service details: %s, %d)", serviceID, serviceVersion.Number)
    93  			case err == nil && testcase.wantError == "":
    94  				have, err := testcase.cmd.ConstructInput(serviceID, fastly.ToValue(serviceVersion.Number))
    95  				testutil.AssertErrorContains(t, err, testcase.wantError)
    96  				testutil.AssertEqual(t, testcase.want, have)
    97  			}
    98  		})
    99  	}
   100  }
   101  
   102  func TestUpdateSFTPInput(t *testing.T) {
   103  	scenarios := []struct {
   104  		name      string
   105  		cmd       *sftp.UpdateCommand
   106  		api       mock.API
   107  		want      *fastly.UpdateSFTPInput
   108  		wantError string
   109  	}{
   110  		{
   111  			name: "all values set flag serviceID",
   112  			cmd:  updateCommandAll(),
   113  			api: mock.API{
   114  				ListVersionsFn: testutil.ListVersions,
   115  				CloneVersionFn: testutil.CloneVersionResult(4),
   116  				GetSFTPFn:      getSFTPOK,
   117  			},
   118  			want: &fastly.UpdateSFTPInput{
   119  				ServiceID:         "123",
   120  				ServiceVersion:    4,
   121  				Name:              "log",
   122  				NewName:           fastly.ToPointer("new1"),
   123  				Address:           fastly.ToPointer("new2"),
   124  				Port:              fastly.ToPointer(81),
   125  				User:              fastly.ToPointer("new3"),
   126  				SSHKnownHosts:     fastly.ToPointer("new4"),
   127  				Password:          fastly.ToPointer("new5"),
   128  				PublicKey:         fastly.ToPointer("new6"),
   129  				SecretKey:         fastly.ToPointer("new7"),
   130  				Path:              fastly.ToPointer("new8"),
   131  				Period:            fastly.ToPointer(3601),
   132  				FormatVersion:     fastly.ToPointer(3),
   133  				GzipLevel:         fastly.ToPointer(0),
   134  				Format:            fastly.ToPointer("new9"),
   135  				ResponseCondition: fastly.ToPointer("new10"),
   136  				TimestampFormat:   fastly.ToPointer("new11"),
   137  				Placement:         fastly.ToPointer("new12"),
   138  				MessageType:       fastly.ToPointer("new13"),
   139  				CompressionCodec:  fastly.ToPointer("new14"),
   140  			},
   141  		},
   142  		{
   143  			name: "no updates",
   144  			cmd:  updateCommandNoUpdates(),
   145  			api: mock.API{
   146  				ListVersionsFn: testutil.ListVersions,
   147  				CloneVersionFn: testutil.CloneVersionResult(4),
   148  				GetSFTPFn:      getSFTPOK,
   149  			},
   150  			want: &fastly.UpdateSFTPInput{
   151  				ServiceID:      "123",
   152  				ServiceVersion: 4,
   153  				Name:           "log",
   154  			},
   155  		},
   156  		{
   157  			name:      "error missing serviceID",
   158  			cmd:       updateCommandMissingServiceID(),
   159  			want:      nil,
   160  			wantError: errors.ErrNoServiceID.Error(),
   161  		},
   162  	}
   163  	for testcaseIdx := range scenarios {
   164  		testcase := &scenarios[testcaseIdx]
   165  		t.Run(testcase.name, func(t *testing.T) {
   166  			testcase.cmd.Globals.APIClient = testcase.api
   167  
   168  			var bs []byte
   169  			out := bytes.NewBuffer(bs)
   170  			verboseMode := true
   171  
   172  			serviceID, serviceVersion, err := argparser.ServiceDetails(argparser.ServiceDetailsOpts{
   173  				AutoCloneFlag:      testcase.cmd.AutoClone,
   174  				APIClient:          testcase.api,
   175  				Manifest:           testcase.cmd.Manifest,
   176  				Out:                out,
   177  				ServiceVersionFlag: testcase.cmd.ServiceVersion,
   178  				VerboseMode:        verboseMode,
   179  			})
   180  
   181  			switch {
   182  			case err != nil && testcase.wantError == "":
   183  				t.Fatalf("unexpected error getting service details: %v", err)
   184  				return
   185  			case err != nil && testcase.wantError != "":
   186  				testutil.AssertErrorContains(t, err, testcase.wantError)
   187  				return
   188  			case err == nil && testcase.wantError != "":
   189  				t.Fatalf("expected error, have nil (service details: %s, %d)", serviceID, serviceVersion.Number)
   190  			case err == nil && testcase.wantError == "":
   191  				have, err := testcase.cmd.ConstructInput(serviceID, fastly.ToValue(serviceVersion.Number))
   192  				testutil.AssertErrorContains(t, err, testcase.wantError)
   193  				testutil.AssertEqual(t, testcase.want, have)
   194  			}
   195  		})
   196  	}
   197  }
   198  
   199  func createCommandRequired() *sftp.CreateCommand {
   200  	var b bytes.Buffer
   201  
   202  	g := global.Data{
   203  		Config: config.File{},
   204  		Env:    config.Environment{},
   205  		Output: &b,
   206  	}
   207  	g.APIClient, _ = mock.APIClient(mock.API{
   208  		ListVersionsFn: testutil.ListVersions,
   209  		CloneVersionFn: testutil.CloneVersionResult(4),
   210  	})("token", "endpoint", false)
   211  
   212  	return &sftp.CreateCommand{
   213  		Base: argparser.Base{
   214  			Globals: &g,
   215  		},
   216  		Manifest: manifest.Data{
   217  			Flag: manifest.Flag{
   218  				ServiceID: "123",
   219  			},
   220  		},
   221  		ServiceVersion: argparser.OptionalServiceVersion{
   222  			OptionalString: argparser.OptionalString{Value: "1"},
   223  		},
   224  		AutoClone: argparser.OptionalAutoClone{
   225  			OptionalBool: argparser.OptionalBool{
   226  				Optional: argparser.Optional{
   227  					WasSet: true,
   228  				},
   229  				Value: true,
   230  			},
   231  		},
   232  		EndpointName:  argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "log"},
   233  		Address:       argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "127.0.0.1"},
   234  		User:          argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "user"},
   235  		SSHKnownHosts: argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: knownHosts()},
   236  	}
   237  }
   238  
   239  func createCommandAll() *sftp.CreateCommand {
   240  	var b bytes.Buffer
   241  
   242  	g := global.Data{
   243  		Config: config.File{},
   244  		Env:    config.Environment{},
   245  		Output: &b,
   246  	}
   247  	g.APIClient, _ = mock.APIClient(mock.API{
   248  		ListVersionsFn: testutil.ListVersions,
   249  		CloneVersionFn: testutil.CloneVersionResult(4),
   250  	})("token", "endpoint", false)
   251  
   252  	return &sftp.CreateCommand{
   253  		Base: argparser.Base{
   254  			Globals: &g,
   255  		},
   256  		Manifest: manifest.Data{
   257  			Flag: manifest.Flag{
   258  				ServiceID: "123",
   259  			},
   260  		},
   261  		ServiceVersion: argparser.OptionalServiceVersion{
   262  			OptionalString: argparser.OptionalString{Value: "1"},
   263  		},
   264  		AutoClone: argparser.OptionalAutoClone{
   265  			OptionalBool: argparser.OptionalBool{
   266  				Optional: argparser.Optional{
   267  					WasSet: true,
   268  				},
   269  				Value: true,
   270  			},
   271  		},
   272  		EndpointName:      argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "log"},
   273  		Address:           argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "127.0.0.1"},
   274  		User:              argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "user"},
   275  		SSHKnownHosts:     argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: knownHosts()},
   276  		Port:              argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 80},
   277  		Password:          argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "password"},
   278  		PublicKey:         argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: pgpPublicKey()},
   279  		SecretKey:         argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: sshPrivateKey()},
   280  		Path:              argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "/log"},
   281  		Period:            argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 3600},
   282  		Format:            argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: `%h %l %u %t "%r" %>s %b`},
   283  		FormatVersion:     argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 2},
   284  		MessageType:       argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "classic"},
   285  		ResponseCondition: argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "Prevent default logging"},
   286  		TimestampFormat:   argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "%Y-%m-%dT%H:%M:%S.000"},
   287  		Placement:         argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "none"},
   288  		CompressionCodec:  argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "zstd"},
   289  	}
   290  }
   291  
   292  func createCommandMissingServiceID() *sftp.CreateCommand {
   293  	res := createCommandAll()
   294  	res.Manifest = manifest.Data{}
   295  	return res
   296  }
   297  
   298  func updateCommandNoUpdates() *sftp.UpdateCommand {
   299  	var b bytes.Buffer
   300  
   301  	g := global.Data{
   302  		Config: config.File{},
   303  		Env:    config.Environment{},
   304  		Output: &b,
   305  	}
   306  
   307  	return &sftp.UpdateCommand{
   308  		Base: argparser.Base{
   309  			Globals: &g,
   310  		},
   311  		Manifest: manifest.Data{
   312  			Flag: manifest.Flag{
   313  				ServiceID: "123",
   314  			},
   315  		},
   316  		EndpointName: "log",
   317  		ServiceVersion: argparser.OptionalServiceVersion{
   318  			OptionalString: argparser.OptionalString{Value: "1"},
   319  		},
   320  		AutoClone: argparser.OptionalAutoClone{
   321  			OptionalBool: argparser.OptionalBool{
   322  				Optional: argparser.Optional{
   323  					WasSet: true,
   324  				},
   325  				Value: true,
   326  			},
   327  		},
   328  	}
   329  }
   330  
   331  func updateCommandAll() *sftp.UpdateCommand {
   332  	var b bytes.Buffer
   333  
   334  	g := global.Data{
   335  		Config: config.File{},
   336  		Env:    config.Environment{},
   337  		Output: &b,
   338  	}
   339  
   340  	return &sftp.UpdateCommand{
   341  		Base: argparser.Base{
   342  			Globals: &g,
   343  		},
   344  		Manifest: manifest.Data{
   345  			Flag: manifest.Flag{
   346  				ServiceID: "123",
   347  			},
   348  		},
   349  		EndpointName: "log",
   350  		ServiceVersion: argparser.OptionalServiceVersion{
   351  			OptionalString: argparser.OptionalString{Value: "1"},
   352  		},
   353  		AutoClone: argparser.OptionalAutoClone{
   354  			OptionalBool: argparser.OptionalBool{
   355  				Optional: argparser.Optional{
   356  					WasSet: true,
   357  				},
   358  				Value: true,
   359  			},
   360  		},
   361  		NewName:           argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new1"},
   362  		Address:           argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new2"},
   363  		User:              argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new3"},
   364  		SSHKnownHosts:     argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new4"},
   365  		Port:              argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 81},
   366  		Password:          argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new5"},
   367  		PublicKey:         argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new6"},
   368  		SecretKey:         argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new7"},
   369  		Path:              argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new8"},
   370  		Period:            argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 3601},
   371  		Format:            argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new9"},
   372  		FormatVersion:     argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 3},
   373  		GzipLevel:         argparser.OptionalInt{Optional: argparser.Optional{WasSet: true}, Value: 0},
   374  		ResponseCondition: argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new10"},
   375  		TimestampFormat:   argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new11"},
   376  		Placement:         argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new12"},
   377  		MessageType:       argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new13"},
   378  		CompressionCodec:  argparser.OptionalString{Optional: argparser.Optional{WasSet: true}, Value: "new14"},
   379  	}
   380  }
   381  
   382  func updateCommandMissingServiceID() *sftp.UpdateCommand {
   383  	res := updateCommandAll()
   384  	res.Manifest = manifest.Data{}
   385  	return res
   386  }