package config import "testing" func TestBackendViewsPreserveEquivalentStorageFields(t *testing.T) { forcePathStyle := false source := Backend{ Backend: BackendS3, Host: "storage.example.com", User: "reports", Port: 2222, Path: "/reports", Endpoint: "https://s3.example.com", Bucket: "source", Prefix: "incoming", Region: "us-west-2", ForcePath: &forcePathStyle, Creds: Credentials{ AccessKeyIDEnv: "ACCESS_KEY_ID", SecretAccessKeyEnv: "SECRET_ACCESS_KEY", }, SSH: SSH{ KeyFile: "/home/reports/.ssh/id_ed25519", KnownHosts: "/home/reports/.ssh/known_hosts", HostKeyPolicy: HostKeyPolicyStrict, }, } destination := Destination{ Backend: source.Backend, Host: source.Host, User: source.User, Port: source.Port, Path: source.Path, Endpoint: source.Endpoint, Bucket: source.Bucket, Prefix: source.Prefix, Region: source.Region, ForcePath: source.ForcePath, Creds: source.Creds, SSH: source.SSH, } sourceView := backendViewFromSource(source) destinationView := backendViewFromDestination(destination) if sourceView != destinationView { t.Fatalf("source view = %#v, destination view = %#v, want equivalent storage fields", sourceView, destinationView) } } func TestBackendViewValidationKeepsHTTPUploadSourceOnly(t *testing.T) { cfg := Config{Pipelines: []Pipeline{{ ID: "reports", Source: Backend{ Backend: BackendHTTPUpload, }, Destinations: []Destination{{ ID: "archive", Backend: BackendHTTPUpload, }}, }}, UploadTokens: []UploadToken{{ ID: "reporter", TokenEnv: "UPLOAD_TOKEN", AllowPipelines: []string{"reports"}, }}} ApplyDefaults(&cfg) err := Validate(cfg) if err == nil { t.Fatal("Validate() error = nil, want destination http_upload error") } if got, want := err.Error(), "pipelines[0].destinations[0].backend http_upload is only supported for sources"; got != want { t.Fatalf("Validate() error = %q, want %q", got, want) } } func TestBackendViewValidationAppliesStorageRulesToSourcesAndDestinations(t *testing.T) { forcePathStyle := false tests := []struct { name string source Backend destination Destination wantErr bool }{ { name: "local valid", source: Backend{ Backend: BackendLocal, Path: "/source", }, destination: Destination{ Backend: BackendLocal, Path: "/destination", }, }, { name: "local missing path", source: Backend{ Backend: BackendLocal, }, destination: Destination{ Backend: BackendLocal, }, wantErr: true, }, { name: "ssh valid", source: Backend{ Backend: BackendSSH, Host: "source.example.com", Port: 22, Path: "/source", SSH: SSH{HostKeyPolicy: HostKeyPolicyAcceptNew}, }, destination: Destination{ Backend: BackendSSH, Host: "destination.example.com", Port: 22, Path: "/destination", SSH: SSH{HostKeyPolicy: HostKeyPolicyAcceptNew}, }, }, { name: "ssh missing host", source: Backend{ Backend: BackendSSH, Port: 22, Path: "/source", SSH: SSH{HostKeyPolicy: HostKeyPolicyAcceptNew}, }, destination: Destination{ Backend: BackendSSH, Port: 22, Path: "/destination", SSH: SSH{HostKeyPolicy: HostKeyPolicyAcceptNew}, }, wantErr: true, }, { name: "s3 valid", source: Backend{ Backend: BackendS3, Endpoint: "https://s3.example.com", Bucket: "source", Prefix: "incoming", Region: DefaultS3Region, ForcePath: &forcePathStyle, }, destination: Destination{ Backend: BackendS3, Endpoint: "https://s3.example.com", Bucket: "destination", Prefix: "archive", Region: DefaultS3Region, ForcePath: &forcePathStyle, }, }, { name: "s3 partial credentials", source: Backend{ Backend: BackendS3, Endpoint: "https://s3.example.com", Bucket: "source", Region: DefaultS3Region, Creds: Credentials{AccessKeyIDEnv: "ACCESS_KEY_ID"}, }, destination: Destination{ Backend: BackendS3, Endpoint: "https://s3.example.com", Bucket: "destination", Region: DefaultS3Region, Creds: Credentials{AccessKeyIDEnv: "ACCESS_KEY_ID"}, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { sourceErrors := validateBackend(nil, "source", backendViewFromSource(tt.source)) destinationErrors := validateBackend(nil, "destination", backendViewFromDestination(tt.destination)) if got := len(sourceErrors) > 0; got != tt.wantErr { t.Fatalf("source validation errors = %#v, wantErr %t", sourceErrors, tt.wantErr) } if got := len(destinationErrors) > 0; got != tt.wantErr { t.Fatalf("destination validation errors = %#v, wantErr %t", destinationErrors, tt.wantErr) } }) } }