diff --git a/internal/cloudapi/v2/handler.go b/internal/cloudapi/v2/handler.go index bf30ce74d..0b0a17c17 100644 --- a/internal/cloudapi/v2/handler.go +++ b/internal/cloudapi/v2/handler.go @@ -187,6 +187,106 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error { } } + if request.Customizations != nil && request.Customizations.Directories != nil { + var dirCustomizations []blueprint.DirectoryCustomization + for _, d := range *request.Customizations.Directories { + dirCustomization := blueprint.DirectoryCustomization{ + Path: d.Path, + } + if d.Mode != nil { + dirCustomization.Mode = *d.Mode + } + if d.User != nil { + dirCustomization.User = *d.User + if uid, ok := dirCustomization.User.(float64); ok { + // check if uid can be converted to int64 + if uid != float64(int64(uid)) { + return fmt.Errorf("invalid user %f: must be an integer", uid) + } + dirCustomization.User = int64(uid) + } + } + if d.Group != nil { + dirCustomization.Group = *d.Group + if gid, ok := dirCustomization.Group.(float64); ok { + // check if gid can be converted to int64 + if gid != float64(int64(gid)) { + return fmt.Errorf("invalid group %f: must be an integer", gid) + } + dirCustomization.Group = int64(gid) + } + } + if d.EnsureParents != nil { + dirCustomization.EnsureParents = *d.EnsureParents + } + dirCustomizations = append(dirCustomizations, dirCustomization) + } + + // Validate the directory customizations, because the Cloud API does not use the custom unmarshaller + _, err := blueprint.DirectoryCustomizationsToFsNodeDirectories(dirCustomizations) + if err != nil { + return HTTPErrorWithInternal(ErrorInvalidCustomization, err) + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Directories: dirCustomizations, + } + } else { + bp.Customizations.Directories = dirCustomizations + } + } + + if request.Customizations != nil && request.Customizations.Files != nil { + var fileCustomizations []blueprint.FileCustomization + for _, f := range *request.Customizations.Files { + fileCustomization := blueprint.FileCustomization{ + Path: f.Path, + } + if f.Data != nil { + fileCustomization.Data = *f.Data + } + if f.Mode != nil { + fileCustomization.Mode = *f.Mode + } + if f.User != nil { + fileCustomization.User = *f.User + if uid, ok := fileCustomization.User.(float64); ok { + // check if uid can be converted to int64 + if uid != float64(int64(uid)) { + return fmt.Errorf("invalid user %f: must be an integer", uid) + } + fileCustomization.User = int64(uid) + } + } + if f.Group != nil { + fileCustomization.Group = *f.Group + if gid, ok := fileCustomization.Group.(float64); ok { + // check if gid can be converted to int64 + if gid != float64(int64(gid)) { + return fmt.Errorf("invalid group %f: must be an integer", gid) + } + fileCustomization.Group = int64(gid) + } + } + fileCustomizations = append(fileCustomizations, fileCustomization) + } + + // Validate the file customizations, because the Cloud API does not use the custom unmarshaller + _, err := blueprint.FileCustomizationsToFsNodeFiles(fileCustomizations) + if err != nil { + return HTTPErrorWithInternal(ErrorInvalidCustomization, err) + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Files: fileCustomizations, + } + } else { + bp.Customizations.Files = fileCustomizations + } + } + if request.Customizations != nil && request.Customizations.Filesystem != nil { var fsCustomizations []blueprint.FilesystemCustomization for _, f := range *request.Customizations.Filesystem { diff --git a/internal/cloudapi/v2/openapi.v2.gen.go b/internal/cloudapi/v2/openapi.v2.gen.go index 528d6389b..ad36f7a13 100644 --- a/internal/cloudapi/v2/openapi.v2.gen.go +++ b/internal/cloudapi/v2/openapi.v2.gen.go @@ -293,9 +293,11 @@ type ContainerUploadStatus struct { // Customizations defines model for Customizations. type Customizations struct { - Containers *[]Container `json:"containers,omitempty"` - Filesystem *[]Filesystem `json:"filesystem,omitempty"` - Packages *[]string `json:"packages,omitempty"` + Containers *[]Container `json:"containers,omitempty"` + Directories *[]Directory `json:"directories,omitempty"` + Files *[]File `json:"files,omitempty"` + Filesystem *[]Filesystem `json:"filesystem,omitempty"` + Packages *[]string `json:"packages,omitempty"` // Extra repositories for packages specified in customizations. These // repositories will only be used to depsolve and retrieve packages @@ -314,6 +316,24 @@ type Customizations struct { Users *[]User `json:"users,omitempty"` } +// A custom directory to create in the final artifact. +type Directory struct { + // Ensure that the parent directories exist + EnsureParents *bool `json:"ensure_parents,omitempty"` + + // Group of the directory as a group name or a gid + Group *interface{} `json:"group,omitempty"` + + // Permissions string for the directory in octal format + Mode *string `json:"mode,omitempty"` + + // Path to the directory + Path string `json:"path"` + + // Owner of the directory as a user name or a uid + User *interface{} `json:"user,omitempty"` +} + // Error defines model for Error. type Error struct { // Embedded struct due to allOf(#/components/schemas/ObjectReference) @@ -333,6 +353,27 @@ type ErrorList struct { Items []Error `json:"items"` } +// A custom file to create in the final artifact. +type File struct { + // Contents of the file as plain text + Data *string `json:"data,omitempty"` + + // Ensure that the parent directories exist + EnsureParents *bool `json:"ensure_parents,omitempty"` + + // Group of the file as a gid or a group name + Group *interface{} `json:"group,omitempty"` + + // Permissions string for the file in octal format + Mode *string `json:"mode,omitempty"` + + // Path to the file + Path string `json:"path"` + + // Owner of the file as a uid or a user name + User *interface{} `json:"user,omitempty"` +} + // Filesystem defines model for Filesystem. type Filesystem struct { MinSize uint64 `json:"min_size"` @@ -809,124 +850,129 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "o4hIwguPomH2wfn+4/8HAAD//3wEUOAObwAA", + "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", + "9x//PwAA//+8fVvneXUAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/cloudapi/v2/openapi.v2.yml b/internal/cloudapi/v2/openapi.v2.yml index 8fe307ff1..321a2ebd5 100644 --- a/internal/cloudapi/v2/openapi.v2.yml +++ b/internal/cloudapi/v2/openapi.v2.yml @@ -976,8 +976,18 @@ components: containers: type: array items: - $ref: '#/components/schemas/Container' - description: Container images to embed into the final artfact + $ref: '#/components/schemas/Container' + description: Container images to embed into the final artfact + directories: + type: array + items: + $ref: '#/components/schemas/Directory' + description: Directories to create in the final artifact + files: + type: array + items: + $ref: '#/components/schemas/File' + description: Files to create in the final artifact subscription: $ref: '#/components/schemas/Subscription' packages: @@ -1037,6 +1047,72 @@ components: type: boolean description: Control TLS verifification example: true + Directory: + type: object + description: | + A custom directory to create in the final artifact. + required: + - path + properties: + path: + type: string + description: Path to the directory + example: '/etc/mydir' + mode: + type: string + description: Permissions string for the directory in octal format + example: "0755" + user: + oneOf: + - type: string + - type: integer + description: Owner of the directory as a user name or a uid + example: 'root' + group: + oneOf: + - type: string + - type: integer + description: Group of the directory as a group name or a gid + example: 'root' + ensure_parents: + type: boolean + description: Ensure that the parent directories exist + default: false + File: + type: object + description: | + A custom file to create in the final artifact. + required: + - path + properties: + path: + type: string + description: Path to the file + example: '/etc/myfile' + mode: + type: string + description: Permissions string for the file in octal format + example: "0644" + user: + oneOf: + - type: string + - type: integer + description: Owner of the file as a uid or a user name + example: 'root' + group: + oneOf: + - type: string + - type: integer + description: Group of the file as a gid or a group name + example: 'root' + data: + type: string + description: Contents of the file as plain text + ensure_parents: + type: boolean + description: Ensure that the parent directories exist + example: true + default: false Filesystem: type: object required: diff --git a/internal/cloudapi/v2/v2_test.go b/internal/cloudapi/v2/v2_test.go index 9b5c2a07f..7c0c903d6 100644 --- a/internal/cloudapi/v2/v2_test.go +++ b/internal/cloudapi/v2/v2_test.go @@ -927,7 +927,48 @@ func TestComposeCustomizations(t *testing.T) { "disabled": [ "firewalld" ] - } + }, + "directories": [ + { + "path": "/etc/my/dir", + "mode": "0700" + }, + { + "path": "/etc/my/dir1", + "mode": "0700", + "user": "user1", + "group": "user1", + "ensure_parents": true + }, + { + "path": "/etc/my/dir2", + "mode": "0700", + "user": 1000, + "group": 1000, + "ensure_parents": true + } + ], + "files": [ + { + "path": "/etc/my/dir/file", + "mode": "0600", + "data": "Hello world!" + }, + { + "path": "/etc/my/dir/file2", + "mode": "0600", + "user": "user1", + "group": "user1", + "data": "Hello world!" + }, + { + "path": "/etc/my/dir/file3", + "mode": "0600", + "user": 1000, + "group": 1000, + "data": "Hello world!" + } + ] }, "image_request":{ "architecture": "%s",