From 5cbb76eac343885cfb9121c31de0998e21e553ea Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Tue, 27 Aug 2024 17:01:06 -0700 Subject: [PATCH 1/3] v2_test: Add repository json for test-distro This adds an actual repository json file for the test-disro. Without this the repo.ListDistros() function doesn't return any actual distros. Also includes a test to make sure 1 or more repos are loaded. Related: RHEL-60133 --- internal/cloudapi/v2/v2_test.go | 1 + test/data/repositories/test-distro-1.json | 26 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/data/repositories/test-distro-1.json diff --git a/internal/cloudapi/v2/v2_test.go b/internal/cloudapi/v2/v2_test.go index 8df071bfe7..8cf6f790e1 100644 --- a/internal/cloudapi/v2/v2_test.go +++ b/internal/cloudapi/v2/v2_test.go @@ -80,6 +80,7 @@ func newV2Server(t *testing.T, dir string, depsolveChannels []string, enableJWT repos, err := reporegistry.New([]string{"../../../test/data"}) require.Nil(t, err) require.NotNil(t, repos) + require.Greater(t, len(repos.ListDistros()), 0) config := v2.ServerConfig{ JWTEnabled: enableJWT, diff --git a/test/data/repositories/test-distro-1.json b/test/data/repositories/test-distro-1.json new file mode 100644 index 0000000000..bdfd3bc15e --- /dev/null +++ b/test/data/repositories/test-distro-1.json @@ -0,0 +1,26 @@ +{ + "test_arch": [ + { + "name": "test-distro", + "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-x86_64-rawhide-20240101", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGPQTCwBEADFUL0EQLzwpKHtlPkacVI156F2LnWp6K69g/6yzllidHI3b7EV\nQgQ9/Kdou6wNuOahNKa6WcEi6grEXexD7pAcu4xdRUp79XxQy5pC7Aq2/Dwf0vRL\n2y0kqof+C7iSzhHsfLoaqKKeh2njAo1KLZXYTHAWAMbXEyO/FJevaHLXe2+yYd7j\nluD58gyXgGDXXJ2lymLqs2jobjWdmGPNZGFl36RP3Dnk0FpbdH78kyIIsc2foYuF\n00rnuumwCtK3V58VOZo6IkaYk2irdyeetmJjVHwLHwJB3EaAwGy9Z2oAH3LxxFfk\nrQb0DH0Nzb3fpEziopOOqSi+6guV4RHUKAkCUMu+Mo5XwFVPUAIfNRTVqoIaEasC\nWO26lhkB87wwIvyb/TPGSeh6laHPRf0QOUOLkugdkSHoaJFWoTCcu9Y4aeDpf+ZQ\nfMVmkJNRS1tXONgz+pDk1rro/tNrkusYG18xjvSZTB0P0C4b4+jgK5l7me0NU6G3\nWw/hIng5lxWfXgE9bpxlN834v1xy5Z3v17guJu1ec/jzKzQQ4356wyegXURjYoWe\nawcnK1S+9gxivnkOk1bGLNxrEh5vB6PDcI1VQ1ECH50EHyvE1IXJDaaStdAkacv2\nqHcd15CnlBW1LYFj0CHs/sGu9FD0iSF95OVRX4gjg9Wa4f8KvtEO/f+FeQARAQAB\ntDFGZWRvcmEgKDQwKSA8ZmVkb3JhLTQwLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJOBBMBCAA4FiEEEV35rvhXhT7oRF0KBydwfqFbecwFAmPQTCwCGw8FCwkI\nBwIGFQoJCAsCBBYCAwECHgECF4AACgkQBydwfqFbecxJOw//XaoJG3zN01bVM63H\nnFmMW/EnLzKrZqH8ZNq8CP9ycoc4q8SYcMprHKG9jufzj5/FhtpYecp3kBMpSYHt\nVu46LS9NajJDwdfvUMezVbieNIQ8icTR5s5IUYFlc47eG6PRe3k0n5fOPcIb6q82\nbyrK3dQnanOcVdoGU7QO9LAAHO9hg0zgZa0MxQAlDQov3dZcr7u7qGcQmU5JzcRS\nJgfDxHxDuMjmq6Kd0/UwD00kd2ptZgRls0ntXdm9CZGtQ/Q0baJ3eRzccpd/8bxy\nRWF9MnOdmV6ojcFKYECjEzcuheUlcKQH9rLkeBSfgrIlK3L7LG8bg5ouZLdx17rQ\nXABNQGmJTaGAiEnS/48G3roMS8R7fhUljcKr6t63QQQJ2qWdPvI6EMC2xKZsLHK4\nXiUvrmJpUprvEQSKBUOf/2zuXDBshtAnoKh7h5aG+TvozL4yNG5DKpSH3MRj1E43\nKoMsP/GN/X5h+vJnvhiCWxNMPP81Op0czBAgukBm627FTnsvieJOOrzyxb1s75+W\n56gJombmhzUfzr88AYY9mFy7diTw/oldDZcfwa8rvOAGJVDlyr2hqkLoGl+5jPex\nslt3NF4caE/wP9wPMgFRkmMOr8eiRhjlWLrO6mQdBp7Qsj3kEXioP+CZ1cv/sbaK\n4DM7VidB4PLrMFQMaf0LpjpC2DM=\n=wOl2\n-----END PGP PUBLIC KEY BLOCK-----", + "check_gpg": true + } + ], + "test_arch2": [ + { + "name": "test-distro", + "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-aarch64-rawhide-20240101", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGPQTCwBEADFUL0EQLzwpKHtlPkacVI156F2LnWp6K69g/6yzllidHI3b7EV\nQgQ9/Kdou6wNuOahNKa6WcEi6grEXexD7pAcu4xdRUp79XxQy5pC7Aq2/Dwf0vRL\n2y0kqof+C7iSzhHsfLoaqKKeh2njAo1KLZXYTHAWAMbXEyO/FJevaHLXe2+yYd7j\nluD58gyXgGDXXJ2lymLqs2jobjWdmGPNZGFl36RP3Dnk0FpbdH78kyIIsc2foYuF\n00rnuumwCtK3V58VOZo6IkaYk2irdyeetmJjVHwLHwJB3EaAwGy9Z2oAH3LxxFfk\nrQb0DH0Nzb3fpEziopOOqSi+6guV4RHUKAkCUMu+Mo5XwFVPUAIfNRTVqoIaEasC\nWO26lhkB87wwIvyb/TPGSeh6laHPRf0QOUOLkugdkSHoaJFWoTCcu9Y4aeDpf+ZQ\nfMVmkJNRS1tXONgz+pDk1rro/tNrkusYG18xjvSZTB0P0C4b4+jgK5l7me0NU6G3\nWw/hIng5lxWfXgE9bpxlN834v1xy5Z3v17guJu1ec/jzKzQQ4356wyegXURjYoWe\nawcnK1S+9gxivnkOk1bGLNxrEh5vB6PDcI1VQ1ECH50EHyvE1IXJDaaStdAkacv2\nqHcd15CnlBW1LYFj0CHs/sGu9FD0iSF95OVRX4gjg9Wa4f8KvtEO/f+FeQARAQAB\ntDFGZWRvcmEgKDQwKSA8ZmVkb3JhLTQwLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJOBBMBCAA4FiEEEV35rvhXhT7oRF0KBydwfqFbecwFAmPQTCwCGw8FCwkI\nBwIGFQoJCAsCBBYCAwECHgECF4AACgkQBydwfqFbecxJOw//XaoJG3zN01bVM63H\nnFmMW/EnLzKrZqH8ZNq8CP9ycoc4q8SYcMprHKG9jufzj5/FhtpYecp3kBMpSYHt\nVu46LS9NajJDwdfvUMezVbieNIQ8icTR5s5IUYFlc47eG6PRe3k0n5fOPcIb6q82\nbyrK3dQnanOcVdoGU7QO9LAAHO9hg0zgZa0MxQAlDQov3dZcr7u7qGcQmU5JzcRS\nJgfDxHxDuMjmq6Kd0/UwD00kd2ptZgRls0ntXdm9CZGtQ/Q0baJ3eRzccpd/8bxy\nRWF9MnOdmV6ojcFKYECjEzcuheUlcKQH9rLkeBSfgrIlK3L7LG8bg5ouZLdx17rQ\nXABNQGmJTaGAiEnS/48G3roMS8R7fhUljcKr6t63QQQJ2qWdPvI6EMC2xKZsLHK4\nXiUvrmJpUprvEQSKBUOf/2zuXDBshtAnoKh7h5aG+TvozL4yNG5DKpSH3MRj1E43\nKoMsP/GN/X5h+vJnvhiCWxNMPP81Op0czBAgukBm627FTnsvieJOOrzyxb1s75+W\n56gJombmhzUfzr88AYY9mFy7diTw/oldDZcfwa8rvOAGJVDlyr2hqkLoGl+5jPex\nslt3NF4caE/wP9wPMgFRkmMOr8eiRhjlWLrO6mQdBp7Qsj3kEXioP+CZ1cv/sbaK\n4DM7VidB4PLrMFQMaf0LpjpC2DM=\n=wOl2\n-----END PGP PUBLIC KEY BLOCK-----", + "check_gpg": true + } + ], + "test_arch3": [ + { + "name": "test-distro", + "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGPQTCwBEADFUL0EQLzwpKHtlPkacVI156F2LnWp6K69g/6yzllidHI3b7EV\nQgQ9/Kdou6wNuOahNKa6WcEi6grEXexD7pAcu4xdRUp79XxQy5pC7Aq2/Dwf0vRL\n2y0kqof+C7iSzhHsfLoaqKKeh2njAo1KLZXYTHAWAMbXEyO/FJevaHLXe2+yYd7j\nluD58gyXgGDXXJ2lymLqs2jobjWdmGPNZGFl36RP3Dnk0FpbdH78kyIIsc2foYuF\n00rnuumwCtK3V58VOZo6IkaYk2irdyeetmJjVHwLHwJB3EaAwGy9Z2oAH3LxxFfk\nrQb0DH0Nzb3fpEziopOOqSi+6guV4RHUKAkCUMu+Mo5XwFVPUAIfNRTVqoIaEasC\nWO26lhkB87wwIvyb/TPGSeh6laHPRf0QOUOLkugdkSHoaJFWoTCcu9Y4aeDpf+ZQ\nfMVmkJNRS1tXONgz+pDk1rro/tNrkusYG18xjvSZTB0P0C4b4+jgK5l7me0NU6G3\nWw/hIng5lxWfXgE9bpxlN834v1xy5Z3v17guJu1ec/jzKzQQ4356wyegXURjYoWe\nawcnK1S+9gxivnkOk1bGLNxrEh5vB6PDcI1VQ1ECH50EHyvE1IXJDaaStdAkacv2\nqHcd15CnlBW1LYFj0CHs/sGu9FD0iSF95OVRX4gjg9Wa4f8KvtEO/f+FeQARAQAB\ntDFGZWRvcmEgKDQwKSA8ZmVkb3JhLTQwLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJOBBMBCAA4FiEEEV35rvhXhT7oRF0KBydwfqFbecwFAmPQTCwCGw8FCwkI\nBwIGFQoJCAsCBBYCAwECHgECF4AACgkQBydwfqFbecxJOw//XaoJG3zN01bVM63H\nnFmMW/EnLzKrZqH8ZNq8CP9ycoc4q8SYcMprHKG9jufzj5/FhtpYecp3kBMpSYHt\nVu46LS9NajJDwdfvUMezVbieNIQ8icTR5s5IUYFlc47eG6PRe3k0n5fOPcIb6q82\nbyrK3dQnanOcVdoGU7QO9LAAHO9hg0zgZa0MxQAlDQov3dZcr7u7qGcQmU5JzcRS\nJgfDxHxDuMjmq6Kd0/UwD00kd2ptZgRls0ntXdm9CZGtQ/Q0baJ3eRzccpd/8bxy\nRWF9MnOdmV6ojcFKYECjEzcuheUlcKQH9rLkeBSfgrIlK3L7LG8bg5ouZLdx17rQ\nXABNQGmJTaGAiEnS/48G3roMS8R7fhUljcKr6t63QQQJ2qWdPvI6EMC2xKZsLHK4\nXiUvrmJpUprvEQSKBUOf/2zuXDBshtAnoKh7h5aG+TvozL4yNG5DKpSH3MRj1E43\nKoMsP/GN/X5h+vJnvhiCWxNMPP81Op0czBAgukBm627FTnsvieJOOrzyxb1s75+W\n56gJombmhzUfzr88AYY9mFy7diTw/oldDZcfwa8rvOAGJVDlyr2hqkLoGl+5jPex\nslt3NF4caE/wP9wPMgFRkmMOr8eiRhjlWLrO6mQdBp7Qsj3kEXioP+CZ1cv/sbaK\n4DM7VidB4PLrMFQMaf0LpjpC2DM=\n=wOl2\n-----END PGP PUBLIC KEY BLOCK-----", + "check_gpg": true + } + ] +} From 97c0cc5e10bcc9aef34be43767aa2dc5215cbacf Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 25 Sep 2024 17:07:25 -0700 Subject: [PATCH 2/3] cloudapi: Add /distributions to return distro:arch:image-type This adds support for listing all of the supported distributions, their arches, the image types, and their repository details. Resolves: RHEL-60133 --- go.mod | 2 +- internal/cloudapi/v2/handler.go | 35 ++ internal/cloudapi/v2/openapi.v2.gen.go | 447 +++++++++++++++---------- internal/cloudapi/v2/openapi.v2.yml | 36 ++ 4 files changed, 336 insertions(+), 184 deletions(-) diff --git a/go.mod b/go.mod index 4ac9aa6c7f..ceb8250036 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( github.com/osbuild/images v0.96.0 github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d github.com/osbuild/pulp-client v0.1.0 + github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.2 github.com/segmentio/ksuid v1.0.4 github.com/sirupsen/logrus v1.9.3 @@ -201,7 +202,6 @@ require ( github.com/opencontainers/selinux v1.11.0 // indirect github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/proglottis/gpgme v0.1.3 // indirect diff --git a/internal/cloudapi/v2/handler.go b/internal/cloudapi/v2/handler.go index 34ecd88212..e5c77bc9fc 100644 --- a/internal/cloudapi/v2/handler.go +++ b/internal/cloudapi/v2/handler.go @@ -1354,3 +1354,38 @@ func uploadStatusFromJobStatus(js *worker.JobStatus, je *clienterrors.Error) Upl } return UploadStatusValueSuccess } + +// GetDistributionList returns the list of all supported distribution repositories +// It is arranged by distro name -> architecture -> image type +func (h *apiHandlers) GetDistributionList(ctx echo.Context) error { + distros := make(map[string]map[string]map[string][]rpmmd.RepoConfig) + distroNames := h.server.repos.ListDistros() + sort.Strings(distroNames) + for _, distroName := range distroNames { + distro := h.server.distros.GetDistro(distroName) + if distro == nil { + continue + } + + for _, archName := range distro.ListArches() { + arch, _ := distro.GetArch(archName) + for _, imageType := range arch.ListImageTypes() { + repos, err := h.server.repos.ReposByImageTypeName(distroName, archName, imageType) + if err != nil { + continue + } + + if _, ok := distros[distroName]; !ok { + distros[distroName] = make(map[string]map[string][]rpmmd.RepoConfig) + } + if _, ok := distros[distroName][archName]; !ok { + distros[distroName][archName] = make(map[string][]rpmmd.RepoConfig) + } + + distros[distroName][archName][imageType] = repos + } + } + } + + return ctx.JSON(http.StatusOK, distros) +} diff --git a/internal/cloudapi/v2/openapi.v2.gen.go b/internal/cloudapi/v2/openapi.v2.gen.go index c76902471c..ea6544d1d8 100644 --- a/internal/cloudapi/v2/openapi.v2.gen.go +++ b/internal/cloudapi/v2/openapi.v2.gen.go @@ -7,6 +7,7 @@ import ( "bytes" "compress/gzip" "encoding/base64" + "encoding/json" "fmt" "net/http" "net/url" @@ -16,6 +17,7 @@ import ( "github.com/deepmap/oapi-codegen/pkg/runtime" "github.com/getkin/kin-openapi/openapi3" "github.com/labstack/echo/v4" + "github.com/pkg/errors" ) const ( @@ -651,6 +653,16 @@ type Directory struct { User *interface{} `json:"user,omitempty"` } +// DistributionList defines model for DistributionList. +type DistributionList struct { + Map *DistributionList_Map `json:"map,omitempty"` +} + +// DistributionList_Map defines model for DistributionList.Map. +type DistributionList_Map struct { + AdditionalProperties map[string]interface{} `json:"-"` +} + // Error defines model for Error. type Error struct { // Embedded struct due to allOf(#/components/schemas/ObjectReference) @@ -1222,6 +1234,59 @@ type PostComposeJSONRequestBody PostComposeJSONBody // PostCloneComposeJSONRequestBody defines body for PostCloneCompose for application/json ContentType. type PostCloneComposeJSONRequestBody PostCloneComposeJSONBody +// Getter for additional properties for DistributionList_Map. Returns the specified +// element and whether it was found +func (a DistributionList_Map) Get(fieldName string) (value interface{}, found bool) { + if a.AdditionalProperties != nil { + value, found = a.AdditionalProperties[fieldName] + } + return +} + +// Setter for additional properties for DistributionList_Map +func (a *DistributionList_Map) Set(fieldName string, value interface{}) { + if a.AdditionalProperties == nil { + a.AdditionalProperties = make(map[string]interface{}) + } + a.AdditionalProperties[fieldName] = value +} + +// Override default JSON handling for DistributionList_Map to handle AdditionalProperties +func (a *DistributionList_Map) UnmarshalJSON(b []byte) error { + object := make(map[string]json.RawMessage) + err := json.Unmarshal(b, &object) + if err != nil { + return err + } + + if len(object) != 0 { + a.AdditionalProperties = make(map[string]interface{}) + for fieldName, fieldBuf := range object { + var fieldVal interface{} + err := json.Unmarshal(fieldBuf, &fieldVal) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("error unmarshaling field %s", fieldName)) + } + a.AdditionalProperties[fieldName] = fieldVal + } + } + return nil +} + +// Override default JSON handling for DistributionList_Map to handle AdditionalProperties +func (a DistributionList_Map) MarshalJSON() ([]byte, error) { + var err error + object := make(map[string]json.RawMessage) + + for fieldName, field := range a.AdditionalProperties { + object[fieldName], err = json.Marshal(field) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("error marshaling '%s'", fieldName)) + } + } + return json.Marshal(object) +} + // ServerInterface represents all server handlers. type ServerInterface interface { // The status of a cloned compose @@ -1248,6 +1313,9 @@ type ServerInterface interface { // Get the SBOMs for a compose. // (GET /composes/{id}/sboms) GetComposeSBOMs(ctx echo.Context, id string) error + // Get all of the supported distribution repository details + // (GET /distributions) + GetDistributionList(ctx echo.Context) error // Get a list of all possible errors // (GET /errors) GetErrorList(ctx echo.Context, params GetErrorListParams) error @@ -1393,6 +1461,17 @@ func (w *ServerInterfaceWrapper) GetComposeSBOMs(ctx echo.Context) error { return err } +// GetDistributionList converts echo context to params. +func (w *ServerInterfaceWrapper) GetDistributionList(ctx echo.Context) error { + var err error + + ctx.Set(BearerScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetDistributionList(ctx) + return err +} + // GetErrorList converts echo context to params. func (w *ServerInterfaceWrapper) GetErrorList(ctx echo.Context) error { var err error @@ -1485,6 +1564,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/composes/:id/manifests", wrapper.GetComposeManifests) router.GET(baseURL+"/composes/:id/metadata", wrapper.GetComposeMetadata) router.GET(baseURL+"/composes/:id/sboms", wrapper.GetComposeSBOMs) + router.GET(baseURL+"/distributions", wrapper.GetDistributionList) router.GET(baseURL+"/errors", wrapper.GetErrorList) router.GET(baseURL+"/errors/:id", wrapper.GetError) router.GET(baseURL+"/openapi", wrapper.GetOpenapi) @@ -1494,189 +1574,190 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "qo1G0xneTHt/vnxsFHb2H33HnbQbT48ng5fJ2aBLCp/72+/X/ftR76RcPHytDFs7V0f7l0Vy/uXz/l3J", - "C0btz6+doF15OGf7Fa9yHLjCP7s9PD07F17t8KBLSuz4/UuDdkoTf/exVT9vHNgXzebV5KXxwunDXX3n", - "8S5ofi70yAvroNvy+e1Vsz+5bu5sP+zWa/jqvku8Wvtzj98cjHea5XPm2o2L6sVBQCdPpTYWx/CpenZz", - "fi8+dw5hqYr5Y/u4+fJOd64f6/eV06thrdglzuuDUy9fFnpe+fC9vdOpVx4OD3old/RSbbmjN6f1eoac", - "Uun9y+Obxx7bT6enzf7ovf/ZvWxvB2/OSZe8vBVOixP3qXyOe8ds+7jRmFzt3j2wxlN73L4oHlovnfr4", - "sEnehu2DYPLqPYzvR5f7X4LD1n39ClUeu+QC35X6p5d1bu8c+PzorXbx+YtNLshN+/MJe+lcnx1UvAfm", - "Nmxy2BnYj/f1l6eh/zA4mPBKYXcXXXXJYFhk52RSfLkcD2HQL+C7+pW1/WV0MXw5v704dWp3u/dnk9Pg", - "4UG8j7+Ql4vL2sPt0f7rWZU/Ue/iokv6otc5KX2uTXq3D4VGZbTfg2+3D2Wxc/d++WK9o2H76RDD88vd", - "88KJddps3ZZujurb9fKB3XAPj3btLhmWnRv82L5pQHhaPD1tvJ+Mboe3p+fnzln58eYRn1zeT8qicjo5", - "6nMGvdq43Xy46g+uUWtyvt95Ou2SEfMv3ese6vPObm2n0y/vX7YC5/2JNWv3bwfts+GTczso3R+P2q0b", - "0py8D28m24d35ddrHz/UdqWMGly3vjyxM2qdVc7O27sF/H5607l1xctF47cu+e2639npEnW6HF4eLDt6", - "FpS7ogw9c+6mH9I/qx6ufvRnqTv4ox4Bilf/SfW6yPFCx4YuEaSc6jGtCHKp0HCgTK5YRomqPNQlv4aR", - "TJ9SqxDN5RSEZWbphpW2PtaPnnSVgwWe8jVLE5hHQzezq1NVyYZtRxd1oc/VPO8DAzGgDL8jW9kz8/nt", - "a73W02g/YDG8Oqne1XeqhzbfvyMT0av0xqNbxzlxb9ze4xd3h5SKo90FdW5T0+Tv9BtHkfmj86TM46uS", - "pJKOIdvDZHXEN1dBBRJPadbx2pnLH5CBDHqT2Fs6KdVxw2KIdrokIi3dpfQhqckroSF9FbTFNwbGg3y4", - "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", } // 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 95c61bfc83..ca1d056b46 100644 --- a/internal/cloudapi/v2/openapi.v2.yml +++ b/internal/cloudapi/v2/openapi.v2.yml @@ -397,6 +397,27 @@ paths: schema: $ref: '#/components/schemas/Error' + /distributions: + get: + operationId: getDistributionList + summary: |- + Get all of the supported distribution repository details + security: + - Bearer: [] + responses: + '200': + description: Distribution repositories + content: + application/json: + schema: + $ref: '#/components/schemas/DistributionList' + '500': + description: Unexpected error occurred + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /errors/{id}: get: operationId: getError @@ -548,6 +569,21 @@ components: items: $ref: '#/components/schemas/Error' + DistributionList: + properties: + map: + type: object + additionalProperties: + map: + type: object + additionalProperties: + map: + type: object + additionalProperties: + type: array + items: + $ref: '#/components/schemas/BlueprintRepository' + ComposeStatus: allOf: - $ref: '#/components/schemas/ObjectReference' From d15d3c4bdd067fd01589acc90434f24a0d423266 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Tue, 27 Aug 2024 16:01:55 -0700 Subject: [PATCH 3/3] v2_test: Add a test for GetDistributionsList Related: RHEL-60133 --- internal/cloudapi/v2/v2_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/internal/cloudapi/v2/v2_test.go b/internal/cloudapi/v2/v2_test.go index 8cf6f790e1..1a8099056a 100644 --- a/internal/cloudapi/v2/v2_test.go +++ b/internal/cloudapi/v2/v2_test.go @@ -252,6 +252,37 @@ func TestGetErrorList(t *testing.T) { }`, "operation_id", "total", "details") } +func TestGetDistributionList(t *testing.T) { + srv, _, _, cancel := newV2Server(t, t.TempDir(), []string{""}, false, false) + defer cancel() + + test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", + "/api/image-builder-composer/v2/distributions", ``, http.StatusOK, ` + { + "test-distro-1":{ + "test_arch":{ + "test_ostree_type":[ + {"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-x86_64-rawhide-20240101"], "check_gpg":true, "name":"test-distro"} + ], + "test_type":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-x86_64-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}] + }, + "test_arch2":{ + "test_type":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-aarch64-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "test_type2":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-aarch64-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}]}, + "test_arch3":{ + "ami":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "gce":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "image-installer":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "qcow2":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "rhel-edge-commit":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "rhel-edge-installer":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "vhd":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}], + "vmdk":[{"baseurls":["https://rpmrepo.osbuild.org/v2/mirror/public/f40/f40-ppc64le-rawhide-20240101"], "check_gpg":true, "name":"test-distro"}] + } + } + }`, "gpgkeys", "baseurl") +} + func TestCompose(t *testing.T) { srv, _, _, cancel := newV2Server(t, t.TempDir(), []string{""}, false, false) defer cancel()