diff --git a/publisher/config/schema.go b/publisher/config/schema.go index 70b570e..d8ec58d 100644 --- a/publisher/config/schema.go +++ b/publisher/config/schema.go @@ -4,13 +4,21 @@ import ( "fmt" "gopkg.in/yaml.v2" "io/ioutil" + "strings" ) -//Errors +// Errors const ( noDestinationError = "no uploads were provided for the schema" + //FileTypes + TypeFile = "file" + TypeZypp = "zypp" + TypeYum = "yum" + TypeApt = "apt" ) +var fileTypes = []string{TypeFile, TypeZypp, TypeYum, TypeApt} + type UploadArtifactSchema struct { Src string `yaml:"src"` Arch []string `yaml:"arch"` @@ -65,3 +73,36 @@ func parseUploadSchema(fileContent []byte) (UploadArtifactSchemas, error) { return schema, nil } + +// ValidateSchemas validates that some components of the schema are correct (this is still wip) +// It validates: +// - no incorrect fileType is present +// - the app name is the prefix of the src package. This is mandatory to create consistent apt repositories. +// If they are not equal, the file will be uploaded to a location, and the metadata will point to different location +// which will break the apt repository as you'll receive a 404 when trying to install the package. +func ValidateSchemas(appName string, schemas UploadArtifactSchemas) error { + for _, schema := range schemas { + if !isValidAppName(appName, schema) { + return fmt.Errorf("invalid app name: %s", appName) + } + for _, upload := range schema.Uploads { + if !isValidType(upload.Type) { + return fmt.Errorf("invalid upload type: %s", upload.Type) + } + } + } + return nil +} + +func isValidType(uploadType string) bool { + for _, validType := range fileTypes { + if uploadType == validType { + return true + } + } + return false +} + +func isValidAppName(appName string, schemas UploadArtifactSchema) bool { + return strings.HasPrefix(schemas.Src, appName) +} diff --git a/publisher/config/schema_test.go b/publisher/config/schema_test.go index b3d3710..38bc6b3 100644 --- a/publisher/config/schema_test.go +++ b/publisher/config/schema_test.go @@ -136,3 +136,47 @@ func TestSchema(t *testing.T) { }) } } + +func TestValidateSchemas_UploadType(t *testing.T) { + tests := []struct { + name string + appName string + schemas UploadArtifactSchemas + expectedError error + }{ + {name: "valid apt", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_0.0.1_amd64.deb", Uploads: []Upload{{Type: TypeApt}}}}, expectedError: nil}, + {name: "valid yum", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_0.0.1_amd64.rpm", Uploads: []Upload{{Type: TypeYum}}}}, expectedError: nil}, + {name: "valid file", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_0.0.1_amd64.tar-gz", Uploads: []Upload{{Type: TypeFile}}}}, expectedError: nil}, + {name: "valid zypp", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_0.0.1_amd64.rpm", Uploads: []Upload{{Type: TypeZypp}}}}, expectedError: nil}, + {name: "invalid type even with valid file", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_0.0.1_amd64.deb", Uploads: []Upload{{Type: "something wrong"}}}}, expectedError: errors.New("invalid upload type: something wrong")}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + err := ValidateSchemas(tt.appName, tt.schemas) + assert.Equal(t, tt.expectedError, err) + }) + } +} + +func TestValidateSchemas_AppNameShouldBePkgPrefix(t *testing.T) { + tests := []struct { + name string + appName string + schemas UploadArtifactSchemas + expectedError error + }{ + {name: "valid app name with pkg suffix", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_some_suffix_0.0.1_amd64.deb", Uploads: []Upload{{Type: TypeApt}}}}, expectedError: nil}, + {name: "valid app name exactly as pkg name", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-app-name_0.0.1_amd64.deb", Uploads: []Upload{{Type: TypeApt}}}}, expectedError: nil}, + {name: "invalid app name", appName: "some-app-name", schemas: UploadArtifactSchemas{{Src: "some-other-name_0.0.1_amd64.deb", Uploads: []Upload{{Type: TypeFile}}}}, expectedError: errors.New("invalid app name: some-app-name")}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + err := ValidateSchemas(tt.appName, tt.schemas) + assert.Equal(t, tt.expectedError, err) + }) + } +} diff --git a/publisher/publisher.go b/publisher/publisher.go index d1e6941..d1b98c2 100644 --- a/publisher/publisher.go +++ b/publisher/publisher.go @@ -89,6 +89,10 @@ func main() { if err != nil { l.Fatal(err) } + // validate schemas + if err = config.ValidateSchemas(conf.AppName, uploadSchemas); err != nil { + l.Fatal(err) + } if conf.LocalPackagesPath == "" { d := download.NewDownloader(http.DefaultClient) diff --git a/publisher/upload/upload.go b/publisher/upload/upload.go index e018157..eb109d5 100644 --- a/publisher/upload/upload.go +++ b/publisher/upload/upload.go @@ -18,11 +18,6 @@ import ( ) const ( - //FileTypes - typeFile = "file" - typeZypp = "zypp" - typeYum = "yum" - typeApt = "apt" repodataRpmPath = "/repodata/repomd.xml" signatureRpmPath = "/repodata/repomd.xml.asc" aptPoolMain = "pool/main/" @@ -33,7 +28,7 @@ const ( ) func uploadArtifact(conf config.Config, schema config.UploadArtifactSchema, upload config.Upload) (err error) { - if upload.Type == typeFile { + if upload.Type == config.TypeFile { utils.Logger.Println("Uploading file artifact") for _, arch := range schema.Arch { if len(upload.OsVersion) == 0 { @@ -50,7 +45,7 @@ func uploadArtifact(conf config.Config, schema config.UploadArtifactSchema, uplo } } } - } else if upload.Type == typeYum || upload.Type == typeZypp { + } else if upload.Type == config.TypeYum || upload.Type == config.TypeZypp { utils.Logger.Println("Uploading rpm as yum or zypp") for _, arch := range schema.Arch { err = uploadRpm(conf, schema.Src, upload, arch) @@ -58,7 +53,7 @@ func uploadArtifact(conf config.Config, schema config.UploadArtifactSchema, uplo return err } } - } else if upload.Type == typeApt { + } else if upload.Type == config.TypeApt { utils.Logger.Println("Uploading apt") err = uploadApt(conf, schema.Src, upload, schema.Arch) if err != nil {