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

     1  package openstack_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 TestOpenstackCreate(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 openstack create --service-id 123 --version 1 --name log --bucket log --access-key foo --user user --url https://example.com --autoclone"),
    28  			api: mock.API{
    29  				ListVersionsFn:    testutil.ListVersions,
    30  				CloneVersionFn:    testutil.CloneVersionResult(4),
    31  				CreateOpenstackFn: createOpenstackOK,
    32  			},
    33  			wantOutput: "Created OpenStack logging endpoint log (service 123 version 4)",
    34  		},
    35  		{
    36  			args: args("logging openstack create --service-id 123 --version 1 --name log --bucket log --access-key foo --user user --url https://example.com --autoclone"),
    37  			api: mock.API{
    38  				ListVersionsFn:    testutil.ListVersions,
    39  				CloneVersionFn:    testutil.CloneVersionResult(4),
    40  				CreateOpenstackFn: createOpenstackError,
    41  			},
    42  			wantError: errTest.Error(),
    43  		},
    44  		{
    45  			args: args("logging openstack create --service-id 123 --version 1 --name log --bucket log --access-key foo --user user --url https://example.com --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 TestOpenstackList(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 openstack list --service-id 123 --version 1"),
    79  			api: mock.API{
    80  				ListVersionsFn:   testutil.ListVersions,
    81  				ListOpenstacksFn: listOpenstacksOK,
    82  			},
    83  			wantOutput: listOpenstacksShortOutput,
    84  		},
    85  		{
    86  			args: args("logging openstack list --service-id 123 --version 1 --verbose"),
    87  			api: mock.API{
    88  				ListVersionsFn:   testutil.ListVersions,
    89  				ListOpenstacksFn: listOpenstacksOK,
    90  			},
    91  			wantOutput: listOpenstacksVerboseOutput,
    92  		},
    93  		{
    94  			args: args("logging openstack list --service-id 123 --version 1 -v"),
    95  			api: mock.API{
    96  				ListVersionsFn:   testutil.ListVersions,
    97  				ListOpenstacksFn: listOpenstacksOK,
    98  			},
    99  			wantOutput: listOpenstacksVerboseOutput,
   100  		},
   101  		{
   102  			args: args("logging openstack --verbose list --service-id 123 --version 1"),
   103  			api: mock.API{
   104  				ListVersionsFn:   testutil.ListVersions,
   105  				ListOpenstacksFn: listOpenstacksOK,
   106  			},
   107  			wantOutput: listOpenstacksVerboseOutput,
   108  		},
   109  		{
   110  			args: args("logging -v openstack list --service-id 123 --version 1"),
   111  			api: mock.API{
   112  				ListVersionsFn:   testutil.ListVersions,
   113  				ListOpenstacksFn: listOpenstacksOK,
   114  			},
   115  			wantOutput: listOpenstacksVerboseOutput,
   116  		},
   117  		{
   118  			args: args("logging openstack list --service-id 123 --version 1"),
   119  			api: mock.API{
   120  				ListVersionsFn:   testutil.ListVersions,
   121  				ListOpenstacksFn: listOpenstacksError,
   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 TestOpenstackDescribe(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 openstack describe --service-id 123 --version 1"),
   152  			wantError: "error parsing arguments: required flag --name not provided",
   153  		},
   154  		{
   155  			args: args("logging openstack describe --service-id 123 --version 1 --name logs"),
   156  			api: mock.API{
   157  				ListVersionsFn: testutil.ListVersions,
   158  				GetOpenstackFn: getOpenstackError,
   159  			},
   160  			wantError: errTest.Error(),
   161  		},
   162  		{
   163  			args: args("logging openstack describe --service-id 123 --version 1 --name logs"),
   164  			api: mock.API{
   165  				ListVersionsFn: testutil.ListVersions,
   166  				GetOpenstackFn: getOpenstackOK,
   167  			},
   168  			wantOutput: describeOpenstackOutput,
   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 TestOpenstackUpdate(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 openstack 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 openstack 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  				UpdateOpenstackFn: updateOpenstackError,
   205  			},
   206  			wantError: errTest.Error(),
   207  		},
   208  		{
   209  			args: args("logging openstack 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  				UpdateOpenstackFn: updateOpenstackOK,
   214  			},
   215  			wantOutput: "Updated OpenStack 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 TestOpenstackDelete(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 openstack delete --service-id 123 --version 1"),
   244  			wantError: "error parsing arguments: required flag --name not provided",
   245  		},
   246  		{
   247  			args: args("logging openstack delete --service-id 123 --version 1 --name logs --autoclone"),
   248  			api: mock.API{
   249  				ListVersionsFn:    testutil.ListVersions,
   250  				CloneVersionFn:    testutil.CloneVersionResult(4),
   251  				DeleteOpenstackFn: deleteOpenstackError,
   252  			},
   253  			wantError: errTest.Error(),
   254  		},
   255  		{
   256  			args: args("logging openstack delete --service-id 123 --version 1 --name logs --autoclone"),
   257  			api: mock.API{
   258  				ListVersionsFn:    testutil.ListVersions,
   259  				CloneVersionFn:    testutil.CloneVersionResult(4),
   260  				DeleteOpenstackFn: deleteOpenstackOK,
   261  			},
   262  			wantOutput: "Deleted OpenStack 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 createOpenstackOK(i *fastly.CreateOpenstackInput) (*fastly.Openstack, error) {
   284  	s := fastly.Openstack{
   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 createOpenstackError(_ *fastly.CreateOpenstackInput) (*fastly.Openstack, error) {
   297  	return nil, errTest
   298  }
   299  
   300  func listOpenstacksOK(i *fastly.ListOpenstackInput) ([]*fastly.Openstack, error) {
   301  	return []*fastly.Openstack{
   302  		{
   303  			ServiceID:         fastly.ToPointer(i.ServiceID),
   304  			ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   305  			Name:              fastly.ToPointer("logs"),
   306  			BucketName:        fastly.ToPointer("my-logs"),
   307  			AccessKey:         fastly.ToPointer("1234"),
   308  			User:              fastly.ToPointer("user"),
   309  			URL:               fastly.ToPointer("https://example.com"),
   310  			Path:              fastly.ToPointer("logs/"),
   311  			Period:            fastly.ToPointer(3600),
   312  			GzipLevel:         fastly.ToPointer(0),
   313  			Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   314  			FormatVersion:     fastly.ToPointer(2),
   315  			ResponseCondition: fastly.ToPointer("Prevent default logging"),
   316  			MessageType:       fastly.ToPointer("classic"),
   317  			TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   318  			Placement:         fastly.ToPointer("none"),
   319  			PublicKey:         fastly.ToPointer(pgpPublicKey()),
   320  			CompressionCodec:  fastly.ToPointer("zstd"),
   321  		},
   322  		{
   323  			ServiceID:         fastly.ToPointer(i.ServiceID),
   324  			ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   325  			Name:              fastly.ToPointer("analytics"),
   326  			BucketName:        fastly.ToPointer("analytics"),
   327  			AccessKey:         fastly.ToPointer("1234"),
   328  			User:              fastly.ToPointer("user2"),
   329  			URL:               fastly.ToPointer("https://two.example.com"),
   330  			Path:              fastly.ToPointer("logs/"),
   331  			Period:            fastly.ToPointer(86400),
   332  			GzipLevel:         fastly.ToPointer(0),
   333  			Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   334  			FormatVersion:     fastly.ToPointer(2),
   335  			MessageType:       fastly.ToPointer("classic"),
   336  			ResponseCondition: fastly.ToPointer("Prevent default logging"),
   337  			TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   338  			Placement:         fastly.ToPointer("none"),
   339  			PublicKey:         fastly.ToPointer(pgpPublicKey()),
   340  			CompressionCodec:  fastly.ToPointer("zstd"),
   341  		},
   342  	}, nil
   343  }
   344  
   345  func listOpenstacksError(_ *fastly.ListOpenstackInput) ([]*fastly.Openstack, error) {
   346  	return nil, errTest
   347  }
   348  
   349  var listOpenstacksShortOutput = strings.TrimSpace(`
   350  SERVICE  VERSION  NAME
   351  123      1        logs
   352  123      1        analytics
   353  `) + "\n"
   354  
   355  var listOpenstacksVerboseOutput = strings.TrimSpace(`
   356  Fastly API endpoint: https://api.fastly.com
   357  Fastly API token provided via config file (profile: user)
   358  
   359  Service ID (via --service-id): 123
   360  
   361  Version: 1
   362  	Openstack 1/2
   363  		Service ID: 123
   364  		Version: 1
   365  		Name: logs
   366  		Bucket: my-logs
   367  		Access key: 1234
   368  		User: user
   369  		URL: https://example.com
   370  		Path: logs/
   371  		Period: 3600
   372  		GZip level: 0
   373  		Format: %h %l %u %t "%r" %>s %b
   374  		Format version: 2
   375  		Response condition: Prevent default logging
   376  		Message type: classic
   377  		Timestamp format: %Y-%m-%dT%H:%M:%S.000
   378  		Placement: none
   379  		Public key: `+pgpPublicKey()+`
   380  		Compression codec: zstd
   381  	Openstack 2/2
   382  		Service ID: 123
   383  		Version: 1
   384  		Name: analytics
   385  		Bucket: analytics
   386  		Access key: 1234
   387  		User: user2
   388  		URL: https://two.example.com
   389  		Path: logs/
   390  		Period: 86400
   391  		GZip level: 0
   392  		Format: %h %l %u %t "%r" %>s %b
   393  		Format version: 2
   394  		Response condition: Prevent default logging
   395  		Message type: classic
   396  		Timestamp format: %Y-%m-%dT%H:%M:%S.000
   397  		Placement: none
   398  		Public key: `+pgpPublicKey()+`
   399  		Compression codec: zstd
   400  `) + "\n\n"
   401  
   402  func getOpenstackOK(i *fastly.GetOpenstackInput) (*fastly.Openstack, error) {
   403  	return &fastly.Openstack{
   404  		ServiceID:         fastly.ToPointer(i.ServiceID),
   405  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   406  		Name:              fastly.ToPointer("logs"),
   407  		BucketName:        fastly.ToPointer("my-logs"),
   408  		AccessKey:         fastly.ToPointer("1234"),
   409  		User:              fastly.ToPointer("user"),
   410  		URL:               fastly.ToPointer("https://example.com"),
   411  		Path:              fastly.ToPointer("logs/"),
   412  		Period:            fastly.ToPointer(3600),
   413  		GzipLevel:         fastly.ToPointer(0),
   414  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   415  		FormatVersion:     fastly.ToPointer(2),
   416  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   417  		MessageType:       fastly.ToPointer("classic"),
   418  		TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   419  		Placement:         fastly.ToPointer("none"),
   420  		PublicKey:         fastly.ToPointer(pgpPublicKey()),
   421  		CompressionCodec:  fastly.ToPointer("zstd"),
   422  	}, nil
   423  }
   424  
   425  func getOpenstackError(_ *fastly.GetOpenstackInput) (*fastly.Openstack, error) {
   426  	return nil, errTest
   427  }
   428  
   429  var describeOpenstackOutput = "\n" + strings.TrimSpace(`
   430  Access key: 1234
   431  Bucket: my-logs
   432  Compression codec: zstd
   433  Format: %h %l %u %t "%r" %>s %b
   434  Format version: 2
   435  GZip level: 0
   436  Message type: classic
   437  Name: logs
   438  Path: logs/
   439  Period: 3600
   440  Placement: none
   441  Public key: `+pgpPublicKey()+`
   442  Response condition: Prevent default logging
   443  Service ID: 123
   444  Timestamp format: %Y-%m-%dT%H:%M:%S.000
   445  URL: https://example.com
   446  User: user
   447  Version: 1
   448  `) + "\n"
   449  
   450  func updateOpenstackOK(i *fastly.UpdateOpenstackInput) (*fastly.Openstack, error) {
   451  	return &fastly.Openstack{
   452  		ServiceID:         fastly.ToPointer(i.ServiceID),
   453  		ServiceVersion:    fastly.ToPointer(i.ServiceVersion),
   454  		Name:              fastly.ToPointer("log"),
   455  		BucketName:        fastly.ToPointer("my-logs"),
   456  		AccessKey:         fastly.ToPointer("1234"),
   457  		User:              fastly.ToPointer("userupdate"),
   458  		URL:               fastly.ToPointer("https://update.example.com"),
   459  		Path:              fastly.ToPointer("logs/"),
   460  		Period:            fastly.ToPointer(3600),
   461  		Format:            fastly.ToPointer(`%h %l %u %t "%r" %>s %b`),
   462  		FormatVersion:     fastly.ToPointer(2),
   463  		ResponseCondition: fastly.ToPointer("Prevent default logging"),
   464  		MessageType:       fastly.ToPointer("classic"),
   465  		TimestampFormat:   fastly.ToPointer("%Y-%m-%dT%H:%M:%S.000"),
   466  		Placement:         fastly.ToPointer("none"),
   467  		PublicKey:         fastly.ToPointer(pgpPublicKey()),
   468  		CompressionCodec:  fastly.ToPointer("zstd"),
   469  	}, nil
   470  }
   471  
   472  func updateOpenstackError(_ *fastly.UpdateOpenstackInput) (*fastly.Openstack, error) {
   473  	return nil, errTest
   474  }
   475  
   476  func deleteOpenstackOK(_ *fastly.DeleteOpenstackInput) error {
   477  	return nil
   478  }
   479  
   480  func deleteOpenstackError(_ *fastly.DeleteOpenstackInput) error {
   481  	return errTest
   482  }
   483  
   484  // pgpPublicKey returns a PEM encoded PGP public key suitable for testing.
   485  func pgpPublicKey() string {
   486  	return strings.TrimSpace(`-----BEGIN PGP PUBLIC KEY BLOCK-----
   487  mQENBFyUD8sBCACyFnB39AuuTygseek+eA4fo0cgwva6/FSjnWq7riouQee8GgQ/
   488  ibXTRyv4iVlwI12GswvMTIy7zNvs1R54i0qvsLr+IZ4GVGJqs6ZJnvQcqe3xPoR4
   489  8AnBfw90o32r/LuHf6QCJXi+AEu35koNlNAvLJ2B+KACaNB7N0EeWmqpV/1V2k9p
   490  lDYk+th7LcCuaFNGqKS/PrMnnMqR6VDLCjHhNx4KR79b0Twm/2qp6an3hyNRu8Gn
   491  dwxpf1/BUu3JWf+LqkN4Y3mbOmSUL3MaJNvyQguUzTfS0P0uGuBDHrJCVkMZCzDB
   492  89ag55jCPHyGeHBTd02gHMWzsg3WMBWvCsrzABEBAAG0JXRlcnJhZm9ybSAodGVz
   493  dCkgPHRlc3RAdGVycmFmb3JtLmNvbT6JAU4EEwEIADgWIQSHYyc6Kj9l6HzQsau6
   494  vFFc9jxV/wUCXJQPywIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRC6vFFc
   495  9jxV/815CAClb32OxV7wG01yF97TzlyTl8TnvjMtoG29Mw4nSyg+mjM3b8N7iXm9
   496  OLX59fbDAWtBSldSZE22RXd3CvlFOG/EnKBXSjBtEqfyxYSnyOPkMPBYWGL/ApkX
   497  SvPYJ4LKdvipYToKFh3y9kk2gk1DcDBDyaaHvR+3rv1u3aoy7/s2EltAfDS3ZQIq
   498  7/cWTLJml/lleeB/Y6rPj8xqeCYhE5ahw9gsV/Mdqatl24V9Tks30iijx0Hhw+Gx
   499  kATUikMGr2GDVqoIRga5kXI7CzYff4rkc0Twn47fMHHHe/KY9M2yVnMHUXmAZwbG
   500  M1cMI/NH1DjevCKdGBLcRJlhuLPKF/anuQENBFyUD8sBCADIpd7r7GuPd6n/Ikxe
   501  u6h7umV6IIPoAm88xCYpTbSZiaK30Svh6Ywra9jfE2KlU9o6Y/art8ip0VJ3m07L
   502  4RSfSpnzqgSwdjSq5hNour2Fo/BzYhK7yaz2AzVSbe33R0+RYhb4b/6N+bKbjwGF
   503  ftCsqVFMH+PyvYkLbvxyQrHlA9woAZaNThI1ztO5rGSnGUR8xt84eup28WIFKg0K
   504  UEGUcTzz+8QGAwAra+0ewPXo/AkO+8BvZjDidP417u6gpBHOJ9qYIcO9FxHeqFyu
   505  YrjlrxowEgXn5wO8xuNz6Vu1vhHGDHGDsRbZF8pv1d5O+0F1G7ttZ2GRRgVBZPwi
   506  kiyRABEBAAGJATYEGAEIACAWIQSHYyc6Kj9l6HzQsau6vFFc9jxV/wUCXJQPywIb
   507  DAAKCRC6vFFc9jxV/9YOCACe8qmOSnKQpQfW+PqYOqo3dt7JyweTs3FkD6NT8Zml
   508  dYy/vkstbTjPpX6aTvUZjkb46BVi7AOneVHpD5GBqvRsZ9iVgDYHaehmLCdKiG5L
   509  3Tp90NN+QY5WDbsGmsyk6+6ZMYejb4qYfweQeduOj27aavCJdLkCYMoRKfcFYI8c
   510  FaNmEfKKy/r1PO20NXEG6t9t05K/frHy6ZG8bCNYdpagfFVot47r9JaQqWlTNtIR
   511  5+zkkSq/eG9BEtRij3a6cTdQbktdBzx2KBeI0PYc1vlZR0LpuFKZqY9vlE6vTGLR
   512  wMfrTEOvx0NxUM3rpaCgEmuWbB1G1Hu371oyr4srrr+N
   513  =28dr
   514  -----END PGP PUBLIC KEY BLOCK-----
   515  `)
   516  }