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

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