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

     1  package cloudfiles_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 TestCloudfilesCreate(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 cloudfiles create --service-id 123 --version 1 --name log --user username --bucket log --access-key foo --autoclone"),
    28  			api: mock.API{
    29  				ListVersionsFn:     testutil.ListVersions,
    30  				CloneVersionFn:     testutil.CloneVersionResult(4),
    31  				CreateCloudfilesFn: createCloudfilesOK,
    32  			},
    33  			wantOutput: "Created Cloudfiles logging endpoint log (service 123 version 4)",
    34  		},
    35  		{
    36  			args: args("logging cloudfiles create --service-id 123 --version 1 --name log --user username --bucket log --access-key foo --autoclone"),
    37  			api: mock.API{
    38  				ListVersionsFn:     testutil.ListVersions,
    39  				CloneVersionFn:     testutil.CloneVersionResult(4),
    40  				CreateCloudfilesFn: createCloudfilesError,
    41  			},
    42  			wantError: errTest.Error(),
    43  		},
    44  		{
    45  			args: args("logging cloudfiles create --service-id 123 --version 1 --name log --user username --bucket log --access-key foo --compression-codec zstd --gzip-level 9 --autoclone"),
    46  			api: mock.API{
    47  				ListVersionsFn: testutil.ListVersions,
    48  				CloneVersionFn: testutil.CloneVersionResult(4),
    49  			},
    50  			wantError: "error parsing arguments: the --compression-codec flag is mutually exclusive with the --gzip-level flag",
    51  		},
    52  	}
    53  	for testcaseIdx := range scenarios {
    54  		testcase := &scenarios[testcaseIdx]
    55  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
    56  			var stdout bytes.Buffer
    57  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
    58  				opts := testutil.MockGlobalData(testcase.args, &stdout)
    59  				opts.APIClientFactory = mock.APIClient(testcase.api)
    60  				return opts, nil
    61  			}
    62  			err := app.Run(testcase.args, nil)
    63  			testutil.AssertErrorContains(t, err, testcase.wantError)
    64  			testutil.AssertStringContains(t, stdout.String(), testcase.wantOutput)
    65  		})
    66  	}
    67  }
    68  
    69  func TestCloudfilesList(t *testing.T) {
    70  	args := testutil.Args
    71  	scenarios := []struct {
    72  		args       []string
    73  		api        mock.API
    74  		wantError  string
    75  		wantOutput string
    76  	}{
    77  		{
    78  			args: args("logging cloudfiles list --service-id 123 --version 1"),
    79  			api: mock.API{
    80  				ListVersionsFn:   testutil.ListVersions,
    81  				ListCloudfilesFn: listCloudfilesOK,
    82  			},
    83  			wantOutput: listCloudfilesShortOutput,
    84  		},
    85  		{
    86  			args: args("logging cloudfiles list --service-id 123 --version 1 --verbose"),
    87  			api: mock.API{
    88  				ListVersionsFn:   testutil.ListVersions,
    89  				ListCloudfilesFn: listCloudfilesOK,
    90  			},
    91  			wantOutput: listCloudfilesVerboseOutput,
    92  		},
    93  		{
    94  			args: args("logging cloudfiles list --service-id 123 --version 1 -v"),
    95  			api: mock.API{
    96  				ListVersionsFn:   testutil.ListVersions,
    97  				ListCloudfilesFn: listCloudfilesOK,
    98  			},
    99  			wantOutput: listCloudfilesVerboseOutput,
   100  		},
   101  		{
   102  			args: args("logging cloudfiles --verbose list --service-id 123 --version 1"),
   103  			api: mock.API{
   104  				ListVersionsFn:   testutil.ListVersions,
   105  				ListCloudfilesFn: listCloudfilesOK,
   106  			},
   107  			wantOutput: listCloudfilesVerboseOutput,
   108  		},
   109  		{
   110  			args: args("logging -v cloudfiles list --service-id 123 --version 1"),
   111  			api: mock.API{
   112  				ListVersionsFn:   testutil.ListVersions,
   113  				ListCloudfilesFn: listCloudfilesOK,
   114  			},
   115  			wantOutput: listCloudfilesVerboseOutput,
   116  		},
   117  		{
   118  			args: args("logging cloudfiles list --service-id 123 --version 1"),
   119  			api: mock.API{
   120  				ListVersionsFn:   testutil.ListVersions,
   121  				ListCloudfilesFn: listCloudfilesError,
   122  			},
   123  			wantError: errTest.Error(),
   124  		},
   125  	}
   126  	for testcaseIdx := range scenarios {
   127  		testcase := &scenarios[testcaseIdx]
   128  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   129  			var stdout bytes.Buffer
   130  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   131  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   132  				opts.APIClientFactory = mock.APIClient(testcase.api)
   133  				return opts, nil
   134  			}
   135  			err := app.Run(testcase.args, nil)
   136  			testutil.AssertErrorContains(t, err, testcase.wantError)
   137  			testutil.AssertString(t, testcase.wantOutput, stdout.String())
   138  		})
   139  	}
   140  }
   141  
   142  func TestCloudfilesDescribe(t *testing.T) {
   143  	args := testutil.Args
   144  	scenarios := []struct {
   145  		args       []string
   146  		api        mock.API
   147  		wantError  string
   148  		wantOutput string
   149  	}{
   150  		{
   151  			args:      args("logging cloudfiles describe --service-id 123 --version 1"),
   152  			wantError: "error parsing arguments: required flag --name not provided",
   153  		},
   154  		{
   155  			args: args("logging cloudfiles describe --service-id 123 --version 1 --name logs"),
   156  			api: mock.API{
   157  				ListVersionsFn:  testutil.ListVersions,
   158  				GetCloudfilesFn: getCloudfilesError,
   159  			},
   160  			wantError: errTest.Error(),
   161  		},
   162  		{
   163  			args: args("logging cloudfiles describe --service-id 123 --version 1 --name logs"),
   164  			api: mock.API{
   165  				ListVersionsFn:  testutil.ListVersions,
   166  				GetCloudfilesFn: getCloudfilesOK,
   167  			},
   168  			wantOutput: describeCloudfilesOutput,
   169  		},
   170  	}
   171  	for testcaseIdx := range scenarios {
   172  		testcase := &scenarios[testcaseIdx]
   173  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   174  			var stdout bytes.Buffer
   175  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   176  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   177  				opts.APIClientFactory = mock.APIClient(testcase.api)
   178  				return opts, nil
   179  			}
   180  			err := app.Run(testcase.args, nil)
   181  			testutil.AssertErrorContains(t, err, testcase.wantError)
   182  			testutil.AssertString(t, testcase.wantOutput, stdout.String())
   183  		})
   184  	}
   185  }
   186  
   187  func TestCloudfilesUpdate(t *testing.T) {
   188  	args := testutil.Args
   189  	scenarios := []struct {
   190  		args       []string
   191  		api        mock.API
   192  		wantError  string
   193  		wantOutput string
   194  	}{
   195  		{
   196  			args:      args("logging cloudfiles update --service-id 123 --version 1 --new-name log"),
   197  			wantError: "error parsing arguments: required flag --name not provided",
   198  		},
   199  		{
   200  			args: args("logging cloudfiles update --service-id 123 --version 1 --name logs --new-name log --autoclone"),
   201  			api: mock.API{
   202  				ListVersionsFn:     testutil.ListVersions,
   203  				CloneVersionFn:     testutil.CloneVersionResult(4),
   204  				UpdateCloudfilesFn: updateCloudfilesError,
   205  			},
   206  			wantError: errTest.Error(),
   207  		},
   208  		{
   209  			args: args("logging cloudfiles update --service-id 123 --version 1 --name logs --new-name log --autoclone"),
   210  			api: mock.API{
   211  				ListVersionsFn:     testutil.ListVersions,
   212  				CloneVersionFn:     testutil.CloneVersionResult(4),
   213  				UpdateCloudfilesFn: updateCloudfilesOK,
   214  			},
   215  			wantOutput: "Updated Cloudfiles logging endpoint log (service 123 version 4)",
   216  		},
   217  	}
   218  	for testcaseIdx := range scenarios {
   219  		testcase := &scenarios[testcaseIdx]
   220  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   221  			var stdout bytes.Buffer
   222  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   223  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   224  				opts.APIClientFactory = mock.APIClient(testcase.api)
   225  				return opts, nil
   226  			}
   227  			err := app.Run(testcase.args, nil)
   228  			testutil.AssertErrorContains(t, err, testcase.wantError)
   229  			testutil.AssertStringContains(t, stdout.String(), testcase.wantOutput)
   230  		})
   231  	}
   232  }
   233  
   234  func TestCloudfilesDelete(t *testing.T) {
   235  	args := testutil.Args
   236  	scenarios := []struct {
   237  		args       []string
   238  		api        mock.API
   239  		wantError  string
   240  		wantOutput string
   241  	}{
   242  		{
   243  			args:      args("logging cloudfiles delete --service-id 123 --version 1"),
   244  			wantError: "error parsing arguments: required flag --name not provided",
   245  		},
   246  		{
   247  			args: args("logging cloudfiles delete --service-id 123 --version 1 --name logs --autoclone"),
   248  			api: mock.API{
   249  				ListVersionsFn:     testutil.ListVersions,
   250  				CloneVersionFn:     testutil.CloneVersionResult(4),
   251  				DeleteCloudfilesFn: deleteCloudfilesError,
   252  			},
   253  			wantError: errTest.Error(),
   254  		},
   255  		{
   256  			args: args("logging cloudfiles delete --service-id 123 --version 1 --name logs --autoclone"),
   257  			api: mock.API{
   258  				ListVersionsFn:     testutil.ListVersions,
   259  				CloneVersionFn:     testutil.CloneVersionResult(4),
   260  				DeleteCloudfilesFn: deleteCloudfilesOK,
   261  			},
   262  			wantOutput: "Deleted Cloudfiles logging endpoint logs (service 123 version 4)",
   263  		},
   264  	}
   265  	for testcaseIdx := range scenarios {
   266  		testcase := &scenarios[testcaseIdx]
   267  		t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
   268  			var stdout bytes.Buffer
   269  			app.Init = func(_ []string, _ io.Reader) (*global.Data, error) {
   270  				opts := testutil.MockGlobalData(testcase.args, &stdout)
   271  				opts.APIClientFactory = mock.APIClient(testcase.api)
   272  				return opts, nil
   273  			}
   274  			err := app.Run(testcase.args, nil)
   275  			testutil.AssertErrorContains(t, err, testcase.wantError)
   276  			testutil.AssertStringContains(t, stdout.String(), testcase.wantOutput)
   277  		})
   278  	}
   279  }
   280  
   281  var errTest = errors.New("fixture error")
   282  
   283  func createCloudfilesOK(i *fastly.CreateCloudfilesInput) (*fastly.Cloudfiles, error) {
   284  	s := fastly.Cloudfiles{
   285  		ServiceID:      fastly.ToPointer(i.ServiceID),
   286  		ServiceVersion: fastly.ToPointer(i.ServiceVersion),
   287  	}
   288  
   289  	if i.Name != nil {
   290  		s.Name = i.Name
   291  	}
   292  
   293  	return &s, nil
   294  }
   295  
   296  func createCloudfilesError(_ *fastly.CreateCloudfilesInput) (*fastly.Cloudfiles, error) {
   297  	return nil, errTest
   298  }
   299  
   300  func listCloudfilesOK(i *fastly.ListCloudfilesInput) ([]*fastly.Cloudfiles, error) {
   301  	return []*fastly.Cloudfiles{
   302  		{
   303  			ServiceID:         fastly.ToPointer(i.ServiceID),
   304  			ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   305  			Name:              fastly.ToPointer("logs"),
   306  			User:              fastly.ToPointer("username"),
   307  			AccessKey:         fastly.ToPointer("1234"),
   308  			BucketName:        fastly.ToPointer("my-logs"),
   309  			Path:              fastly.ToPointer("logs/"),
   310  			Region:            fastly.ToPointer("ORD"),
   311  			Placement:         fastly.ToPointer("none"),
   312  			Period:            fastly.ToPointer(3600),
   313  			GzipLevel:         fastly.ToPointer(9),
   314  			Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   315  			FormatVersion:     fastly.ToPointer(2),
   316  			ResponseCondition: fastly.ToPointer("Prevent default logging"),
   317  			MessageType:       fastly.ToPointer("classic"),
   318  			TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   319  			PublicKey:         fastly.ToPointer(pgpPublicKey()),
   320  		},
   321  		{
   322  			ServiceID:         fastly.ToPointer(i.ServiceID),
   323  			ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   324  			Name:              fastly.ToPointer("analytics"),
   325  			User:              fastly.ToPointer("username"),
   326  			AccessKey:         fastly.ToPointer("1234"),
   327  			BucketName:        fastly.ToPointer("analytics"),
   328  			Path:              fastly.ToPointer("logs/"),
   329  			Region:            fastly.ToPointer("ORD"),
   330  			Placement:         fastly.ToPointer("none"),
   331  			Period:            fastly.ToPointer(86400),
   332  			GzipLevel:         fastly.ToPointer(9),
   333  			Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   334  			FormatVersion:     fastly.ToPointer(2),
   335  			ResponseCondition: fastly.ToPointer("Prevent default logging"),
   336  			MessageType:       fastly.ToPointer("classic"),
   337  			TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   338  			PublicKey:         fastly.ToPointer(pgpPublicKey()),
   339  		},
   340  	}, nil
   341  }
   342  
   343  func listCloudfilesError(_ *fastly.ListCloudfilesInput) ([]*fastly.Cloudfiles, error) {
   344  	return nil, errTest
   345  }
   346  
   347  var listCloudfilesShortOutput = strings.TrimSpace(`
   348  SERVICE  VERSION  NAME
   349  123      1        logs
   350  123      1        analytics
   351  `) + "\n"
   352  
   353  var listCloudfilesVerboseOutput = strings.TrimSpace(`
   354  Fastly API endpoint: https://api.fastly.com
   355  Fastly API token provided via config file (profile: user)
   356  
   357  Service ID (via --service-id): 123
   358  
   359  Version: 1
   360  	Cloudfiles 1/2
   361  		Service ID: 123
   362  		Version: 1
   363  		Name: logs
   364  		User: username
   365  		Access key: 1234
   366  		Bucket: my-logs
   367  		Path: logs/
   368  		Region: ORD
   369  		Placement: none
   370  		Period: 3600
   371  		GZip level: 9
   372  		Format: %h %l %u %t "%r" %>s %b
   373  		Format version: 2
   374  		Response condition: Prevent default logging
   375  		Message type: classic
   376  		Timestamp format: %Y-%m-%dT%H:%M:%S.000
   377  		Public key: `+pgpPublicKey()+`
   378  	Cloudfiles 2/2
   379  		Service ID: 123
   380  		Version: 1
   381  		Name: analytics
   382  		User: username
   383  		Access key: 1234
   384  		Bucket: analytics
   385  		Path: logs/
   386  		Region: ORD
   387  		Placement: none
   388  		Period: 86400
   389  		GZip level: 9
   390  		Format: %h %l %u %t "%r" %>s %b
   391  		Format version: 2
   392  		Response condition: Prevent default logging
   393  		Message type: classic
   394  		Timestamp format: %Y-%m-%dT%H:%M:%S.000
   395  		Public key: `+pgpPublicKey()+`
   396  `) + "\n\n"
   397  
   398  func getCloudfilesOK(i *fastly.GetCloudfilesInput) (*fastly.Cloudfiles, error) {
   399  	return &fastly.Cloudfiles{
   400  		ServiceID:         fastly.ToPointer(i.ServiceID),
   401  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   402  		Name:              fastly.ToPointer("logs"),
   403  		User:              fastly.ToPointer("username"),
   404  		AccessKey:         fastly.ToPointer("1234"),
   405  		BucketName:        fastly.ToPointer("my-logs"),
   406  		Path:              fastly.ToPointer("logs/"),
   407  		Region:            fastly.ToPointer("ORD"),
   408  		Placement:         fastly.ToPointer("none"),
   409  		Period:            fastly.ToPointer(3600),
   410  		GzipLevel:         fastly.ToPointer(9),
   411  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   412  		FormatVersion:     fastly.ToPointer(2),
   413  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   414  		MessageType:       fastly.ToPointer("classic"),
   415  		TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   416  		PublicKey:         fastly.ToPointer(pgpPublicKey()),
   417  	}, nil
   418  }
   419  
   420  func getCloudfilesError(_ *fastly.GetCloudfilesInput) (*fastly.Cloudfiles, error) {
   421  	return nil, errTest
   422  }
   423  
   424  var describeCloudfilesOutput = "\n" + strings.TrimSpace(`
   425  Access key: 1234
   426  Bucket: my-logs
   427  Format: %h %l %u %t "%r" %>s %b
   428  Format version: 2
   429  GZip level: 9
   430  Message type: classic
   431  Name: logs
   432  Path: logs/
   433  Period: 3600
   434  Placement: none
   435  Public key: `+pgpPublicKey()+`
   436  Region: ORD
   437  Response condition: Prevent default logging
   438  Service ID: 123
   439  Timestamp format: %Y-%m-%dT%H:%M:%S.000
   440  User: username
   441  Version: 1
   442  `) + "\n"
   443  
   444  func updateCloudfilesOK(i *fastly.UpdateCloudfilesInput) (*fastly.Cloudfiles, error) {
   445  	return &fastly.Cloudfiles{
   446  		ServiceID:         fastly.ToPointer(i.ServiceID),
   447  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   448  		Name:              fastly.ToPointer("log"),
   449  		User:              fastly.ToPointer("username"),
   450  		AccessKey:         fastly.ToPointer("1234"),
   451  		BucketName:        fastly.ToPointer("my-logs"),
   452  		Path:              fastly.ToPointer("logs/"),
   453  		Region:            fastly.ToPointer("ORD"),
   454  		Placement:         fastly.ToPointer("none"),
   455  		Period:            fastly.ToPointer(3600),
   456  		GzipLevel:         fastly.ToPointer(9),
   457  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   458  		FormatVersion:     fastly.ToPointer(2),
   459  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   460  		MessageType:       fastly.ToPointer("classic"),
   461  		TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   462  		PublicKey:         fastly.ToPointer(pgpPublicKey()),
   463  	}, nil
   464  }
   465  
   466  func updateCloudfilesError(_ *fastly.UpdateCloudfilesInput) (*fastly.Cloudfiles, error) {
   467  	return nil, errTest
   468  }
   469  
   470  func deleteCloudfilesOK(_ *fastly.DeleteCloudfilesInput) error {
   471  	return nil
   472  }
   473  
   474  func deleteCloudfilesError(_ *fastly.DeleteCloudfilesInput) error {
   475  	return errTest
   476  }
   477  
   478  // pgpPublicKey returns a PEM encoded PGP public key suitable for testing.
   479  func pgpPublicKey() string {
   480  	return strings.TrimSpace(`-----BEGIN PGP PUBLIC KEY BLOCK-----
   481  mQENBFyUD8sBCACyFnB39AuuTygseek+eA4fo0cgwva6/FSjnWq7riouQee8GgQ/
   482  ibXTRyv4iVlwI12GswvMTIy7zNvs1R54i0qvsLr+IZ4GVGJqs6ZJnvQcqe3xPoR4
   483  8AnBfw90o32r/LuHf6QCJXi+AEu35koNlNAvLJ2B+KACaNB7N0EeWmqpV/1V2k9p
   484  lDYk+th7LcCuaFNGqKS/PrMnnMqR6VDLCjHhNx4KR79b0Twm/2qp6an3hyNRu8Gn
   485  dwxpf1/BUu3JWf+LqkN4Y3mbOmSUL3MaJNvyQguUzTfS0P0uGuBDHrJCVkMZCzDB
   486  89ag55jCPHyGeHBTd02gHMWzsg3WMBWvCsrzABEBAAG0JXRlcnJhZm9ybSAodGVz
   487  dCkgPHRlc3RAdGVycmFmb3JtLmNvbT6JAU4EEwEIADgWIQSHYyc6Kj9l6HzQsau6
   488  vFFc9jxV/wUCXJQPywIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRC6vFFc
   489  9jxV/815CAClb32OxV7wG01yF97TzlyTl8TnvjMtoG29Mw4nSyg+mjM3b8N7iXm9
   490  OLX59fbDAWtBSldSZE22RXd3CvlFOG/EnKBXSjBtEqfyxYSnyOPkMPBYWGL/ApkX
   491  SvPYJ4LKdvipYToKFh3y9kk2gk1DcDBDyaaHvR+3rv1u3aoy7/s2EltAfDS3ZQIq
   492  7/cWTLJml/lleeB/Y6rPj8xqeCYhE5ahw9gsV/Mdqatl24V9Tks30iijx0Hhw+Gx
   493  kATUikMGr2GDVqoIRga5kXI7CzYff4rkc0Twn47fMHHHe/KY9M2yVnMHUXmAZwbG
   494  M1cMI/NH1DjevCKdGBLcRJlhuLPKF/anuQENBFyUD8sBCADIpd7r7GuPd6n/Ikxe
   495  u6h7umV6IIPoAm88xCYpTbSZiaK30Svh6Ywra9jfE2KlU9o6Y/art8ip0VJ3m07L
   496  4RSfSpnzqgSwdjSq5hNour2Fo/BzYhK7yaz2AzVSbe33R0+RYhb4b/6N+bKbjwGF
   497  ftCsqVFMH+PyvYkLbvxyQrHlA9woAZaNThI1ztO5rGSnGUR8xt84eup28WIFKg0K
   498  UEGUcTzz+8QGAwAra+0ewPXo/AkO+8BvZjDidP417u6gpBHOJ9qYIcO9FxHeqFyu
   499  YrjlrxowEgXn5wO8xuNz6Vu1vhHGDHGDsRbZF8pv1d5O+0F1G7ttZ2GRRgVBZPwi
   500  kiyRABEBAAGJATYEGAEIACAWIQSHYyc6Kj9l6HzQsau6vFFc9jxV/wUCXJQPywIb
   501  DAAKCRC6vFFc9jxV/9YOCACe8qmOSnKQpQfW+PqYOqo3dt7JyweTs3FkD6NT8Zml
   502  dYy/vkstbTjPpX6aTvUZjkb46BVi7AOneVHpD5GBqvRsZ9iVgDYHaehmLCdKiG5L
   503  3Tp90NN+QY5WDbsGmsyk6+6ZMYejb4qYfweQeduOj27aavCJdLkCYMoRKfcFYI8c
   504  FaNmEfKKy/r1PO20NXEG6t9t05K/frHy6ZG8bCNYdpagfFVot47r9JaQqWlTNtIR
   505  5+zkkSq/eG9BEtRij3a6cTdQbktdBzx2KBeI0PYc1vlZR0LpuFKZqY9vlE6vTGLR
   506  wMfrTEOvx0NxUM3rpaCgEmuWbB1G1Hu371oyr4srrr+N
   507  =28dr
   508  -----END PGP PUBLIC KEY BLOCK-----
   509  `)
   510  }