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

     1  package https_test
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/fastly/go-fastly/v9/fastly"
    11  
    12  	"github.com/fastly/cli/pkg/app"
    13  	"github.com/fastly/cli/pkg/global"
    14  	"github.com/fastly/cli/pkg/mock"
    15  	"github.com/fastly/cli/pkg/testutil"
    16  )
    17  
    18  func TestHTTPSCreate(t *testing.T) {
    19  	args := testutil.Args
    20  	scenarios := []struct {
    21  		args       []string
    22  		api        mock.API
    23  		wantError  string
    24  		wantOutput string
    25  	}{
    26  		{
    27  			args: args("logging https create --service-id 123 --version 1 --name log --url example.com --autoclone"),
    28  			api: mock.API{
    29  				ListVersionsFn: testutil.ListVersions,
    30  				CloneVersionFn: testutil.CloneVersionResult(4),
    31  				CreateHTTPSFn:  createHTTPSOK,
    32  			},
    33  			wantOutput: "Created HTTPS logging endpoint log (service 123 version 4)",
    34  		},
    35  		{
    36  			args: args("logging https create --service-id 123 --version 1 --name log --url example.com --autoclone"),
    37  			api: mock.API{
    38  				ListVersionsFn: testutil.ListVersions,
    39  				CloneVersionFn: testutil.CloneVersionResult(4),
    40  				CreateHTTPSFn:  createHTTPSError,
    41  			},
    42  			wantError: errTest.Error(),
    43  		},
    44  	}
    45  	for testcaseIdx := range scenarios {
    46  		testcase := &scenarios[testcaseIdx]
    47  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
    48  			var stdout bytes.Buffer
    49  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
    50  				opts := testutil.MockGlobalData(testcase.args, &stdout)
    51  				opts.APIClientFactory = mock.APIClient(testcase.api)
    52  				return opts, nil
    53  			}
    54  			err := app.Run(testcase.args, nil)
    55  			testutil.AssertErrorContains(t, err, testcase.wantError)
    56  			testutil.AssertStringContains(t, stdout.String(), testcase.wantOutput)
    57  		})
    58  	}
    59  }
    60  
    61  func TestHTTPSList(t *testing.T) {
    62  	args := testutil.Args
    63  	scenarios := []struct {
    64  		args       []string
    65  		api        mock.API
    66  		wantError  string
    67  		wantOutput string
    68  	}{
    69  		{
    70  			args: args("logging https list --service-id 123 --version 1"),
    71  			api: mock.API{
    72  				ListVersionsFn: testutil.ListVersions,
    73  				ListHTTPSFn:    listHTTPSsOK,
    74  			},
    75  			wantOutput: listHTTPSsShortOutput,
    76  		},
    77  		{
    78  			args: args("logging https list --service-id 123 --version 1 --verbose"),
    79  			api: mock.API{
    80  				ListVersionsFn: testutil.ListVersions,
    81  				ListHTTPSFn:    listHTTPSsOK,
    82  			},
    83  			wantOutput: listHTTPSsVerboseOutput,
    84  		},
    85  		{
    86  			args: args("logging https list --service-id 123 --version 1 -v"),
    87  			api: mock.API{
    88  				ListVersionsFn: testutil.ListVersions,
    89  				ListHTTPSFn:    listHTTPSsOK,
    90  			},
    91  			wantOutput: listHTTPSsVerboseOutput,
    92  		},
    93  		{
    94  			args: args("logging https --verbose list --service-id 123 --version 1"),
    95  			api: mock.API{
    96  				ListVersionsFn: testutil.ListVersions,
    97  				ListHTTPSFn:    listHTTPSsOK,
    98  			},
    99  			wantOutput: listHTTPSsVerboseOutput,
   100  		},
   101  		{
   102  			args: args("logging -v https list --service-id 123 --version 1"),
   103  			api: mock.API{
   104  				ListVersionsFn: testutil.ListVersions,
   105  				ListHTTPSFn:    listHTTPSsOK,
   106  			},
   107  			wantOutput: listHTTPSsVerboseOutput,
   108  		},
   109  		{
   110  			args: args("logging https list --service-id 123 --version 1"),
   111  			api: mock.API{
   112  				ListVersionsFn: testutil.ListVersions,
   113  				ListHTTPSFn:    listHTTPSsError,
   114  			},
   115  			wantError: errTest.Error(),
   116  		},
   117  	}
   118  	for testcaseIdx := range scenarios {
   119  		testcase := &scenarios[testcaseIdx]
   120  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   121  			var stdout bytes.Buffer
   122  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   123  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   124  				opts.APIClientFactory = mock.APIClient(testcase.api)
   125  				return opts, nil
   126  			}
   127  			err := app.Run(testcase.args, nil)
   128  			testutil.AssertErrorContains(t, err, testcase.wantError)
   129  			testutil.AssertString(t, testcase.wantOutput, stdout.String())
   130  		})
   131  	}
   132  }
   133  
   134  func TestHTTPSDescribe(t *testing.T) {
   135  	args := testutil.Args
   136  	scenarios := []struct {
   137  		args       []string
   138  		api        mock.API
   139  		wantError  string
   140  		wantOutput string
   141  	}{
   142  		{
   143  			args:      args("logging https describe --service-id 123 --version 1"),
   144  			wantError: "error parsing arguments: required flag --name not provided",
   145  		},
   146  		{
   147  			args: args("logging https describe --service-id 123 --version 1 --name logs"),
   148  			api: mock.API{
   149  				ListVersionsFn: testutil.ListVersions,
   150  				GetHTTPSFn:     getHTTPSError,
   151  			},
   152  			wantError: errTest.Error(),
   153  		},
   154  		{
   155  			args: args("logging https describe --service-id 123 --version 1 --name logs"),
   156  			api: mock.API{
   157  				ListVersionsFn: testutil.ListVersions,
   158  				GetHTTPSFn:     getHTTPSOK,
   159  			},
   160  			wantOutput: describeHTTPSOutput,
   161  		},
   162  	}
   163  	for testcaseIdx := range scenarios {
   164  		testcase := &scenarios[testcaseIdx]
   165  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   166  			var stdout bytes.Buffer
   167  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   168  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   169  				opts.APIClientFactory = mock.APIClient(testcase.api)
   170  				return opts, nil
   171  			}
   172  			err := app.Run(testcase.args, nil)
   173  			testutil.AssertErrorContains(t, err, testcase.wantError)
   174  			testutil.AssertString(t, testcase.wantOutput, stdout.String())
   175  		})
   176  	}
   177  }
   178  
   179  func TestHTTPSUpdate(t *testing.T) {
   180  	args := testutil.Args
   181  	scenarios := []struct {
   182  		args       []string
   183  		api        mock.API
   184  		wantError  string
   185  		wantOutput string
   186  	}{
   187  		{
   188  			args:      args("logging https update --service-id 123 --version 1 --new-name log"),
   189  			wantError: "error parsing arguments: required flag --name not provided",
   190  		},
   191  		{
   192  			args: args("logging https update --service-id 123 --version 1 --name logs --new-name log --autoclone"),
   193  			api: mock.API{
   194  				ListVersionsFn: testutil.ListVersions,
   195  				CloneVersionFn: testutil.CloneVersionResult(4),
   196  				UpdateHTTPSFn:  updateHTTPSError,
   197  			},
   198  			wantError: errTest.Error(),
   199  		},
   200  		{
   201  			args: args("logging https update --service-id 123 --version 1 --name logs --new-name log --autoclone"),
   202  			api: mock.API{
   203  				ListVersionsFn: testutil.ListVersions,
   204  				CloneVersionFn: testutil.CloneVersionResult(4),
   205  				UpdateHTTPSFn:  updateHTTPSOK,
   206  			},
   207  			wantOutput: "Updated HTTPS logging endpoint log (service 123 version 4)",
   208  		},
   209  	}
   210  	for testcaseIdx := range scenarios {
   211  		testcase := &scenarios[testcaseIdx]
   212  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   213  			var stdout bytes.Buffer
   214  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   215  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   216  				opts.APIClientFactory = mock.APIClient(testcase.api)
   217  				return opts, nil
   218  			}
   219  			err := app.Run(testcase.args, nil)
   220  			testutil.AssertErrorContains(t, err, testcase.wantError)
   221  			testutil.AssertStringContains(t, stdout.String(), testcase.wantOutput)
   222  		})
   223  	}
   224  }
   225  
   226  func TestHTTPSDelete(t *testing.T) {
   227  	args := testutil.Args
   228  	scenarios := []struct {
   229  		args       []string
   230  		api        mock.API
   231  		wantError  string
   232  		wantOutput string
   233  	}{
   234  		{
   235  			args:      args("logging https delete --service-id 123 --version 1"),
   236  			wantError: "error parsing arguments: required flag --name not provided",
   237  		},
   238  		{
   239  			args: args("logging https delete --service-id 123 --version 1 --name logs --autoclone"),
   240  			api: mock.API{
   241  				ListVersionsFn: testutil.ListVersions,
   242  				CloneVersionFn: testutil.CloneVersionResult(4),
   243  				DeleteHTTPSFn:  deleteHTTPSError,
   244  			},
   245  			wantError: errTest.Error(),
   246  		},
   247  		{
   248  			args: args("logging https delete --service-id 123 --version 1 --name logs --autoclone"),
   249  			api: mock.API{
   250  				ListVersionsFn: testutil.ListVersions,
   251  				CloneVersionFn: testutil.CloneVersionResult(4),
   252  				DeleteHTTPSFn:  deleteHTTPSOK,
   253  			},
   254  			wantOutput: "Deleted HTTPS logging endpoint logs (service 123 version 4)",
   255  		},
   256  	}
   257  	for testcaseIdx := range scenarios {
   258  		testcase := &scenarios[testcaseIdx]
   259  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   260  			var stdout bytes.Buffer
   261  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   262  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   263  				opts.APIClientFactory = mock.APIClient(testcase.api)
   264  				return opts, nil
   265  			}
   266  			err := app.Run(testcase.args, nil)
   267  			testutil.AssertErrorContains(t, err, testcase.wantError)
   268  			testutil.AssertStringContains(t, stdout.String(), testcase.wantOutput)
   269  		})
   270  	}
   271  }
   272  
   273  var errTest = errors.New("fixture error")
   274  
   275  func createHTTPSOK(i *fastly.CreateHTTPSInput) (*fastly.HTTPS, error) {
   276  	return &fastly.HTTPS{
   277  		ServiceID:         fastly.ToPointer(i.ServiceID),
   278  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   279  		Name:              fastly.ToPointer("log"),
   280  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   281  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   282  		URL:               fastly.ToPointer("example.com"),
   283  		RequestMaxEntries: fastly.ToPointer(2),
   284  		RequestMaxBytes:   fastly.ToPointer(2),
   285  		ContentType:       fastly.ToPointer("application/json"),
   286  		HeaderName:        fastly.ToPointer("name"),
   287  		HeaderValue:       fastly.ToPointer("value"),
   288  		Method:            fastly.ToPointer("GET"),
   289  		JSONFormat:        fastly.ToPointer("1"),
   290  		Placement:         fastly.ToPointer("none"),
   291  		TLSCACert:         fastly.ToPointer("-----BEGIN CERTIFICATE-----foo"),
   292  		TLSClientCert:     fastly.ToPointer("-----BEGIN CERTIFICATE-----bar"),
   293  		TLSClientKey:      fastly.ToPointer("-----BEGIN PRIVATE KEY-----bar"),
   294  		TLSHostname:       fastly.ToPointer("example.com"),
   295  		MessageType:       fastly.ToPointer("classic"),
   296  		FormatVersion:     fastly.ToPointer(2),
   297  	}, nil
   298  }
   299  
   300  func createHTTPSError(_ *fastly.CreateHTTPSInput) (*fastly.HTTPS, error) {
   301  	return nil, errTest
   302  }
   303  
   304  func listHTTPSsOK(i *fastly.ListHTTPSInput) ([]*fastly.HTTPS, error) {
   305  	return []*fastly.HTTPS{
   306  		{
   307  			ServiceID:         fastly.ToPointer(i.ServiceID),
   308  			ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   309  			Name:              fastly.ToPointer("logs"),
   310  			ResponseCondition: fastly.ToPointer("Prevent default logging"),
   311  			Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   312  			URL:               fastly.ToPointer("example.com"),
   313  			RequestMaxEntries: fastly.ToPointer(2),
   314  			RequestMaxBytes:   fastly.ToPointer(2),
   315  			ContentType:       fastly.ToPointer("application/json"),
   316  			HeaderName:        fastly.ToPointer("name"),
   317  			HeaderValue:       fastly.ToPointer("value"),
   318  			Method:            fastly.ToPointer("GET"),
   319  			JSONFormat:        fastly.ToPointer("1"),
   320  			Placement:         fastly.ToPointer("none"),
   321  			TLSCACert:         fastly.ToPointer("-----BEGIN CERTIFICATE-----foo"),
   322  			TLSClientCert:     fastly.ToPointer("-----BEGIN CERTIFICATE-----bar"),
   323  			TLSClientKey:      fastly.ToPointer("-----BEGIN PRIVATE KEY-----bar"),
   324  			TLSHostname:       fastly.ToPointer("example.com"),
   325  			MessageType:       fastly.ToPointer("classic"),
   326  			FormatVersion:     fastly.ToPointer(2),
   327  		},
   328  		{
   329  			ServiceID:         fastly.ToPointer(i.ServiceID),
   330  			ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   331  			Name:              fastly.ToPointer("analytics"),
   332  			ResponseCondition: fastly.ToPointer("Prevent default logging"),
   333  			Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   334  			URL:               fastly.ToPointer("analytics.example.com"),
   335  			RequestMaxEntries: fastly.ToPointer(2),
   336  			RequestMaxBytes:   fastly.ToPointer(2),
   337  			ContentType:       fastly.ToPointer("application/json"),
   338  			HeaderName:        fastly.ToPointer("name"),
   339  			HeaderValue:       fastly.ToPointer("value"),
   340  			Method:            fastly.ToPointer("GET"),
   341  			JSONFormat:        fastly.ToPointer("1"),
   342  			Placement:         fastly.ToPointer("none"),
   343  			TLSCACert:         fastly.ToPointer("-----BEGIN CERTIFICATE-----foo"),
   344  			TLSClientCert:     fastly.ToPointer("-----BEGIN CERTIFICATE-----bar"),
   345  			TLSClientKey:      fastly.ToPointer("-----BEGIN PRIVATE KEY-----bar"),
   346  			TLSHostname:       fastly.ToPointer("example.com"),
   347  			MessageType:       fastly.ToPointer("classic"),
   348  			FormatVersion:     fastly.ToPointer(2),
   349  		},
   350  	}, nil
   351  }
   352  
   353  func listHTTPSsError(_ *fastly.ListHTTPSInput) ([]*fastly.HTTPS, error) {
   354  	return nil, errTest
   355  }
   356  
   357  var listHTTPSsShortOutput = strings.TrimSpace(`
   358  SERVICE  VERSION  NAME
   359  123      1        logs
   360  123      1        analytics
   361  `) + "\n"
   362  
   363  var listHTTPSsVerboseOutput = strings.TrimSpace(`
   364  Fastly API endpoint: https://api.fastly.com
   365  Fastly API token provided via config file (profile: user)
   366  
   367  Service ID (via --service-id): 123
   368  
   369  Version: 1
   370  	HTTPS 1/2
   371  		Service ID: 123
   372  		Version: 1
   373  		Name: logs
   374  		URL: example.com
   375  		Content type: application/json
   376  		Header name: name
   377  		Header value: value
   378  		Method: GET
   379  		JSON format: 1
   380  		TLS CA certificate: -----BEGIN CERTIFICATE-----foo
   381  		TLS client certificate: -----BEGIN CERTIFICATE-----bar
   382  		TLS client key: -----BEGIN PRIVATE KEY-----bar
   383  		TLS hostname: example.com
   384  		Request max entries: 2
   385  		Request max bytes: 2
   386  		Message type: classic
   387  		Format: %h %l %u %t "%r" %>s %b
   388  		Format version: 2
   389  		Response condition: Prevent default logging
   390  		Placement: none
   391  	HTTPS 2/2
   392  		Service ID: 123
   393  		Version: 1
   394  		Name: analytics
   395  		URL: analytics.example.com
   396  		Content type: application/json
   397  		Header name: name
   398  		Header value: value
   399  		Method: GET
   400  		JSON format: 1
   401  		TLS CA certificate: -----BEGIN CERTIFICATE-----foo
   402  		TLS client certificate: -----BEGIN CERTIFICATE-----bar
   403  		TLS client key: -----BEGIN PRIVATE KEY-----bar
   404  		TLS hostname: example.com
   405  		Request max entries: 2
   406  		Request max bytes: 2
   407  		Message type: classic
   408  		Format: %h %l %u %t "%r" %>s %b
   409  		Format version: 2
   410  		Response condition: Prevent default logging
   411  		Placement: none
   412  `) + "\n\n"
   413  
   414  func getHTTPSOK(i *fastly.GetHTTPSInput) (*fastly.HTTPS, error) {
   415  	return &fastly.HTTPS{
   416  		ServiceID:         fastly.ToPointer(i.ServiceID),
   417  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   418  		Name:              fastly.ToPointer("log"),
   419  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   420  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   421  		URL:               fastly.ToPointer("example.com"),
   422  		RequestMaxEntries: fastly.ToPointer(2),
   423  		RequestMaxBytes:   fastly.ToPointer(2),
   424  		ContentType:       fastly.ToPointer("application/json"),
   425  		HeaderName:        fastly.ToPointer("name"),
   426  		HeaderValue:       fastly.ToPointer("value"),
   427  		Method:            fastly.ToPointer("GET"),
   428  		JSONFormat:        fastly.ToPointer("1"),
   429  		Placement:         fastly.ToPointer("none"),
   430  		TLSCACert:         fastly.ToPointer("-----BEGIN CERTIFICATE-----foo"),
   431  		TLSClientCert:     fastly.ToPointer("-----BEGIN CERTIFICATE-----bar"),
   432  		TLSClientKey:      fastly.ToPointer("-----BEGIN PRIVATE KEY-----bar"),
   433  		TLSHostname:       fastly.ToPointer("example.com"),
   434  		MessageType:       fastly.ToPointer("classic"),
   435  		FormatVersion:     fastly.ToPointer(2),
   436  	}, nil
   437  }
   438  
   439  func getHTTPSError(_ *fastly.GetHTTPSInput) (*fastly.HTTPS, error) {
   440  	return nil, errTest
   441  }
   442  
   443  var describeHTTPSOutput = "\n" + strings.TrimSpace(`
   444  Content type: application/json
   445  Format: %h %l %u %t "%r" %>s %b
   446  Format version: 2
   447  Header name: name
   448  Header value: value
   449  JSON format: 1
   450  Message type: classic
   451  Method: GET
   452  Name: log
   453  Placement: none
   454  Request max bytes: 2
   455  Request max entries: 2
   456  Response condition: Prevent default logging
   457  Service ID: 123
   458  TLS CA certificate: -----BEGIN CERTIFICATE-----foo
   459  TLS client certificate: -----BEGIN CERTIFICATE-----bar
   460  TLS client key: -----BEGIN PRIVATE KEY-----bar
   461  TLS hostname: example.com
   462  URL: example.com
   463  Version: 1
   464  `) + "\n"
   465  
   466  func updateHTTPSOK(i *fastly.UpdateHTTPSInput) (*fastly.HTTPS, error) {
   467  	return &fastly.HTTPS{
   468  		ServiceID:         fastly.ToPointer(i.ServiceID),
   469  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   470  		Name:              fastly.ToPointer("log"),
   471  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   472  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   473  		URL:               fastly.ToPointer("example.com"),
   474  		RequestMaxEntries: fastly.ToPointer(2),
   475  		RequestMaxBytes:   fastly.ToPointer(2),
   476  		ContentType:       fastly.ToPointer("application/json"),
   477  		HeaderName:        fastly.ToPointer("name"),
   478  		HeaderValue:       fastly.ToPointer("value"),
   479  		Method:            fastly.ToPointer("GET"),
   480  		JSONFormat:        fastly.ToPointer("1"),
   481  		Placement:         fastly.ToPointer("none"),
   482  		TLSCACert:         fastly.ToPointer("-----BEGIN CERTIFICATE-----foo"),
   483  		TLSClientCert:     fastly.ToPointer("-----BEGIN CERTIFICATE-----bar"),
   484  		TLSClientKey:      fastly.ToPointer("-----BEGIN PRIVATE KEY-----bar"),
   485  		TLSHostname:       fastly.ToPointer("example.com"),
   486  		MessageType:       fastly.ToPointer("classic"),
   487  		FormatVersion:     fastly.ToPointer(2),
   488  	}, nil
   489  }
   490  
   491  func updateHTTPSError(_ *fastly.UpdateHTTPSInput) (*fastly.HTTPS, error) {
   492  	return nil, errTest
   493  }
   494  
   495  func deleteHTTPSOK(_ *fastly.DeleteHTTPSInput) error {
   496  	return nil
   497  }
   498  
   499  func deleteHTTPSError(_ *fastly.DeleteHTTPSInput) error {
   500  	return errTest
   501  }