From 983e45c17be6d126f7d4e9cb306698618748e9cc Mon Sep 17 00:00:00 2001 From: iizitounene Date: Tue, 22 Apr 2025 17:21:56 +0200 Subject: [PATCH 01/14] feat: add static catalog for kad packages --- .gitignore | 1 + .local/application-local.yaml | 51 +++ .local/authz-policy.csv | 4 + README.md | 3 +- .../v3/_api/catalogs/catalogs-server.go | 212 +++++++++- api/openapi/v3/_api/spec.go | 96 ++--- api/openapi/v3/_api/types.go | 23 +- api/openapi/v3/api.yaml | 38 +- api/openapi/v3/definition/Catalog.yaml | 37 +- api/openapi/v3/definition/Package.yaml | 15 + ...atalog-by-name.yaml => catalog-by-id.yaml} | 14 +- .../{catalog.yaml => catalog-list.yaml} | 17 +- .../v3/paths/catalogs/package-by-name.yaml | 34 ++ .../v3/paths/catalogs/package-definition.yaml | 41 ++ .../v3/paths/catalogs/package-list.yaml | 30 ++ .../v3/paths/catalogs/package-schema.yaml | 41 ++ .../catalogs/package-versions-by-name.yaml | 34 ++ docker-compose.yml | 2 + go.mod | 150 ++++++- go.sum | 382 ++++++++++++++++++ internal/config/config.go | 15 +- internal/config/config_test.go | 29 ++ internal/config/testdata/application.yaml | 21 +- internal/controllers/catalog_controller.go | 62 ++- internal/controllers/register.go | 1 + .../integrations/registry/client/client.go | 255 ++++++++++++ .../integrations/registry/client/error.go | 31 ++ .../integrations/registry/repo_catalog.go | 53 +++ internal/kad/catalog_client.go | 52 --- internal/kad/client/client.go | 29 +- internal/kad/component_client.go | 6 +- internal/kad/component_release_client.go | 10 +- internal/kad/template_release_client.go | 6 +- internal/logging/logging.go | 12 +- internal/model/catalog.go | 24 +- internal/model/kad.go | 23 ++ internal/schema/parameters/schematic.go | 31 ++ internal/schema/parameters/schematic_test.go | 249 ++++++++++++ internal/schema/release/release.go | 51 +++ internal/security/authc/auth.go | 4 +- .../security/authc/provider/bearer/bearer.go | 6 +- internal/security/authc/provider/oidc/oidc.go | 20 +- internal/security/authz/authz.go | 8 +- .../{errors => servererrors}/server_errors.go | 11 +- internal/services/catalog.go | 38 +- internal/services/component.go | 6 +- internal/services/component_releases.go | 8 +- internal/services/service.go | 4 +- internal/services/template_release.go | 6 +- internal/utils/collection_utils_test.go | 2 +- internal/utils/env_utils.go | 38 ++ internal/utils/env_utils_test.go | 42 ++ internal/utils/versioning_utils.go | 68 ++++ internal/utils/versioning_utils_test.go | 55 +++ 54 files changed, 2240 insertions(+), 261 deletions(-) create mode 100644 api/openapi/v3/definition/Package.yaml rename api/openapi/v3/paths/catalogs/{catalog-by-name.yaml => catalog-by-id.yaml} (66%) rename api/openapi/v3/paths/catalogs/{catalog.yaml => catalog-list.yaml} (53%) create mode 100644 api/openapi/v3/paths/catalogs/package-by-name.yaml create mode 100644 api/openapi/v3/paths/catalogs/package-definition.yaml create mode 100644 api/openapi/v3/paths/catalogs/package-list.yaml create mode 100644 api/openapi/v3/paths/catalogs/package-schema.yaml create mode 100644 api/openapi/v3/paths/catalogs/package-versions-by-name.yaml create mode 100644 internal/integrations/registry/client/client.go create mode 100644 internal/integrations/registry/client/error.go create mode 100644 internal/integrations/registry/repo_catalog.go delete mode 100644 internal/kad/catalog_client.go create mode 100644 internal/model/kad.go create mode 100644 internal/schema/parameters/schematic.go create mode 100644 internal/schema/parameters/schematic_test.go create mode 100644 internal/schema/release/release.go rename internal/{errors => servererrors}/server_errors.go (81%) create mode 100644 internal/utils/env_utils.go create mode 100644 internal/utils/env_utils_test.go create mode 100644 internal/utils/versioning_utils.go create mode 100644 internal/utils/versioning_utils_test.go diff --git a/.gitignore b/.gitignore index fc1f73b..38a5fe6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ tmp/ .go-cache/ .bin/ package-lock.json +*.tgz diff --git a/.local/application-local.yaml b/.local/application-local.yaml index 627a196..8b34ce8 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -82,6 +82,57 @@ swagger: security: - oauth2: [openid, email, profile, roles] + +catalog: + - id: storage + name: Storage catalog + description: My Storage packages + repoUrl: quay.io/kubocd/packages + ### public registry, no credentials needed + #credentials: + # robotAccountName: $(OCI_USERNAME) + # robotAccountToken: $(OCI_PASSWORD) + packages: + - name: redis + - name: minio + - name: cnpg + + - id: auth + name: Auth catalog + description: My Auth packages + repoUrl: quay.io/kubocd/packages + ### private registry, credentials needed + credentials: + robotAccountName: $(OCI_USERNAME) + robotAccountToken: $(OCI_PASSWORD) + packages: + - name: openldap + + - id: infra + name: Infra catalog + description: My Infra packages + repoUrl: quay.io/kubocd/packages + ### Private registry, credentials needed + credentials: + robotAccountName: $(OCI_USERNAME) + robotAccountToken: $(OCI_PASSWORD) + packages: + - name: podinfo + - name: cert-manager + - name: ingress-nginx + - name: metallb + + - id: stack + name: Stack catalog + description: My Stack packages + repoUrl: quay.io/kubocd/packages + ### Private registry, credentials needed + credentials: + robotAccountName: $(OCI_USERNAME) + robotAccountToken: $(OCI_PASSWORD) + packages: + - name: stack1 + kad: - id: sandbox name: Sandbox de idir diff --git a/.local/authz-policy.csv b/.local/authz-policy.csv index 1efc35a..f50c42a 100644 --- a/.local/authz-policy.csv +++ b/.local/authz-policy.csv @@ -1,4 +1,8 @@ p, role:viewers, /api/v1/users/myprofile, * +p, role:viewers, /api/v1/catalogs, * +p, role:viewers, /api/v1/catalogs/*, * + + p, role:viewers, /api/v1/kad, * p, role:viewers, /api/v1/kad/*/services, * p, role:viewers, /api/v1/kad/*/catalog, * diff --git a/README.md b/README.md index 0e84d1d..c1cad2b 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,10 @@ kubectl port-forward svc/kad-webserver 6553:6553 ### Start +Start docker compose using your robot account token to access private registries: ```shell docker-compose rm -f -docker-compose up --build +OCI_USERNAME=okdp+okdp_quay_robot OCI_PASSWORD=****** docker-compose up --build ``` Open swagger UI at: http://localhost:8092/ diff --git a/api/openapi/v3/_api/catalogs/catalogs-server.go b/api/openapi/v3/_api/catalogs/catalogs-server.go index 3bab79d..b684597 100644 --- a/api/openapi/v3/_api/catalogs/catalogs-server.go +++ b/api/openapi/v3/_api/catalogs/catalogs-server.go @@ -14,11 +14,26 @@ import ( // ServerInterface represents all server handlers. type ServerInterface interface { // List all catalogs - // (GET /kad/{kadInstanceId}/catalogs) - ListCatalogs(c *gin.Context, kadInstanceId string) - // Get a catalog info by name - // (GET /kad/{kadInstanceId}/catalogs/{name}) - GetCatalog(c *gin.Context, kadInstanceId string, name string) + // (GET /catalogs) + ListCatalogs(c *gin.Context) + // Get a catalog by id + // (GET /catalogs/{catalogId}) + GetCatalog(c *gin.Context, catalogId string) + // Get a list of packages by catalog id + // (GET /catalogs/{catalogId}/packages) + GetPackages(c *gin.Context, catalogId string) + // Get package by catalog id and package name + // (GET /catalogs/{catalogId}/packages/{name}) + GetPackageByName(c *gin.Context, catalogId string, name string) + // List versions for a specific package + // (GET /catalogs/{catalogId}/packages/{name}/versions) + GetPackageVersionsByName(c *gin.Context, catalogId string, name string) + // Get package definition + // (GET /catalogs/{catalogId}/packages/{name}/versions/{version}) + GetPackageDefinition(c *gin.Context, catalogId string, name string, version string) + // Get package schema (parameters, context, etc) + // (GET /catalogs/{catalogId}/packages/{name}/versions/{version}/schema) + GetPackageSchema(c *gin.Context, catalogId string, name string, version string) } // ServerInterfaceWrapper converts contexts to parameters. @@ -33,14 +48,27 @@ type MiddlewareFunc func(c *gin.Context) // ListCatalogs operation middleware func (siw *ServerInterfaceWrapper) ListCatalogs(c *gin.Context) { + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.ListCatalogs(c) +} + +// GetCatalog operation middleware +func (siw *ServerInterfaceWrapper) GetCatalog(c *gin.Context) { + var err error - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string + // ------------- Path parameter "catalogId" ------------- + var catalogId string - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "catalogId", c.Param("catalogId"), &catalogId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalogId: %w", err), http.StatusBadRequest) return } @@ -51,20 +79,77 @@ func (siw *ServerInterfaceWrapper) ListCatalogs(c *gin.Context) { } } - siw.Handler.ListCatalogs(c, kadInstanceId) + siw.Handler.GetCatalog(c, catalogId) } -// GetCatalog operation middleware -func (siw *ServerInterfaceWrapper) GetCatalog(c *gin.Context) { +// GetPackages operation middleware +func (siw *ServerInterfaceWrapper) GetPackages(c *gin.Context) { + + var err error + + // ------------- Path parameter "catalogId" ------------- + var catalogId string + + err = runtime.BindStyledParameterWithOptions("simple", "catalogId", c.Param("catalogId"), &catalogId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalogId: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetPackages(c, catalogId) +} + +// GetPackageByName operation middleware +func (siw *ServerInterfaceWrapper) GetPackageByName(c *gin.Context) { + + var err error + + // ------------- Path parameter "catalogId" ------------- + var catalogId string + + err = runtime.BindStyledParameterWithOptions("simple", "catalogId", c.Param("catalogId"), &catalogId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalogId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "name" ------------- + var name string + + err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetPackageByName(c, catalogId, name) +} + +// GetPackageVersionsByName operation middleware +func (siw *ServerInterfaceWrapper) GetPackageVersionsByName(c *gin.Context) { var err error - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string + // ------------- Path parameter "catalogId" ------------- + var catalogId string - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "catalogId", c.Param("catalogId"), &catalogId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalogId: %w", err), http.StatusBadRequest) return } @@ -84,7 +169,91 @@ func (siw *ServerInterfaceWrapper) GetCatalog(c *gin.Context) { } } - siw.Handler.GetCatalog(c, kadInstanceId, name) + siw.Handler.GetPackageVersionsByName(c, catalogId, name) +} + +// GetPackageDefinition operation middleware +func (siw *ServerInterfaceWrapper) GetPackageDefinition(c *gin.Context) { + + var err error + + // ------------- Path parameter "catalogId" ------------- + var catalogId string + + err = runtime.BindStyledParameterWithOptions("simple", "catalogId", c.Param("catalogId"), &catalogId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalogId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "name" ------------- + var name string + + err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "version" ------------- + var version string + + err = runtime.BindStyledParameterWithOptions("simple", "version", c.Param("version"), &version, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter version: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetPackageDefinition(c, catalogId, name, version) +} + +// GetPackageSchema operation middleware +func (siw *ServerInterfaceWrapper) GetPackageSchema(c *gin.Context) { + + var err error + + // ------------- Path parameter "catalogId" ------------- + var catalogId string + + err = runtime.BindStyledParameterWithOptions("simple", "catalogId", c.Param("catalogId"), &catalogId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalogId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "name" ------------- + var name string + + err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "version" ------------- + var version string + + err = runtime.BindStyledParameterWithOptions("simple", "version", c.Param("version"), &version, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter version: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetPackageSchema(c, catalogId, name, version) } // GinServerOptions provides options for the Gin server. @@ -114,6 +283,11 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options ErrorHandler: errorHandler, } - router.GET(options.BaseURL+"/kad/:kadInstanceId/catalogs", wrapper.ListCatalogs) - router.GET(options.BaseURL+"/kad/:kadInstanceId/catalogs/:name", wrapper.GetCatalog) + router.GET(options.BaseURL+"/catalogs", wrapper.ListCatalogs) + router.GET(options.BaseURL+"/catalogs/:catalogId", wrapper.GetCatalog) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages", wrapper.GetPackages) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name", wrapper.GetPackageByName) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions", wrapper.GetPackageVersionsByName) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions/:version", wrapper.GetPackageDefinition) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions/:version/schema", wrapper.GetPackageSchema) } diff --git a/api/openapi/v3/_api/spec.go b/api/openapi/v3/_api/spec.go index 6d304e1..27ea258 100644 --- a/api/openapi/v3/_api/spec.go +++ b/api/openapi/v3/_api/spec.go @@ -18,51 +18,57 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "KIs3V5v/BQAA//9CJ63ODGQAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/openapi/v3/_api/types.go b/api/openapi/v3/_api/types.go index d8368aa..d67b7ae 100644 --- a/api/openapi/v3/_api/types.go +++ b/api/openapi/v3/_api/types.go @@ -11,9 +11,17 @@ import ( // Catalog defines model for Catalog. type Catalog struct { - Components []string `json:"components"` - Name string `json:"name"` - Templates []string `json:"templates"` + Credentials *struct { + RobotAccountName *string `json:"robotAccountName,omitempty"` + RobotAccountToken *string `json:"robotAccountToken,omitempty"` + } `json:"credentials,omitempty"` + Description string `json:"description"` + ID string `json:"id"` + Name string `json:"name"` + Packages []struct { + Name string `json:"name"` + } `json:"packages"` + RepoURL string `json:"repoUrl"` } // Component defines model for Component. @@ -280,6 +288,15 @@ type KadInstance struct { Name string `json:"name"` } +// Package defines model for Package. +type Package struct { + // Name The name of the package + Name string `json:"name"` + + // Versions A list of versions for the package + Versions []string `json:"versions"` +} + // ServerError defines model for ServerError. type ServerError struct { Message string `json:"message"` diff --git a/api/openapi/v3/api.yaml b/api/openapi/v3/api.yaml index 3254e9e..08c07d3 100644 --- a/api/openapi/v3/api.yaml +++ b/api/openapi/v3/api.yaml @@ -22,6 +22,12 @@ tags: description: User profile externalDocs: url: https://github.com/okdp/okdp-server + - name: catalogs + description: Catalogs + externalDocs: + url: https://github.com/okdp/okdp-server + + - name: kad description: Kad instances configuration externalDocs: @@ -30,10 +36,6 @@ tags: description: Services externalDocs: url: https://github.com/okdp/okdp-server - - name: catalogs - description: Catalogs - externalDocs: - url: https://github.com/okdp/okdp-server - name: templatereleases description: Template releases externalDocs: @@ -51,16 +53,28 @@ paths: ### Users /users/myprofile: $ref: ./paths/users/user-profile.yaml + ### Registry Catalogs + /catalogs: + $ref: ./paths/catalogs/catalog-list.yaml + /catalogs/{catalogId}: + $ref: ./paths/catalogs/catalog-by-id.yaml + /catalogs/{catalogId}/packages: + $ref: ./paths/catalogs/package-list.yaml + /catalogs/{catalogId}/packages/{name}: + $ref: ./paths/catalogs/package-by-name.yaml + /catalogs/{catalogId}/packages/{name}/versions: + $ref: ./paths/catalogs/package-versions-by-name.yaml + /catalogs/{catalogId}/packages/{name}/versions/{version}: + $ref: ./paths/catalogs/package-definition.yaml + /catalogs/{catalogId}/packages/{name}/versions/{version}/schema: + $ref: ./paths/catalogs/package-schema.yaml + + ###### Remove all this ### KAD instances /kad: $ref: ./paths/kad/kad-instance.yaml /kad/{kadInstanceId}: $ref: ./paths/kad/kad-instance-by-name.yaml - ### KAD Catalog API - /kad/{kadInstanceId}/catalogs: - $ref: ./paths/catalogs/catalog.yaml - /kad/{kadInstanceId}/catalogs/{name}: - $ref: ./paths/catalogs/catalog-by-name.yaml ### Services API /kad/{kadInstanceId}/services: $ref: ./paths/services/service.yaml @@ -86,6 +100,12 @@ components: $ref: './definition/UserProfile.yaml' Catalog: $ref: './definition/Catalog.yaml' + Package: + $ref: './definition/Package.yaml' + + + + TemplateRelease: $ref: './definition/TemplateRelease.yaml' ComponentReleasePayload: diff --git a/api/openapi/v3/definition/Catalog.yaml b/api/openapi/v3/definition/Catalog.yaml index 74e2275..d203248 100644 --- a/api/openapi/v3/definition/Catalog.yaml +++ b/api/openapi/v3/definition/Catalog.yaml @@ -1,19 +1,38 @@ type: object xml: name: catalog -required: +required: +- "id" - "name" -- "components" -- "templates" +- "description" +- "repoUrl" +- "packages" properties: + id: + type: string + x-go-name: ID name: type: string - components: - type: array - items: - type: string - templates: + description: + type: string + repoUrl: + type: string + format: uri + x-go-name: repoURL + credentials: + type: object + properties: + robotAccountName: + type: string + robotAccountToken: + type: string + packages: type: array items: - type: string + type: object + required: + - name + properties: + name: + type: string diff --git a/api/openapi/v3/definition/Package.yaml b/api/openapi/v3/definition/Package.yaml new file mode 100644 index 0000000..58cd8a5 --- /dev/null +++ b/api/openapi/v3/definition/Package.yaml @@ -0,0 +1,15 @@ +type: object +xml: + name: package +required: +- "name" +- "versions" +properties: + name: + type: string + description: The name of the package + versions: + type: array + items: + type: string + description: A list of versions for the package diff --git a/api/openapi/v3/paths/catalogs/catalog-by-name.yaml b/api/openapi/v3/paths/catalogs/catalog-by-id.yaml similarity index 66% rename from api/openapi/v3/paths/catalogs/catalog-by-name.yaml rename to api/openapi/v3/paths/catalogs/catalog-by-id.yaml index 3ef81c0..e1626c2 100644 --- a/api/openapi/v3/paths/catalogs/catalog-by-name.yaml +++ b/api/openapi/v3/paths/catalogs/catalog-by-id.yaml @@ -1,23 +1,17 @@ get: - summary: Get a catalog info by name + summary: Get a catalog by id description: | - Get a catalog info by name + Get a catalog by id tags: - catalogs operationId: getCatalog parameters: - in: path - name: kadInstanceId + name: catalogId schema: type: string required: true - description: KAD instance ID - - in: path - name: name - schema: - type: string - required: true - description: Catalog name + description: Catalog ID responses: '200': description: Catalog information diff --git a/api/openapi/v3/paths/catalogs/catalog.yaml b/api/openapi/v3/paths/catalogs/catalog-list.yaml similarity index 53% rename from api/openapi/v3/paths/catalogs/catalog.yaml rename to api/openapi/v3/paths/catalogs/catalog-list.yaml index 3fb37de..990c50f 100644 --- a/api/openapi/v3/paths/catalogs/catalog.yaml +++ b/api/openapi/v3/paths/catalogs/catalog-list.yaml @@ -5,26 +5,15 @@ get: tags: - catalogs operationId: listCatalogs - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID responses: '200': description: List of the catalogs content: application/json: schema: - type: object - required: [catalogs] - properties: - catalogs: - type: array - items: - $ref: '../../definition/Catalog.yaml' + type: array + items: + $ref: '../../definition/Catalog.yaml' default: description: Server error content: diff --git a/api/openapi/v3/paths/catalogs/package-by-name.yaml b/api/openapi/v3/paths/catalogs/package-by-name.yaml new file mode 100644 index 0000000..e3a5a9a --- /dev/null +++ b/api/openapi/v3/paths/catalogs/package-by-name.yaml @@ -0,0 +1,34 @@ +get: + summary: Get package by catalog id and package name + description: | + Get package by catalog id and package name + tags: + - catalogs + operationId: getPackageByName + parameters: + - in: path + name: catalogId + schema: + type: string + required: true + description: Catalog ID + - in: path + name: name + schema: + type: string + required: true + description: Package name + responses: + '200': + description: Packages information + content: + application/json: + schema: + $ref: '../../definition/Package.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerError.yaml' + diff --git a/api/openapi/v3/paths/catalogs/package-definition.yaml b/api/openapi/v3/paths/catalogs/package-definition.yaml new file mode 100644 index 0000000..98ae98b --- /dev/null +++ b/api/openapi/v3/paths/catalogs/package-definition.yaml @@ -0,0 +1,41 @@ +get: + summary: Get package definition + description: | + Get package definition + tags: + - catalogs + operationId: getPackageDefinition + parameters: + - in: path + name: catalogId + schema: + type: string + required: true + description: Catalog ID + - in: path + name: name + schema: + type: string + required: true + description: Package name + - in: path + name: version + schema: + type: string + required: true + description: Package version + responses: + '200': + description: Package definition + content: + application/json: + schema: + type: object + additionalProperties: true + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerError.yaml' + diff --git a/api/openapi/v3/paths/catalogs/package-list.yaml b/api/openapi/v3/paths/catalogs/package-list.yaml new file mode 100644 index 0000000..bd7aec2 --- /dev/null +++ b/api/openapi/v3/paths/catalogs/package-list.yaml @@ -0,0 +1,30 @@ +get: + summary: Get a list of packages by catalog id + description: | + List of packages by catalog id + tags: + - catalogs + operationId: getPackages + parameters: + - in: path + name: catalogId + schema: + type: string + required: true + description: Catalog ID + responses: + '200': + description: Packages information + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/Package.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerError.yaml' + diff --git a/api/openapi/v3/paths/catalogs/package-schema.yaml b/api/openapi/v3/paths/catalogs/package-schema.yaml new file mode 100644 index 0000000..355b512 --- /dev/null +++ b/api/openapi/v3/paths/catalogs/package-schema.yaml @@ -0,0 +1,41 @@ +get: + summary: Get package schema (parameters, context, etc) + description: | + Get package schema (parameters, context, etc) + tags: + - catalogs + operationId: getPackageSchema + parameters: + - in: path + name: catalogId + schema: + type: string + required: true + description: Catalog ID + - in: path + name: name + schema: + type: string + required: true + description: Package name + - in: path + name: version + schema: + type: string + required: true + description: Package version + responses: + '200': + description: Package schema + content: + application/json: + schema: + type: object + additionalProperties: true + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerError.yaml' + diff --git a/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml b/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml new file mode 100644 index 0000000..488e033 --- /dev/null +++ b/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml @@ -0,0 +1,34 @@ +get: + summary: List versions for a specific package + description: | + List versions for a specific package + tags: + - catalogs + operationId: getPackageVersionsByName + parameters: + - in: path + name: catalogId + schema: + type: string + required: true + description: Catalog ID + - in: path + name: name + schema: + type: string + required: true + description: Package name + responses: + '200': + description: Package versions + content: + application/json: + schema: + $ref: '../../definition/Package.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerError.yaml' + diff --git a/docker-compose.yml b/docker-compose.yml index 42882a4..2101c76 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,6 +30,8 @@ services: - .go-cache/go-mod:/go/pkg working_dir: /workspace environment: + - OCI_USERNAME=${OCI_USERNAME} + - OCI_PASSWORD=${OCI_PASSWORD} - GOCACHE=/go-build - GOMODCACHE=/go/pkg depends_on: diff --git a/go.mod b/go.mod index 3631146..97e1264 100644 --- a/go.mod +++ b/go.mod @@ -21,51 +21,152 @@ require ( github.com/stretchr/testify v1.10.0 github.com/tidwall/gjson v1.18.0 go.uber.org/zap v1.27.0 - golang.org/x/net v0.35.0 + golang.org/x/net v0.37.0 golang.org/x/oauth2 v0.26.0 ) require ( + cloud.google.com/go/compute/metadata v0.6.0 // indirect + dario.cat/mergo v1.0.1 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/Masterminds/squirrel v1.5.4 // indirect + github.com/Masterminds/vcs v1.13.3 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect + github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect + github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd // indirect + github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect + github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect github.com/bytedance/sonic v1.12.8 // indirect github.com/bytedance/sonic/loader v0.2.3 // indirect github.com/casbin/govaluate v1.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cloudwego/base64x v0.1.5 // indirect + github.com/containerd/containerd v1.7.24 // indirect + github.com/containerd/errdefs v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/cli v27.5.0+incompatible // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker v27.5.0+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.2 // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect + github.com/docker/go-metrics v0.0.1 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch v5.9.0+incompatible // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gin-contrib/sse v1.0.0 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.25.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect github.com/goccy/go-json v0.10.5 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/gomodule/redigo v1.9.2 // indirect + github.com/google/btree v1.0.1 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-containerregistry v0.20.3 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/context v1.1.2 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.4.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gosuri/uitable v0.0.4 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/huandu/xstrings v1.5.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/magiconair/properties v1.8.9 // indirect github.com/mailru/easyjson v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/spdystream v0.5.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 // indirect github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rubenv/sql-migrate v1.7.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect @@ -75,13 +176,54 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect + github.com/vbatts/tar-split v0.11.6 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect + github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect + github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect + github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect + go.opentelemetry.io/otel v1.33.0 // indirect + go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/otel/trace v1.33.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.14.0 // indirect - golang.org/x/crypto v0.33.0 // indirect + golang.org/x/crypto v0.36.0 // indirect golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/term v0.30.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/time v0.8.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect + google.golang.org/grpc v1.67.3 // indirect google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + helm.sh/helm/v3 v3.17.2 // indirect + k8s.io/api v0.32.2 // indirect + k8s.io/apiextensions-apiserver v0.32.2 // indirect + k8s.io/apimachinery v0.32.2 // indirect + k8s.io/apiserver v0.32.2 // indirect + k8s.io/cli-runtime v0.32.2 // indirect + k8s.io/client-go v0.32.2 // indirect + k8s.io/component-base v0.32.2 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/kubectl v0.32.2 // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect + oras.land/oras-go v1.2.5 // indirect + oras.land/oras-go/v2 v2.5.0 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/kustomize/api v0.18.0 // indirect + sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index a847fb7..9173e8d 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,57 @@ +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/vcs v1.13.3 h1:IIA2aBdXvfbIM+yl/eTnL4hb1XwdpvuQLglAix1gweE= +github.com/Masterminds/vcs v1.13.3/go.mod h1:TiE7xuEjl1N4j016moRd6vezp6e6Lz23gypeXfzXeW8= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs= github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -14,20 +61,72 @@ github.com/casbin/casbin/v2 v2.103.0 h1:dHElatNXNrr8XcseUov0ZSiWjauwmZZE6YMV3eU1 github.com/casbin/casbin/v2 v2.103.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco= github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= +github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= +github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= +github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= +github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= +github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U= +github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= +github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30= @@ -42,10 +141,26 @@ github.com/gin-contrib/zap v1.1.4 h1:xvxTybg6XBdNtcQLH3Tf0lFr4vhDkwzgLLrIGlNTqIo github.com/gin-contrib/zap v1.1.4/go.mod h1:7lgEpe91kLbeJkwBTPgtVBy4zMa6oSBEcvj662diqKQ= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -58,81 +173,217 @@ github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0 github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo= github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s= +github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= +github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 h1:9djga8U4+/TQzv5iMlZHZ/qbGQB9V2nlnk2bmiG+uBs= github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8= github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672 h1:+273wgr7to5QhwOOBE5LwjdNDFAI+8cbJVfB0Zj75aI= github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4= +github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= @@ -147,10 +398,13 @@ github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -171,6 +425,37 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= +github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -179,35 +464,132 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg= golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= +google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8= +google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +helm.sh/helm/v3 v3.17.2 h1:agYQ5ew2jq5vdx2K7q5W44KyKQrnSubUMCQsjkiv3/o= +helm.sh/helm/v3 v3.17.2/go.mod h1:+uJKMH/UiMzZQOALR3XUf3BLIoczI2RKKD6bMhPh4G8= +k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= +k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= +k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= +k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= +k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= +k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apiserver v0.32.2 h1:WzyxAu4mvLkQxwD9hGa4ZfExo3yZZaYzoYvvVDlM6vw= +k8s.io/apiserver v0.32.2/go.mod h1:PEwREHiHNU2oFdte7BjzA1ZyjWjuckORLIK/wLV5goM= +k8s.io/cli-runtime v0.32.2 h1:aKQR4foh9qeyckKRkNXUccP9moxzffyndZAvr+IXMks= +k8s.io/cli-runtime v0.32.2/go.mod h1:a/JpeMztz3xDa7GCyyShcwe55p8pbcCVQxvqZnIwXN8= +k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= +k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= +k8s.io/component-base v0.32.2 h1:1aUL5Vdmu7qNo4ZsE+569PV5zFatM9hl+lb3dEea2zU= +k8s.io/component-base v0.32.2/go.mod h1:PXJ61Vx9Lg+P5mS8TLd7bCIr+eMJRQTyXe8KvkrvJq0= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us= +k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= +oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= +oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= +oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= +sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= +sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= +sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/internal/config/config.go b/internal/config/config.go index 5f8a3a4..6f91c12 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -22,17 +22,18 @@ import ( "github.com/fsnotify/fsnotify" "github.com/getkin/kin-openapi/openapi3" - "github.com/okdp/okdp-server/api/openapi/v3/_api" + "github.com/okdp/okdp-server/internal/model" "github.com/spf13/viper" ) // Application configuration type ApplicationConfig struct { - Server Server `mapstructure:"server"` - Security Security `mapstructure:"security"` - Logging Logging `mapstructure:"logging"` - Swagger Swagger `mapstructure:"swagger"` - Kad []KadInstance `mapstructure:"kad"` + Server Server `mapstructure:"server"` + Security Security `mapstructure:"security"` + Logging Logging `mapstructure:"logging"` + Swagger Swagger `mapstructure:"swagger"` + Kad []model.KadInstance `mapstructure:"kad"` + Catalogs []*model.Catalog `mapstructure:"catalog"` } // Server configuration @@ -140,8 +141,6 @@ type Swagger struct { Security openapi3.SecurityRequirements `yaml:"security,omitempty"` } -type KadInstance _api.KadInstance - var ( instance *ApplicationConfig once sync.Once diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 685eb8e..aa85d83 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_LoadConfig_Server(t *testing.T) { @@ -167,6 +168,34 @@ func Test_LoadConfig_Swagger(t *testing.T) { } +func Test_LoadConfig_Catalog(t *testing.T) { + // Given + viper.Set("config", "testdata/application.yaml") + // When + catalogs := GetAppConfig().Catalogs + // Then + require.NotEmpty(t, catalogs, "Catalogs should not be empty") + catalog := catalogs[0] + assert.True(t, catalog.IsAuthenticated(), "The catalog should be authenticated") + assert.Equal(t, "infra01", catalog.ID, "ID") + assert.Equal(t, "infra01 catalog", catalog.Name, "Name") + assert.Equal(t, "My infrastructure components", catalog.Description, "Description") + assert.Equal(t, "quay.io/okdp/applications", catalog.RepoURL, "RepoURL") + assert.Equal(t, "$(OCI_USERNAME)", *catalog.Credentials.RobotAccountName, "Credentials.RobotAccountName") + assert.Equal(t, "$(OCI_PASSWORD)", *catalog.Credentials.RobotAccountToken, "Credentials.RobotAccountToken") + assert.Equal(t, "quay.io", catalog.RepoHost(), "RepoHost") + + require.NotEmpty(t, catalog.Packages, "Packages catalogs should not be empty") + require.Len(t, catalog.Packages, 3, "The catalog should contain exactly 3 Packages") + assert.Equal(t, "redis", catalog.Packages[0].Name, "Packages") + assert.Equal(t, "podinfo", catalog.Packages[1].Name, "Packages") + assert.Equal(t, "cert-manager", catalog.Packages[2].Name, "Packages") + + catalog = catalogs[1] + assert.Equal(t, "infra02", catalog.ID, "ID") + assert.False(t, catalog.IsAuthenticated(), fmt.Sprintf("The catalog '%s' should not be authenticated", catalog.ID)) +} + func Test_LoadConfig_Kad(t *testing.T) { // Given viper.Set("config", "testdata/application.yaml") diff --git a/internal/config/testdata/application.yaml b/internal/config/testdata/application.yaml index 29a4583..9b1fc6b 100644 --- a/internal/config/testdata/application.yaml +++ b/internal/config/testdata/application.yaml @@ -80,4 +80,23 @@ kad: apiUrl: https://host.docker.internal:6553/api/kad/v1 authBearer: JUDtoP55C2dLfeaXqSbehhKKRdmAWTfj insecureSkipVerify: true - + +catalog: + - id: infra01 + name: infra01 catalog + description: My infrastructure components + repoUrl: quay.io/okdp/applications + credentials: + robotAccountName: $(OCI_USERNAME) + robotAccountToken: $(OCI_PASSWORD) + packages: + - name: redis + - name: podinfo + - name: cert-manager + + - id: infra02 + name: infra02 catalog + description: My infrastructure components + repoUrl: quay.io/okdp/applications + packages: + - name: minio diff --git a/internal/controllers/catalog_controller.go b/internal/controllers/catalog_controller.go index 1e4f427..595bccd 100644 --- a/internal/controllers/catalog_controller.go +++ b/internal/controllers/catalog_controller.go @@ -1,5 +1,5 @@ /* - * Copyright 2024 okdp.io + * Copyright 2025 okdp.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package controllers import ( - "fmt" "net/http" "github.com/gin-gonic/gin" @@ -35,27 +34,66 @@ func CatalogController() *ICatalogController { } } -func (r ICatalogController) ListCatalogs(c *gin.Context, kadInstanceID string) { - catalogs, err := r.catalogService.List(kadInstanceID) +func (r ICatalogController) ListCatalogs(c *gin.Context) { + catalogs := r.catalogService.ListCatalogs() + c.JSON(http.StatusOK, catalogs) +} + +func (r ICatalogController) GetCatalog(c *gin.Context, catalogID string) { + catalog, err := r.catalogService.GetCatalog(catalogID) if err != nil { - log.Error("Unable to list Catalogs on kad instance %s, details: %+v", kadInstanceID, err) + log.Error("Unable to find the Catalog with ID '%s', details: %+v", catalogID, err) c.JSON(err.Status, err) return } - c.JSON(http.StatusOK, catalogs) + c.JSON(http.StatusOK, catalog) } -func (r ICatalogController) GetCatalog(c *gin.Context, kadInstanceID string, name string) { - catalog, err := r.catalogService.Get(kadInstanceID, name) +func (r ICatalogController) GetPackages(c *gin.Context, catalogID string) { + packages, err := r.catalogService.GetPackages(catalogID) if err != nil { - log.Error("Unable to get Catalog info '%s' on kad instance %s, details: %+v", name, kadInstanceID, err) + log.Error("Unable to find the packages with Catalog ID '%s', details: %+v", catalogID, err) c.JSON(err.Status, err) return } - if catalog == nil { - c.JSON(http.StatusNotFound, fmt.Sprintf("Component with id %s not found", name)) + c.JSON(http.StatusOK, packages) +} + +func (r ICatalogController) GetPackageByName(c *gin.Context, catalogID string, name string) { + result, err := r.catalogService.GetPackageByName(catalogID, name) + if err != nil { + log.Error("Unable to find the package '%s' with Catalog ID '%s', details: %+v", name, catalogID, err) + c.JSON(err.Status, err) return } - c.JSON(http.StatusOK, catalog) + c.JSON(http.StatusOK, result) +} + +func (r ICatalogController) GetPackageVersionsByName(c *gin.Context, catalogID string, name string) { + r.GetPackageByName(c, catalogID, name) +} +func (r ICatalogController) GetPackageDefinition(c *gin.Context, catalogID string, name string, version string) { + definition, err := r.catalogService.GetPackageDefinition(catalogID, name, version) + if err != nil { + log.Error("Unable to find the package definition for package '%s:%s' with Catalog ID '%s', details: %+v", name, version, catalogID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, definition) +} + +func (r ICatalogController) GetPackageSchema(c *gin.Context, catalogID string, name string, version string) { + definition, err := r.catalogService.GetPackageDefinition(catalogID, name, version) + if err != nil { + log.Error("Unable to find the package definition for package '%s:%s' with Catalog ID '%s', details: %+v", name, version, catalogID, err) + c.JSON(err.Status, err) + return + } + schema, ok := definition["schema"] + if !ok { + c.JSON(http.StatusOK, struct{}{}) + return + } + c.JSON(http.StatusOK, schema) } diff --git a/internal/controllers/register.go b/internal/controllers/register.go index 975e55b..35880b1 100644 --- a/internal/controllers/register.go +++ b/internal/controllers/register.go @@ -40,6 +40,7 @@ type Group struct { func (g *Group) RegisterControllers() { _user.RegisterHandlers(g, UserProfileController()) _catalog.RegisterHandlers(g, CatalogController()) + _componentrelease.RegisterHandlers(g, ComponentReleaseController()) _templaterelease.RegisterHandlers(g, TemplateReleaseController()) _component.RegisterHandlers(g, ComponentController()) diff --git a/internal/integrations/registry/client/client.go b/internal/integrations/registry/client/client.go new file mode 100644 index 0000000..7969ca4 --- /dev/null +++ b/internal/integrations/registry/client/client.go @@ -0,0 +1,255 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "context" + "encoding/json" + "errors" + "io" + "net/http" + "strings" + "sync" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "oras.land/oras-go/v2" + "oras.land/oras-go/v2/content/memory" + "oras.land/oras-go/v2/registry/remote" + "oras.land/oras-go/v2/registry/remote/auth" + "oras.land/oras-go/v2/registry/remote/errcode" + "oras.land/oras-go/v2/registry/remote/retry" + + "github.com/okdp/okdp-server/internal/config" + log "github.com/okdp/okdp-server/internal/logging" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" + "github.com/okdp/okdp-server/internal/utils" +) + +var ( + instance *RepositoryClients + once sync.Once +) + +type RepositoryClients struct { + clients map[string]*RepositoryClient +} + +type RepositoryClient struct { + *remote.Repository +} + +func GetClients() *RepositoryClients { + once.Do(func() { + clients := make(map[string]*RepositoryClient) + catalogs := config.GetAppConfig().Catalogs + for _, catalog := range catalogs { + log.Info("Container Registry configuration: %+v", catalog) + + var creds auth.CredentialFunc = func(_ context.Context, _ string) (auth.Credential, error) { + return auth.EmptyCredential, nil + } + + if catalog.IsAuthenticated() { + log.Info("The catalog ID '%s' is authenticated", catalog.ID) + username := utils.GetEnv(*catalog.Credentials.RobotAccountName) + password := utils.GetEnv(*catalog.Credentials.RobotAccountToken) + if username == "" || password == "" { + log.Fatal("Robot account name and robot account token: %s/%s are empty for catalog %s", + *catalog.Credentials.RobotAccountName, *catalog.Credentials.RobotAccountToken, catalog.ID) + } + + creds = auth.StaticCredential(catalog.RepoHost(), auth.Credential{ + Username: username, + Password: password, + }) + } else { + log.Info("The catalog ID '%s' is not authenticated", catalog.ID) + } + + authClient := &auth.Client{ + Client: retry.DefaultClient, + Cache: auth.NewCache(), + Credential: creds, + } + + for _, p := range catalog.Packages { + repo, err := remote.NewRepository(strings.TrimSuffix(catalog.RepoURL, "/") + "/" + p.Name) + if err != nil { + log.Fatal("Failed to create a client to the remote repository %s: %v", catalog.RepoURL, err) + } + repo.Client = authClient + clients[repoClientKey(catalog.ID, p.Name)] = &RepositoryClient{repo} + } + } + instance = &RepositoryClients{clients: clients} + }) + return instance +} + +func ListCatalogs() []*model.Catalog { + catalogs := config.GetAppConfig().Catalogs + if catalogs == nil { + return []*model.Catalog{} + } + return catalogs +} + +func GetCatalog(catalogID string) (*model.Catalog, *servererrors.ServerError) { + catalogs := config.GetAppConfig().Catalogs + for _, catalog := range catalogs { + if strings.EqualFold(catalog.ID, catalogID) { + return catalog, nil + } + } + return nil, CatalogNotFoundError(catalogID) +} + +func GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) { + catalog, err := GetCatalog(catalogID) + if err != nil { + return nil, err + } + packages := make([]*model.Package, 0, len(catalog.Packages)) + for _, p := range catalog.Packages { + result, err := getPackage(catalogID, p.Name) + if err != nil { + return nil, err + } + packages = append(packages, result) + } + return packages, nil +} + +func GetPackageByName(catalogID string, name string) (*model.Package, *servererrors.ServerError) { + catalog, err := GetCatalog(catalogID) + if err != nil { + return nil, err + } + for _, p := range catalog.Packages { + if strings.EqualFold(p.Name, name) { + return getPackage(catalogID, p.Name) + } + } + return nil, CatalogPackageNotFoundError(catalogID, name) +} + +func GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *servererrors.ServerError) { + repo, err := getRepoClient(catalogID, name) + if err != nil { + return nil, err + } + return repo.fetchDefinition(version) +} + +func getPackage(catalogID string, name string) (*model.Package, *servererrors.ServerError) { + repo, err := getRepoClient(catalogID, name) + if err != nil { + return nil, err + } + versions, err := repo.listTags() + if err != nil { + return nil, err + } + return &model.Package{ + Name: name, + Versions: utils.SortVersions(versions), + }, nil +} + +func (r RepositoryClient) listTags() ([]string, *servererrors.ServerError) { + ctx := context.Background() + var allTags []string + var last string + var err *servererrors.ServerError + for { + er := r.Tags(ctx, last, func(tags []string) error { + if len(tags) == 0 { + return io.EOF + } + last = tags[len(tags)-1] + allTags = append(allTags, tags...) + return nil + }) + + statusCode := http.StatusBadGateway + if er != nil { + if er != io.EOF { + var httpErr *errcode.ErrorResponse + if errors.As(er, &httpErr) { + err = servererrors.OfType(servererrors.Registry).GenericError(httpErr.StatusCode, httpErr.Error()) + } else { + err = servererrors.OfType(servererrors.Registry).GenericError(statusCode, er.Error()) + } + } + break + } + } + + return allTags, err +} + +func (r RepositoryClient) fetchDefinition(version string) (map[string]interface{}, *servererrors.ServerError) { + ctx := context.Background() + // Pull to memory + memStore := memory.New() + desc, err := oras.Copy(ctx, r.Repository, version, memStore, version, oras.DefaultCopyOptions) + if err != nil { + log.Error("Failed to copy definition into the memstore: %v", err) + return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + } + + // Decode manifest + manifestReader, err := memStore.Fetch(ctx, desc) + if err != nil { + log.Error("Failed to fetch definition from the memstore: %v", err) + return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + } + defer manifestReader.Close() + + var manifest ocispec.Manifest + if err := json.NewDecoder(manifestReader).Decode(&manifest); err != nil { + log.Error("Failed to decode definition: %v", err) + return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + } + + configReader, err := memStore.Fetch(ctx, manifest.Config) + if err != nil { + log.Error("Failed to fetch the definition content: %v", err) + return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + } + defer configReader.Close() + + var definition map[string]interface{} + if err := json.NewDecoder(configReader).Decode(&definition); err != nil { + log.Error("Failed to decode the definition content: %v", err) + return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + } + return definition, nil +} + +func getRepoClient(catalogID string, packageName string) (*RepositoryClient, *servererrors.ServerError) { + instance, found := instance.clients[repoClientKey(catalogID, packageName)] + if !found { + return nil, CatalogPackageNotFoundError(catalogID, packageName) + } + return instance, nil +} + +func repoClientKey(catalogID string, packageName string) string { + return catalogID + packageName +} diff --git a/internal/integrations/registry/client/error.go b/internal/integrations/registry/client/error.go new file mode 100644 index 0000000..9d78ba1 --- /dev/null +++ b/internal/integrations/registry/client/error.go @@ -0,0 +1,31 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "github.com/okdp/okdp-server/internal/servererrors" +) + +func CatalogNotFoundError(provided string) *servererrors.ServerError { + return servererrors.OfType(servererrors.OkdpServer). + NotFoundError("The catalog with id %s not found.", provided) +} + +func CatalogPackageNotFoundError(catalogID string, packageName string) *servererrors.ServerError { + return servererrors.OfType(servererrors.OkdpServer). + NotFoundError("The package %s not found in the catalog ID %s.", packageName, catalogID) +} diff --git a/internal/integrations/registry/repo_catalog.go b/internal/integrations/registry/repo_catalog.go new file mode 100644 index 0000000..13d19da --- /dev/null +++ b/internal/integrations/registry/repo_catalog.go @@ -0,0 +1,53 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package registry + +import ( + "github.com/okdp/okdp-server/internal/integrations/registry/client" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" +) + +type RepoCatalog struct { + r *client.RepositoryClients +} + +func NewRepoCatalog() *RepoCatalog { + return &RepoCatalog{ + r: client.GetClients(), + } +} + +func (r RepoCatalog) ListCatalogs() []*model.Catalog { + return client.ListCatalogs() +} + +func (r RepoCatalog) GetCatalog(catalogID string) (*model.Catalog, *servererrors.ServerError) { + return client.GetCatalog(catalogID) +} + +func (r RepoCatalog) GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) { + return client.GetPackages(catalogID) +} + +func (r RepoCatalog) GetPackageByName(catalogID string, name string) (*model.Package, *servererrors.ServerError) { + return client.GetPackageByName(catalogID, name) +} + +func (r RepoCatalog) GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *servererrors.ServerError) { + return client.GetPackageDefinition(catalogID, name, version) +} diff --git a/internal/kad/catalog_client.go b/internal/kad/catalog_client.go deleted file mode 100644 index b064f74..0000000 --- a/internal/kad/catalog_client.go +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kad - -import ( - "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" - "github.com/okdp/okdp-server/internal/kad/client" - "github.com/okdp/okdp-server/internal/model" -) - -type CatalogClient struct { - KAD *client.KadClients -} - -func NewCatalogClient() *CatalogClient { - return &CatalogClient{ - KAD: client.GetClients(), - } -} - -func (c CatalogClient) Get(kadInstanceID string, name string) (*model.Catalog, *errors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.CatalogURL + "/" + name) - return client.DoGet[model.Catalog](req) -} - -func (c CatalogClient) List(kadInstanceID string) (*model.Catalogs, *errors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.CatalogURL) - return client.DoGet[model.Catalogs](req) -} diff --git a/internal/kad/client/client.go b/internal/kad/client/client.go index 06db19d..59d5a69 100644 --- a/internal/kad/client/client.go +++ b/internal/kad/client/client.go @@ -24,8 +24,9 @@ import ( "github.com/go-resty/resty/v2" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/errors" log "github.com/okdp/okdp-server/internal/logging" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" "github.com/okdp/okdp-server/internal/utils" ) @@ -70,7 +71,7 @@ func GetClients() *KadClients { return instance } -func (c *KadClients) ID(id string) (*KadClient, *errors.ServerError) { +func (c *KadClients) ID(id string) (*KadClient, *servererrors.ServerError) { client, found := c.clients[id] if !found { return nil, invalidInstanceError(id) @@ -78,27 +79,27 @@ func (c *KadClients) ID(id string) (*KadClient, *errors.ServerError) { return client, nil } -func ListInstances() []config.KadInstance { +func ListInstances() []model.KadInstance { return config.GetAppConfig().Kad } -func GetInstanceByID(id string) (config.KadInstance, *errors.ServerError) { +func GetInstanceByID(id string) (model.KadInstance, *servererrors.ServerError) { instances := ListInstances() for _, i := range instances { if i.ID == id { return i, nil } } - return config.KadInstance{}, errors.OfType(errors.OkdpServer). + return model.KadInstance{}, servererrors.OfType(servererrors.OkdpServer). NotFoundError("kad instance with id %s not found", id) } -func DoGet[T any](request *resty.Request) (*T, *errors.ServerError) { +func DoGet[T any](request *resty.Request) (*T, *servererrors.ServerError) { request.Method = resty.MethodGet return doExecute[T](request) } -func DoPut[T any](request *resty.Request) (*T, *errors.ServerError) { +func DoPut[T any](request *resty.Request) (*T, *servererrors.ServerError) { request.Method = resty.MethodPut return doExecute[T](request) } @@ -109,34 +110,34 @@ func (c *KadClient) NewRequest(url string) *resty.Request { return req } -func doExecute[T any](request *resty.Request) (*T, *errors.ServerError) { +func doExecute[T any](request *resty.Request) (*T, *servererrors.ServerError) { log.Info("Sending %s request to KAD at the endpoint %s:", request.Method, request.URL) var object T // request.SetError(&KadError{}) resp, err := request.Send() if err != nil { - return nil, errors.OfType(errors.Kad).Forbidden(err) + return nil, servererrors.OfType(servererrors.Kad).Forbidden(err) } if resp.IsError() { // KAD errors response are plain text - return nil, errors.OfType(errors.Kad). + return nil, servererrors.OfType(servererrors.Kad). GenericError(resp.StatusCode(), "Kad rejected the request, reason: %s", resp.String()) } err = json.Unmarshal([]byte(resp.String()), &object) if err != nil { - return &object, errors.OfType(errors.OkdpServer). + return &object, servererrors.OfType(servererrors.OkdpServer). GenericError(http.StatusUnprocessableEntity, "Unable to process kad response, reason: %+v", err) } return &object, nil } -func invalidInstanceError(provided string) *errors.ServerError { - instances := utils.Map(ListInstances(), func(k config.KadInstance) string { return k.ID }) - return errors.OfType(errors.OkdpServer). +func invalidInstanceError(provided string) *servererrors.ServerError { + instances := utils.Map(ListInstances(), func(k model.KadInstance) string { return k.ID }) + return servererrors.OfType(servererrors.OkdpServer). NotFoundError("kad instance with id %s not found, valid ones: %+v", provided, instances) } diff --git a/internal/kad/component_client.go b/internal/kad/component_client.go index ca08e67..997710b 100644 --- a/internal/kad/component_client.go +++ b/internal/kad/component_client.go @@ -18,9 +18,9 @@ package kad import ( "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/kad/client" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type ComponentClient struct { @@ -33,7 +33,7 @@ func NewComponentClient() *ComponentClient { } } -func (c ComponentClient) Get(kadInstanceID string, name string, catalog *string) (*model.Component, *errors.ServerError) { +func (c ComponentClient) Get(kadInstanceID string, name string, catalog *string) (*model.Component, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err @@ -45,7 +45,7 @@ func (c ComponentClient) Get(kadInstanceID string, name string, catalog *string) return client.DoGet[model.Component](req) } -func (c ComponentClient) List(kadInstanceID string, catalog *string) (*model.Components, *errors.ServerError) { +func (c ComponentClient) List(kadInstanceID string, catalog *string) (*model.Components, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err diff --git a/internal/kad/component_release_client.go b/internal/kad/component_release_client.go index b33db6d..9910244 100644 --- a/internal/kad/component_release_client.go +++ b/internal/kad/component_release_client.go @@ -23,10 +23,10 @@ import ( "github.com/go-resty/resty/v2" "github.com/goccy/go-yaml" "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/kad/client" log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type ComponentReleaseClient struct { @@ -39,7 +39,7 @@ func NewComponentReleaseClient() *ComponentReleaseClient { } } -func (c ComponentReleaseClient) Get(kadInstanceID string, name string, catalog *string) (*model.ComponentReleaseResponse, *errors.ServerError) { +func (c ComponentReleaseClient) Get(kadInstanceID string, name string, catalog *string) (*model.ComponentReleaseResponse, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err @@ -51,7 +51,7 @@ func (c ComponentReleaseClient) Get(kadInstanceID string, name string, catalog * return client.DoGet[model.ComponentReleaseResponse](req) } -func (c ComponentReleaseClient) List(kadInstanceID string, catalog *string) (*model.ComponentReleasesResponse, *errors.ServerError) { +func (c ComponentReleaseClient) List(kadInstanceID string, catalog *string) (*model.ComponentReleasesResponse, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err @@ -65,7 +65,7 @@ func (c ComponentReleaseClient) List(kadInstanceID string, catalog *string) (*mo func (c ComponentReleaseClient) UploadAsYaml(kadInstanceID string, name string, componentReleaseRequest model.ComponentReleaseRequest, - commitData map[string]string) (*model.GitCommit, *errors.ServerError) { + commitData map[string]string) (*model.GitCommit, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err @@ -78,7 +78,7 @@ func (c ComponentReleaseClient) UploadAsYaml(kadInstanceID string, name string, componentReleasesYAML, err2 := yaml.Marshal(result) if err2 != nil { log.Error("Error marshaling ComponentReleases to YAML: %v", err) - return nil, errors.OfType(errors.OkdpServer). + return nil, servererrors.OfType(servererrors.OkdpServer). GenericError(http.StatusBadRequest, "Unable to parse json to yaml: %+v", err2) } diff --git a/internal/kad/template_release_client.go b/internal/kad/template_release_client.go index da8e7e3..cae8d37 100644 --- a/internal/kad/template_release_client.go +++ b/internal/kad/template_release_client.go @@ -18,9 +18,9 @@ package kad import ( "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/kad/client" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type TemplateReleaseClient struct { @@ -33,7 +33,7 @@ func NewTemplateReleaseClient() *TemplateReleaseClient { } } -func (c TemplateReleaseClient) Get(kadInstanceID string, name string, catalog *string) (*model.TemplateRelease, *errors.ServerError) { +func (c TemplateReleaseClient) Get(kadInstanceID string, name string, catalog *string) (*model.TemplateRelease, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err @@ -45,7 +45,7 @@ func (c TemplateReleaseClient) Get(kadInstanceID string, name string, catalog *s return client.DoGet[model.TemplateRelease](req) } -func (c TemplateReleaseClient) List(kadInstanceID string, catalog *string) (*model.TemplateReleases, *errors.ServerError) { +func (c TemplateReleaseClient) List(kadInstanceID string, catalog *string) (*model.TemplateReleases, *servererrors.ServerError) { kadClient, err := c.KAD.ID(kadInstanceID) if err != nil { return nil, err diff --git a/internal/logging/logging.go b/internal/logging/logging.go index a81cc66..65c07bd 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -1,5 +1,5 @@ /* - * Copyright 2024 okdp.io + * Copyright 2025 okdp.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -99,6 +99,12 @@ func Panic(args ...interface{}) { // Logger returns a middleware that will write the logs to gin.DefaultWriter. // By default, gin.DefaultWriter = os.Stdout. func Logger() []gin.HandlerFunc { - return []gin.HandlerFunc{ginzap.Ginzap(instance.Desugar(), time.RFC3339, true), - ginzap.RecoveryWithZap(instance.Desugar(), true)} + logger := zap.NewNop() + + if gin.Mode() != gin.ReleaseMode { + logger = instance.Desugar() + } + + return []gin.HandlerFunc{ginzap.Ginzap(logger, time.RFC3339, true), + ginzap.RecoveryWithZap(logger, true)} } diff --git a/internal/model/catalog.go b/internal/model/catalog.go index ef9ef5a..59967be 100644 --- a/internal/model/catalog.go +++ b/internal/model/catalog.go @@ -1,5 +1,5 @@ /* - * Copyright 2024 okdp.io + * Copyright 2025 okdp.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,26 @@ package model import ( + "strings" + "github.com/okdp/okdp-server/api/openapi/v3/_api" ) -type Catalog = _api.Catalog -type Catalogs = []*Catalog +type Catalog struct { + _api.Catalog `mapstructure:",squash"` +} + +type Package = _api.Package + +func (c Catalog) RepoHost() string { + parts := strings.SplitN(c.RepoURL, "/", 2) + if len(parts) > 0 { + return parts[0] + } + return "" +} + +func (c Catalog) IsAuthenticated() bool { + return c.Credentials != nil +} + diff --git a/internal/model/kad.go b/internal/model/kad.go new file mode 100644 index 0000000..016d89c --- /dev/null +++ b/internal/model/kad.go @@ -0,0 +1,23 @@ +/* + * Copyright 2024 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package model + +import ( + "github.com/okdp/okdp-server/api/openapi/v3/_api" +) + +type KadInstance = _api.KadInstance diff --git a/internal/schema/parameters/schematic.go b/internal/schema/parameters/schematic.go new file mode 100644 index 0000000..0bbab52 --- /dev/null +++ b/internal/schema/parameters/schematic.go @@ -0,0 +1,31 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package schema + +type KuboSchema struct { + ParametersSchema *KuboSchemaItem `json:"parametersSchema"` + ContextSchema *KuboSchemaItem `json:"contextSchema"` +} + +type KuboSchemaItem struct { + Description string `json:"description,omitempty"` + Type string `json:"type,omitempty"` + Properties map[string]*KuboSchemaItem `json:"properties,omitempty"` + Items *KuboSchemaItem `json:"items,omitempty"` + Required bool `json:"required,omitempty"` + Default interface{} `json:"default,omitempty"` +} diff --git a/internal/schema/parameters/schematic_test.go b/internal/schema/parameters/schematic_test.go new file mode 100644 index 0000000..0fed1b3 --- /dev/null +++ b/internal/schema/parameters/schematic_test.go @@ -0,0 +1,249 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package schema + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParametersSchemaSimple(t *testing.T) { + // Given + jsonData := []byte(`{ + "parametersSchema": { + "properties": { + "hostname": { + "type": "string", + "required": false + }, + "tls": { + "type": "boolean", + "default": false + } + } + } + }`) + + // When + var s KuboSchema + err := json.Unmarshal(jsonData, &s) + + // Then + assert.NoError(t, err) + + assert.NotNil(t, s.ParametersSchema) + props := s.ParametersSchema.Properties + + assert.Contains(t, props, "hostname") + assert.Equal(t, "string", props["hostname"].Type) + assert.Equal(t, false, props["hostname"].Required) + + assert.Contains(t, props, "tls") + assert.Equal(t, "boolean", props["tls"].Type) + assert.Equal(t, false, props["tls"].Default) +} + +func TestParametersSchemaNested(t *testing.T) { + // Given + jsonData := []byte(`{ + "parametersSchema": { + "properties": { + "trust": { + "properties": { + "enabled": { + "type": "boolean", + "default": false + } + } + }, + "issuers": { + "properties": { + "enabled": { + "type": "boolean", + "default": true + }, + "caClusterIssuers": { + "items": { + "properties": { + "name": { + "type": "string", + "required": true + }, + "ca_crt": { + "type": "string", + "required": true + }, + "ca_key": { + "type": "string", + "required": true + } + } + } + }, + "selfSignedClusterIssuers": { + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "required": true + } + } + } + } + } + } + } + } + }`) + + // When + var s KuboSchema + err := json.Unmarshal(jsonData, &s) + + // Then + assert.NoError(t, err) + + // Validate top-level keys + assert.NotNil(t, s.ParametersSchema) + assert.Contains(t, s.ParametersSchema.Properties, "trust") + assert.Contains(t, s.ParametersSchema.Properties, "issuers") + + // Validate nested fields + trust := s.ParametersSchema.Properties["trust"] + assert.Contains(t, trust.Properties, "enabled") + assert.Equal(t, "boolean", trust.Properties["enabled"].Type) + assert.Equal(t, false, trust.Properties["enabled"].Default) + + issuers := s.ParametersSchema.Properties["issuers"] + assert.Contains(t, issuers.Properties, "enabled") + assert.Equal(t, true, issuers.Properties["enabled"].Default) + + caClusterIssuers := issuers.Properties["caClusterIssuers"] + assert.NotNil(t, caClusterIssuers.Items) + assert.Contains(t, caClusterIssuers.Items.Properties, "name") + assert.Equal(t, "string", caClusterIssuers.Items.Properties["name"].Type) +} + +func TestParametersSchemaExtended(t *testing.T) { + // Given + jsonData := []byte(`{ + "parametersSchema": { + "description": "Redis stack", + "properties": { + "redis": { + "required": false, + "properties": { + "password": { + "type": "string", + "default": "redis123" + }, + "replicaCount": { + "type": "integer", + "default": 1, + "description": "The number of replicas" + } + } + }, + "commander": { + "required": true, + "properties": { + "enabled": { + "type": "boolean", + "default": true + }, + "tls": { + "type": "boolean", + "default": false + }, + "hostname": { + "type": "string", + "required": false + } + } + } + } + } + }`) + + // When + var s KuboSchema + err := json.Unmarshal(jsonData, &s) + + // Then + assert.NoError(t, err) + + ps := s.ParametersSchema + assert.Equal(t, "Redis stack", ps.Description) + + redis := ps.Properties["redis"] + assert.NotNil(t, redis) + assert.False(t, redis.Required) + assert.Equal(t, "redis123", redis.Properties["password"].Default) + assert.Equal(t, float64(1), redis.Properties["replicaCount"].Default) + + commander := ps.Properties["commander"] + assert.NotNil(t, commander) + assert.True(t, commander.Required) + assert.Equal(t, true, commander.Properties["enabled"].Default) + assert.Equal(t, false, commander.Properties["tls"].Default) +} + +func TestContextSchema(t *testing.T) { + // Given + jsonData := []byte(`{ + "contextSchema": { + "properties": { + "ingress": { + "required": true, + "properties": { + "className": { + "type": "string", + "default": "nginx" + }, + "hostPostfix": { + "type": "string", + "required": true + } + } + } + } + } + }`) + + // When + var s KuboSchema + err := json.Unmarshal(jsonData, &s) + + // Then + assert.NoError(t, err) + + ingress := s.ContextSchema.Properties["ingress"] + assert.NotNil(t, ingress) + assert.True(t, ingress.Required) + + className := ingress.Properties["className"] + assert.NotNil(t, className) + assert.Equal(t, "string", className.Type) + assert.Equal(t, "nginx", className.Default) + + hostPostfix := ingress.Properties["hostPostfix"] + assert.NotNil(t, hostPostfix) + assert.True(t, hostPostfix.Required) +} diff --git a/internal/schema/release/release.go b/internal/schema/release/release.go new file mode 100644 index 0000000..2bb5fef --- /dev/null +++ b/internal/schema/release/release.go @@ -0,0 +1,51 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package schema + +// Release section +type Release struct { + APIVersion string `json:"apiVersion"` + Kind string `json:"kind"` + Metadata Metadata `json:"metadata"` + Spec Spec `json:"spec"` +} + +// Metadata section +type Metadata struct { + Name string `json:"name"` +} + +// Spec section +type Spec struct { + Protected bool `json:"protected"` + TargetNamespace string `json:"targetNamespace"` + CreateNamespace bool `json:"createNamespace"` + Debug Debug `json:"debug"` + Parameters map[string]interface{} `yaml:"parameters"` + Application Application `json:"application"` +} + +type Debug struct { + DumpContext bool `json:"dumpContext"` +} + +// Application section +type Application struct { + Repository string `json:"repository"` + Tag string `json:"tag"` + Interval string `json:"interval"` +} diff --git a/internal/security/authc/auth.go b/internal/security/authc/auth.go index ded4c4f..6f334c4 100644 --- a/internal/security/authc/auth.go +++ b/internal/security/authc/auth.go @@ -22,11 +22,11 @@ import ( "github.com/gin-gonic/gin" "github.com/okdp/okdp-server/internal/config" "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/security/authc/provider/basic" "github.com/okdp/okdp-server/internal/security/authc/provider/bearer" "github.com/okdp/okdp-server/internal/security/authc/provider/oidc" + "github.com/okdp/okdp-server/internal/servererrors" ) func Authenticator(authNConfig config.AuthN) []gin.HandlerFunc { @@ -64,7 +64,7 @@ func ensureUserAuthenticated() gin.HandlerFunc { _, found := c.Get(constants.OAuth2UserInfo) if !found { log.Warn("Failed to authenticate user") - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Authentication failed")) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Authentication failed")) return } } diff --git a/internal/security/authc/provider/bearer/bearer.go b/internal/security/authc/provider/bearer/bearer.go index 40fb9fb..d89adc3 100644 --- a/internal/security/authc/provider/bearer/bearer.go +++ b/internal/security/authc/provider/bearer/bearer.go @@ -25,9 +25,9 @@ import ( "github.com/gin-gonic/gin" "github.com/okdp/okdp-server/internal/config" "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/security/authc/model" + "github.com/okdp/okdp-server/internal/servererrors" "golang.org/x/net/context" ) @@ -73,14 +73,14 @@ func (p *Provider) authenticate() gin.HandlerFunc { err := p.verifyAccessToken(accessToken) if err != nil { log.Warn("Failed to verify access Token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to verify access Token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to verify access Token: "+err.Error())) return } userInfo, err = p.getUserInfo(accessToken) if err != nil { log.Warn("Unable to get user roles/groups from access token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) return } log.Debug("Successfully authenticated user : %s", userInfo.AsJSONString()) diff --git a/internal/security/authc/provider/oidc/oidc.go b/internal/security/authc/provider/oidc/oidc.go index c27c0d4..83b54d0 100644 --- a/internal/security/authc/provider/oidc/oidc.go +++ b/internal/security/authc/provider/oidc/oidc.go @@ -27,9 +27,9 @@ import ( "github.com/gin-gonic/gin" "github.com/okdp/okdp-server/internal/config" "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/security/authc/model" + "github.com/okdp/okdp-server/internal/servererrors" "github.com/okdp/okdp-server/internal/utils" "golang.org/x/net/context" "golang.org/x/oauth2" @@ -81,12 +81,12 @@ func NewProvider(oidcConf config.OpenIDAuth) (*Provider, error) { func (p *Provider) AuthLogin(c *gin.Context) { state, err := utils.RandomString() if err != nil { - c.JSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 state")) + c.JSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 state")) return } nonce, err := utils.RandomString() if err != nil { - c.JSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 nonce")) + c.JSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 nonce")) return } url := p.Config.AuthCodeURL(state, oidc.Nonce(nonce)) @@ -94,7 +94,7 @@ func (p *Provider) AuthLogin(c *gin.Context) { session.Set(constants.OAuth2State, state) session.Set(constants.OAuth2Nonce, nonce) if err = session.Save(); err != nil { - c.JSON(http.StatusInternalServerError, errors.OfType(errors.OkdpServer).GenericError(http.StatusInternalServerError, "Failed to save user session in cookie")) + c.JSON(http.StatusInternalServerError, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusInternalServerError, "Failed to save user session in cookie")) } c.Redirect(http.StatusTemporaryRedirect, url) } @@ -126,40 +126,40 @@ func (p *Provider) authenticate() gin.HandlerFunc { state := session.Get(constants.OAuth2State) if c.Query("state") != state { log.Warn("Invalid authentication OAuth2 state") - c.AbortWithStatusJSON(http.StatusBadRequest, errors.OfType(errors.OkdpServer).GenericError(http.StatusBadRequest, "Invalid authentication OAuth2 'state': "+state.(string))) + c.AbortWithStatusJSON(http.StatusBadRequest, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusBadRequest, "Invalid authentication OAuth2 'state': "+state.(string))) return } // Exchange the authorization code for an access token token, err := p.Config.Exchange(p.Context, c.Query("code")) if err != nil { log.Warn("Failed to exchange the authorization code with an access token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to exchange authorization code with an access token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to exchange authorization code with an access token: "+err.Error())) return } rawIDToken, ok := token.Extra("id_token").(string) if !ok { log.Warn("No id_token field found in the OAuth2 token") - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "No id_token field found in the OAuth2 token")) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "No id_token field found in the OAuth2 token")) return } idToken, err := p.Verify(p.Context, rawIDToken) if err != nil { log.Warn("Failed to verify the ID Token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to verify the ID Token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to verify the ID Token: "+err.Error())) return } nonce := session.Get(constants.OAuth2Nonce) if idToken.Nonce != nonce { log.Warn("Invalid authentication OAuth2 'nonce': %s", nonce.(string)) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Invalid authentication OAuth2 'nonce': "+nonce.(string))) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Invalid authentication OAuth2 'nonce': "+nonce.(string))) return } userInfo, err = p.getUserInfo(token.AccessToken) if err != nil { log.Warn("Unable to get user roles/groups from the access token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) return } // Retrieve the user information from the access token diff --git a/internal/security/authz/authz.go b/internal/security/authz/authz.go index bb3ad7a..51d92d5 100644 --- a/internal/security/authz/authz.go +++ b/internal/security/authz/authz.go @@ -28,9 +28,9 @@ import ( "github.com/gin-gonic/gin" "github.com/okdp/okdp-server/internal/config" "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/errors" log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/security/authc/model" + "github.com/okdp/okdp-server/internal/servererrors" "github.com/okdp/okdp-server/internal/utils" ) @@ -80,7 +80,7 @@ func (e *Enforcer) authorize() gin.HandlerFunc { userInfo, ok := c.Get(constants.OAuth2UserInfo) if !ok { log.Warn("Unable to authorize user, no user informtaion found in context") - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to authorize user, no user informtaion found in context")) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to authorize user, no user informtaion found in context")) return } email := userInfo.(*model.UserInfo).Email @@ -106,12 +106,12 @@ func (e *Enforcer) authorize() gin.HandlerFunc { if err != nil { log.Warn("Unable to authorize user (%s/%s): %s", email, sub, err.Error()) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, err.Error())) return } if !allowed { log.Warn("User (%s/%s) not allowed to execute the action", email, sub) - c.AbortWithStatusJSON(http.StatusUnauthorized, errors.OfType(errors.OkdpServer).GenericError(http.StatusUnauthorized, "Unauthorized action")) + c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unauthorized action")) return } diff --git a/internal/errors/server_errors.go b/internal/servererrors/server_errors.go similarity index 81% rename from internal/errors/server_errors.go rename to internal/servererrors/server_errors.go index 253a41e..5ae16e1 100644 --- a/internal/errors/server_errors.go +++ b/internal/servererrors/server_errors.go @@ -1,4 +1,4 @@ -package errors +package servererrors import ( "fmt" @@ -11,8 +11,9 @@ type ServerError _api.ServerError const ( // Error types - Kad = "kad" OkdpServer = "okdp_server" + Registry = "registry" + Kad = "kad" ) func OfType(errorType string) *ServerError { @@ -33,6 +34,12 @@ func (s *ServerError) Forbidden(messages ...interface{}) *ServerError { return s } +func (s *ServerError) UnprocessableEntity(messages ...interface{}) *ServerError { + s.Message = toError(messages...) + s.Status = http.StatusUnprocessableEntity + return s +} + func (s *ServerError) GenericError(statusCode int, messages ...interface{}) *ServerError { s.Message = toError(messages...) s.Status = statusCode diff --git a/internal/services/catalog.go b/internal/services/catalog.go index 95eaab1..26c29e5 100644 --- a/internal/services/catalog.go +++ b/internal/services/catalog.go @@ -1,5 +1,5 @@ /* - * Copyright 2024 okdp.io + * Copyright 2025 okdp.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,25 +17,45 @@ package services import ( - "github.com/okdp/okdp-server/internal/errors" - "github.com/okdp/okdp-server/internal/kad" + "github.com/okdp/okdp-server/internal/integrations/registry" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type CatalogService struct { - catalog *kad.CatalogClient + catalog *registry.RepoCatalog } func NewCatalogService() *CatalogService { return &CatalogService{ - catalog: kad.NewCatalogClient(), + catalog: registry.NewRepoCatalog(), } } -func (s CatalogService) Get(kadInstanceID string, name string) (*model.Catalog, *errors.ServerError) { - return s.catalog.Get(kadInstanceID, name) +func (s CatalogService) ListCatalogs() []*model.Catalog { + return s.catalog.ListCatalogs() } -func (s CatalogService) List(kadInstanceID string) (*model.Catalogs, *errors.ServerError) { - return s.catalog.List(kadInstanceID) +func (s CatalogService) GetCatalog(catalogID string) (*model.Catalog, *servererrors.ServerError) { + return s.catalog.GetCatalog(catalogID) } + +func (s CatalogService) GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) { + return s.catalog.GetPackages(catalogID) +} + +func (s CatalogService) GetPackageByName(catalogID string, name string) (*model.Package, *servererrors.ServerError) { + return s.catalog.GetPackageByName(catalogID, name) +} + +func (s CatalogService) GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *servererrors.ServerError) { + return s.catalog.GetPackageDefinition(catalogID, name, version) +} + +// func (s CatalogService) GetDefinition(name string) (*model.Catalog, *errors.ServerError) { +// return s.catalog.GetDefinition(name) +// } + +// func (s CatalogService) GetTags(name string) (*model.Catalog, *errors.ServerError) { +// return s.catalog.GetTags(name) +// } diff --git a/internal/services/component.go b/internal/services/component.go index c1fa13f..039f796 100644 --- a/internal/services/component.go +++ b/internal/services/component.go @@ -17,9 +17,9 @@ package services import ( - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/kad" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type ComponentService struct { @@ -32,10 +32,10 @@ func NewComponentService() *ComponentService { } } -func (s ComponentService) Get(kadInstanceID string, name string, catalog *string) (*model.Component, *errors.ServerError) { +func (s ComponentService) Get(kadInstanceID string, name string, catalog *string) (*model.Component, *servererrors.ServerError) { return s.component.Get(kadInstanceID, name, catalog) } -func (s ComponentService) List(kadInstanceID string, catalog *string) (*model.Components, *errors.ServerError) { +func (s ComponentService) List(kadInstanceID string, catalog *string) (*model.Components, *servererrors.ServerError) { return s.component.List(kadInstanceID, catalog) } diff --git a/internal/services/component_releases.go b/internal/services/component_releases.go index 943aa04..a8ef60c 100644 --- a/internal/services/component_releases.go +++ b/internal/services/component_releases.go @@ -17,9 +17,9 @@ package services import ( - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/kad" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type ComponentReleaseService struct { @@ -32,14 +32,14 @@ func NewComponentReleaseService() *ComponentReleaseService { } } -func (s ComponentReleaseService) Get(kadInstanceID string, name string, catalog *string) (*model.ComponentReleaseResponse, *errors.ServerError) { +func (s ComponentReleaseService) Get(kadInstanceID string, name string, catalog *string) (*model.ComponentReleaseResponse, *servererrors.ServerError) { return s.componentRelease.Get(kadInstanceID, name, catalog) } -func (s ComponentReleaseService) List(kadInstanceID string, catalog *string) (*model.ComponentReleasesResponse, *errors.ServerError) { +func (s ComponentReleaseService) List(kadInstanceID string, catalog *string) (*model.ComponentReleasesResponse, *servererrors.ServerError) { return s.componentRelease.List(kadInstanceID, catalog) } -func (s ComponentReleaseService) CreateOrUpdateComponentRelease(kadInstanceID string, name string, componentReleaseRequest model.ComponentReleaseRequest, commitData map[string]string) (*model.GitCommit, *errors.ServerError) { +func (s ComponentReleaseService) CreateOrUpdateComponentRelease(kadInstanceID string, name string, componentReleaseRequest model.ComponentReleaseRequest, commitData map[string]string) (*model.GitCommit, *servererrors.ServerError) { return s.componentRelease.UploadAsYaml(kadInstanceID, name, componentReleaseRequest, commitData) } diff --git a/internal/services/service.go b/internal/services/service.go index abeb608..c9c3762 100644 --- a/internal/services/service.go +++ b/internal/services/service.go @@ -17,8 +17,8 @@ package services import ( - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type Service struct { @@ -33,7 +33,7 @@ func NewService() (*Service, error) { }, nil } -func (s Service) List(kadInstanceID string, catalog *string) (*model.Services, *errors.ServerError) { +func (s Service) List(kadInstanceID string, catalog *string) (*model.Services, *servererrors.ServerError) { componentReleases, err := s.componentReleaseService.List(kadInstanceID, catalog) if err != nil { return nil, err diff --git a/internal/services/template_release.go b/internal/services/template_release.go index d2dd31d..0ca3e71 100644 --- a/internal/services/template_release.go +++ b/internal/services/template_release.go @@ -17,9 +17,9 @@ package services import ( - "github.com/okdp/okdp-server/internal/errors" "github.com/okdp/okdp-server/internal/kad" "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/servererrors" ) type TemplateReleaseService struct { @@ -32,10 +32,10 @@ func NewTemplateReleaseService() *TemplateReleaseService { } } -func (s TemplateReleaseService) Get(kadInstanceID string, name string, catalog *string) (*model.TemplateRelease, *errors.ServerError) { +func (s TemplateReleaseService) Get(kadInstanceID string, name string, catalog *string) (*model.TemplateRelease, *servererrors.ServerError) { return s.templateRelease.Get(kadInstanceID, name, catalog) } -func (s TemplateReleaseService) List(kadInstanceID string, catalog *string) (*model.TemplateReleases, *errors.ServerError) { +func (s TemplateReleaseService) List(kadInstanceID string, catalog *string) (*model.TemplateReleases, *servererrors.ServerError) { return s.templateRelease.List(kadInstanceID, catalog) } diff --git a/internal/utils/collection_utils_test.go b/internal/utils/collection_utils_test.go index f9c8f76..01be831 100644 --- a/internal/utils/collection_utils_test.go +++ b/internal/utils/collection_utils_test.go @@ -22,7 +22,7 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_Map_function(t *testing.T) { +func TestMapfunction(t *testing.T) { // Given numbers := []int{1, 2, 3} diff --git a/internal/utils/env_utils.go b/internal/utils/env_utils.go new file mode 100644 index 0000000..1c05eb2 --- /dev/null +++ b/internal/utils/env_utils.go @@ -0,0 +1,38 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "os" + "strings" +) + +// GetEnv reads an environment variable. If the value is a placeholder like $(VAR_NAME), +// it will replace it with the actual value from the environment variable. +// If the value is not a placeholder, it returns the value as is. +func GetEnv(key string) string { + // Check if the key has the $(...) format + if strings.HasPrefix(key, "$(") && strings.HasSuffix(key, ")") { + varName := strings.TrimPrefix(key, "$(") + varName = strings.TrimSuffix(varName, ")") + if value, exists := os.LookupEnv(varName); exists { + return value + } + return "" + } + return key +} diff --git a/internal/utils/env_utils_test.go b/internal/utils/env_utils_test.go new file mode 100644 index 0000000..e1d8005 --- /dev/null +++ b/internal/utils/env_utils_test.go @@ -0,0 +1,42 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "os" + "testing" +) + +func TestGetEnv(t *testing.T) { + // Test the behavior when the environment variable is set + os.Setenv("OCI_USERNAME", "myusername") + defer os.Unsetenv("OCI_USERNAME") + + if got := GetEnv("$(OCI_USERNAME)"); got != "myusername" { + t.Errorf("expected 'myusername', got %s", got) + } + + // Test when the environment variable does not exist + if got := GetEnv("$(NON_EXISTENT_VAR)"); got != "" { + t.Errorf("expected '', got %s", got) + } + + // Test non-placeholder value + if got := GetEnv("JustSomeOtherValue"); got != "JustSomeOtherValue" { + t.Errorf("expected 'JustSomeOtherValue', got %s", got) + } +} diff --git a/internal/utils/versioning_utils.go b/internal/utils/versioning_utils.go new file mode 100644 index 0000000..bef2755 --- /dev/null +++ b/internal/utils/versioning_utils.go @@ -0,0 +1,68 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "sort" + "strings" + + "github.com/Masterminds/semver/v3" +) + +// SortVersions sorts a list of version strings in descending order. +// +// - Versions are expected to follow semantic versioning (SemVer). +// - Versions that begin with a 'v' (e.g. "v1.2.3") are supported and normalized for sorting. +// - Invalid SemVer strings are placed at the end of the result list in the original order. +// +// Example: +// +// input: []string{"v2.0.0", "v1.0.0", "invalid"} +// output: []string{"v2.0.0", "v1.0.0", "invalid"} +func SortVersions(versions []string) []string { + type versionWithOriginal struct { + Original string + Version *semver.Version + } + + validVersions := make([]versionWithOriginal, 0, len(versions)) + var invalidVersions []string + + for _, v := range versions { + parsed := strings.TrimPrefix(v, "v") + sv, err := semver.NewVersion(parsed) + if err != nil { + invalidVersions = append(invalidVersions, v) + continue + } + validVersions = append(validVersions, versionWithOriginal{ + Original: v, + Version: sv, + }) + } + + sort.Slice(validVersions, func(i, j int) bool { + return validVersions[i].Version.GreaterThan(validVersions[j].Version) + }) + + sorted := make([]string, 0, len(versions)) + for _, v := range validVersions { + sorted = append(sorted, v.Original) + } + + return append(sorted, invalidVersions...) +} diff --git a/internal/utils/versioning_utils_test.go b/internal/utils/versioning_utils_test.go new file mode 100644 index 0000000..9324586 --- /dev/null +++ b/internal/utils/versioning_utils_test.go @@ -0,0 +1,55 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSortVersions(t *testing.T) { + tests := []struct { + versions []string + expected []string + }{ + { + versions: []string{"1.0.0", "1.2.0", "2.0.0", "1.1.1", "invalid", "v2.1.0"}, + expected: []string{"v2.1.0", "2.0.0", "1.2.0", "1.1.1", "1.0.0", "invalid"}, + }, + { + versions: []string{"v2.1.0", "1.0.0", "v1.1.0", "v3.0.0", "1.1.1", "v2.0.0"}, + expected: []string{"v3.0.0", "v2.1.0", "v2.0.0", "1.1.1", "v1.1.0", "1.0.0"}, + }, + { + versions: []string{"v1.0.0", "invalid", "v2.2.0"}, + expected: []string{"v2.2.0", "v1.0.0", "invalid"}, + }, + { + versions: []string{"invalid", "v1.0.0", "v2.0.0"}, + expected: []string{"v2.0.0", "v1.0.0", "invalid"}, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("Sorting %v", test.versions), func(t *testing.T) { + result := SortVersions(test.versions) + assert.Equal(t, test.expected, result) + }) + } +} From 4a86f13ba91f5479b2ec6635bad17e339a7121a6 Mon Sep 17 00:00:00 2001 From: iizitounene Date: Tue, 22 Apr 2025 17:27:39 +0200 Subject: [PATCH 02/14] ci: remove credentials from public registries --- .local/application-local.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.local/application-local.yaml b/.local/application-local.yaml index 8b34ce8..ddf46ea 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -101,10 +101,10 @@ catalog: name: Auth catalog description: My Auth packages repoUrl: quay.io/kubocd/packages - ### private registry, credentials needed - credentials: - robotAccountName: $(OCI_USERNAME) - robotAccountToken: $(OCI_PASSWORD) + ### public registry, no credentials needed + #credentials: + # robotAccountName: $(OCI_USERNAME) + # robotAccountToken: $(OCI_PASSWORD) packages: - name: openldap @@ -112,10 +112,10 @@ catalog: name: Infra catalog description: My Infra packages repoUrl: quay.io/kubocd/packages - ### Private registry, credentials needed - credentials: - robotAccountName: $(OCI_USERNAME) - robotAccountToken: $(OCI_PASSWORD) + ### public registry, no credentials needed + #credentials: + # robotAccountName: $(OCI_USERNAME) + # robotAccountToken: $(OCI_PASSWORD) packages: - name: podinfo - name: cert-manager @@ -126,10 +126,10 @@ catalog: name: Stack catalog description: My Stack packages repoUrl: quay.io/kubocd/packages - ### Private registry, credentials needed - credentials: - robotAccountName: $(OCI_USERNAME) - robotAccountToken: $(OCI_PASSWORD) + ### public registry, no credentials needed + #credentials: + # robotAccountName: $(OCI_USERNAME) + # robotAccountToken: $(OCI_PASSWORD) packages: - name: stack1 From a471b9e1c578a3334b9a2eea925891a529eb201c Mon Sep 17 00:00:00 2001 From: iizitounene Date: Wed, 23 Apr 2025 12:24:49 +0200 Subject: [PATCH 03/14] chore: remove all references to kad v1 --- .local/application-local.yaml | 21 - .local/authz-policy.csv | 12 - README.md | 61 --- .../componentreleases-server.go | 229 -------- .../v3/_api/components/components-server.go | 153 ------ api/openapi/v3/_api/kad/kad-server.go | 99 ---- .../v3/_api/services/services-server.go | 99 ---- api/openapi/v3/_api/spec.go | 72 +-- .../templatereleases-server.go | 153 ------ api/openapi/v3/_api/types.go | 504 ------------------ api/openapi/v3/api.yaml | 70 +-- api/openapi/v3/definition/Component.yaml | 226 -------- .../definition/ComponentReleasePayload.yaml | 67 --- .../definition/ComponentReleaseRequest.yaml | 17 - .../definition/ComponentReleaseResponse.yaml | 125 ----- api/openapi/v3/definition/FlatComponent.yaml | 47 -- api/openapi/v3/definition/KadInstance.yaml | 23 - api/openapi/v3/definition/Service.yaml | 23 - .../v3/definition/TemplateRelease.yaml | 73 --- .../component-releases-by-name.yaml | 88 --- .../componentreleases/component-releases.yaml | 41 -- .../paths/components/component-by-name.yaml | 46 -- .../v3/paths/components/component.yaml | 40 -- .../v3/paths/kad/kad-instance-by-name.yaml | 33 -- api/openapi/v3/paths/kad/kad-instance.yaml | 26 - api/openapi/v3/paths/services/service.yaml | 40 -- .../template-releases-by-name.yaml | 40 -- .../templatereleases/template-releases.yaml | 40 -- go.mod | 6 +- go.sum | 9 + internal/config/config.go | 11 +- internal/config/config_test.go | 13 - internal/config/testdata/application.yaml | 7 - internal/constants/constants.go | 10 - internal/controllers/component_controller.go | 65 --- .../component_release_controller.go | 92 ---- internal/controllers/kad_contoller.go | 49 -- internal/controllers/register.go | 11 - internal/controllers/service_controller.go | 50 -- .../template_release_controller.go | 62 --- .../git/client/client.go} | 10 +- .../git/git_repo.go} | 11 +- internal/kad/client/client.go | 143 ----- internal/kad/component_client.go | 58 -- internal/kad/component_release_client.go | 100 ---- internal/kad/template_release_client.go | 58 -- internal/model/catalog.go | 1 - internal/model/component_release.go | 87 --- internal/model/service.go | 26 - internal/model/template_release.go | 62 --- internal/servererrors/server_errors.go | 1 - internal/services/component.go | 41 -- internal/services/component_releases.go | 45 -- internal/services/service.go | 47 -- internal/services/template_release.go | 41 -- 55 files changed, 45 insertions(+), 3539 deletions(-) delete mode 100644 api/openapi/v3/_api/componentreleases/componentreleases-server.go delete mode 100644 api/openapi/v3/_api/components/components-server.go delete mode 100644 api/openapi/v3/_api/kad/kad-server.go delete mode 100644 api/openapi/v3/_api/services/services-server.go delete mode 100644 api/openapi/v3/_api/templatereleases/templatereleases-server.go delete mode 100644 api/openapi/v3/definition/Component.yaml delete mode 100644 api/openapi/v3/definition/ComponentReleasePayload.yaml delete mode 100644 api/openapi/v3/definition/ComponentReleaseRequest.yaml delete mode 100644 api/openapi/v3/definition/ComponentReleaseResponse.yaml delete mode 100644 api/openapi/v3/definition/FlatComponent.yaml delete mode 100644 api/openapi/v3/definition/KadInstance.yaml delete mode 100644 api/openapi/v3/definition/Service.yaml delete mode 100644 api/openapi/v3/definition/TemplateRelease.yaml delete mode 100644 api/openapi/v3/paths/componentreleases/component-releases-by-name.yaml delete mode 100644 api/openapi/v3/paths/componentreleases/component-releases.yaml delete mode 100644 api/openapi/v3/paths/components/component-by-name.yaml delete mode 100644 api/openapi/v3/paths/components/component.yaml delete mode 100644 api/openapi/v3/paths/kad/kad-instance-by-name.yaml delete mode 100644 api/openapi/v3/paths/kad/kad-instance.yaml delete mode 100644 api/openapi/v3/paths/services/service.yaml delete mode 100644 api/openapi/v3/paths/templatereleases/template-releases-by-name.yaml delete mode 100644 api/openapi/v3/paths/templatereleases/template-releases.yaml delete mode 100644 internal/controllers/component_controller.go delete mode 100644 internal/controllers/component_release_controller.go delete mode 100644 internal/controllers/kad_contoller.go delete mode 100644 internal/controllers/service_controller.go delete mode 100644 internal/controllers/template_release_controller.go rename internal/{model/kad.go => integrations/git/client/client.go} (80%) rename internal/{model/component.go => integrations/git/git_repo.go} (77%) delete mode 100644 internal/kad/client/client.go delete mode 100644 internal/kad/component_client.go delete mode 100644 internal/kad/component_release_client.go delete mode 100644 internal/kad/template_release_client.go delete mode 100644 internal/model/component_release.go delete mode 100644 internal/model/service.go delete mode 100644 internal/model/template_release.go delete mode 100644 internal/services/component.go delete mode 100644 internal/services/component_releases.go delete mode 100644 internal/services/service.go delete mode 100644 internal/services/template_release.go diff --git a/.local/application-local.yaml b/.local/application-local.yaml index ddf46ea..03e17f9 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -133,25 +133,4 @@ catalog: packages: - name: stack1 -kad: - - id: sandbox - name: Sandbox de idir - apiUrl: https://host.docker.internal:6553 - authBearer: 4Ys3brdqnD5LVjf6hLcQsSQbHWLh5asJ - insecureSkipVerify: true - - id: sandbox2 - name: Sandbox2 de idir - apiUrl: https://host.docker.internal:6553 - authBearer: 4Ys3brdqnD5LVjf6hLcQsSQbHWLh5asJ - insecureSkipVerify: true - - id: sandbox3 - name: Sandbox3 de idir - apiUrl: https://host.docker.internal:6553 - authBearer: 4Ys3brdqnD5LVjf6hLcQsSQbHWLh5asJ - insecureSkipVerify: true - - id: sandbox4 - name: Sandbox4 de idir - apiUrl: https://host.docker.internal:6553 - authBearer: 4Ys3brdqnD5LVjf6hLcQsSQbHWLh5asJ - insecureSkipVerify: true diff --git a/.local/authz-policy.csv b/.local/authz-policy.csv index f50c42a..358e6bc 100644 --- a/.local/authz-policy.csv +++ b/.local/authz-policy.csv @@ -2,18 +2,6 @@ p, role:viewers, /api/v1/users/myprofile, * p, role:viewers, /api/v1/catalogs, * p, role:viewers, /api/v1/catalogs/*, * - -p, role:viewers, /api/v1/kad, * -p, role:viewers, /api/v1/kad/*/services, * -p, role:viewers, /api/v1/kad/*/catalog, * -p, role:viewers, /api/v1/kad/*/catalog/*, * -p, role:viewers, /api/v1/kad/*/componentreleases, * -p, role:viewers, /api/v1/kad/*/componentreleases/*, * -p, role:viewers, /api/v1/kad/*/templatereleases, * -p, role:viewers, /api/v1/kad/*/templatereleases/*, * -p, role:viewers, /api/v1/kad/*/components, * -p, role:viewers, /api/v1/kad/*/components/*, * - g, role:admins, role:developers g, role:developers, role:viewers diff --git a/README.md b/README.md index c1cad2b..7b57b9e 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,6 @@ Manually add the following entry in /etc/hosts 127.0.0.1 keycloak ``` -Forward kad webserver to localhost: - -```shell -kubectl port-forward svc/kad-webserver 6553:6553 -``` - ### Start Start docker compose using your robot account token to access private registries: @@ -40,61 +34,6 @@ adm1/user view1/user -```shell - -kadcli git remove projectA-1.yaml -m "Test remove" -n "idir" --insecureSkipVerify -kadcli git add -m "test add" -n"idir" projectA-1.yaml --insecureSkipVerify - -curl -H "Authorization: Bearer HEDG296X4XjnjETBJ1HGEUEqQbn3pNaD" -X PUT 'https://kad.ingress.kind.local/api/git/v1/mycluster/deployments/minio3.yaml' -F kadfile=@.tmp/z.tmp/curl/minio3.yaml -F commit-message='A commit Message' -F committer-name='Serge' -F committer-email='serge@example.com' -k - - -kadcli kad componentReleases apply --insecureSkipVerify minio1 -kadcli kad componentReleases apply --insecureSkipVerify _all_ - -``` - - -http://localhost:8092/#/componentreleases/CreateOrUpdateComponentRelease -``` -{ - "comment": "Create minio deployment example", - "gitRepoFolder": "deployments", - "componentReleases": [ - { - "name": "minio3", - "component": { - "name": "minio", - "version": "1.0.0", - "protected": true, - "config": { - "install": { - "createNamespace": true - } - }, - "parameters": { - "ingressName": "minio3", - "ldap": "openldap" - }, - "parameterFiles": [ - { - "document": "minio-flavor-small" - }, - { - "document": "data1-minio-parameters", - "unwrap": "minio" - } - ] - }, - "namespace": "minio3", - "dependsOn": [ - "ldapLocalServer" - ] - } - ] -} -``` - - # Helm ``` diff --git a/api/openapi/v3/_api/componentreleases/componentreleases-server.go b/api/openapi/v3/_api/componentreleases/componentreleases-server.go deleted file mode 100644 index cb3a87f..0000000 --- a/api/openapi/v3/_api/componentreleases/componentreleases-server.go +++ /dev/null @@ -1,229 +0,0 @@ -// Package _componentreleases provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. -package _componentreleases - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/oapi-codegen/runtime" -) - -// ListComponentReleasesParams defines parameters for ListComponentReleases. -type ListComponentReleasesParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// GetComponentReleaseParams defines parameters for GetComponentRelease. -type GetComponentReleaseParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// CreateOrUpdateComponentReleaseJSONBody defines parameters for CreateOrUpdateComponentRelease. -type CreateOrUpdateComponentReleaseJSONBody struct { - Comment string `json:"comment"` - ComponentReleases []struct { - Component struct { - // Config Additional configuration - Config *map[string]interface{} `json:"config,omitempty"` - Name string `json:"name"` - ParameterFiles *[]struct { - Document *string `json:"document,omitempty"` - File *string `json:"file,omitempty"` - Unwrap *string `json:"unwrap,omitempty"` - Wrap *string `json:"wrap,omitempty"` - } `json:"parameterFiles,omitempty"` - - // Parameters List of paramters as key/value pairs - Parameters *map[string]interface{} `json:"parameters,omitempty"` - Protected *bool `json:"protected,omitempty"` - Source *struct { - Version string `json:"version"` - } `json:"source,omitempty"` - Suspended *bool `json:"suspended,omitempty"` - - // Values List of values as key/value pairs - Values *map[string]interface{} `json:"values,omitempty"` - Version string `json:"version"` - } `json:"component"` - DependsOn *[]string `json:"dependsOn,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Name string `json:"name"` - Namespace *string `json:"namespace,omitempty"` - Roles *[]string `json:"roles,omitempty"` - } `json:"componentReleases"` - GitRepoFolder string `json:"gitRepoFolder"` -} - -// CreateOrUpdateComponentReleaseJSONRequestBody defines body for CreateOrUpdateComponentRelease for application/json ContentType. -type CreateOrUpdateComponentReleaseJSONRequestBody CreateOrUpdateComponentReleaseJSONBody - -// ServerInterface represents all server handlers. -type ServerInterface interface { - // List all component releases - // (GET /kad/{kadInstanceId}/componentreleases) - ListComponentReleases(c *gin.Context, kadInstanceId string, params ListComponentReleasesParams) - // Get a component release by name - // (GET /kad/{kadInstanceId}/componentreleases/{name}) - GetComponentRelease(c *gin.Context, kadInstanceId string, name string, params GetComponentReleaseParams) - // Create or update a component release - // (PUT /kad/{kadInstanceId}/componentreleases/{name}) - CreateOrUpdateComponentRelease(c *gin.Context, kadInstanceId string, name string) -} - -// ServerInterfaceWrapper converts contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface - HandlerMiddlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -type MiddlewareFunc func(c *gin.Context) - -// ListComponentReleases operation middleware -func (siw *ServerInterfaceWrapper) ListComponentReleases(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params ListComponentReleasesParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.ListComponentReleases(c, kadInstanceId, params) -} - -// GetComponentRelease operation middleware -func (siw *ServerInterfaceWrapper) GetComponentRelease(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // ------------- Path parameter "name" ------------- - var name string - - err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params GetComponentReleaseParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.GetComponentRelease(c, kadInstanceId, name, params) -} - -// CreateOrUpdateComponentRelease operation middleware -func (siw *ServerInterfaceWrapper) CreateOrUpdateComponentRelease(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // ------------- Path parameter "name" ------------- - var name string - - err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.CreateOrUpdateComponentRelease(c, kadInstanceId, name) -} - -// GinServerOptions provides options for the Gin server. -type GinServerOptions struct { - BaseURL string - Middlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. -func RegisterHandlers(router gin.IRouter, si ServerInterface) { - RegisterHandlersWithOptions(router, si, GinServerOptions{}) -} - -// RegisterHandlersWithOptions creates http.Handler with additional options -func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { - errorHandler := options.ErrorHandler - if errorHandler == nil { - errorHandler = func(c *gin.Context, err error, statusCode int) { - c.JSON(statusCode, gin.H{"msg": err.Error()}) - } - } - - wrapper := ServerInterfaceWrapper{ - Handler: si, - HandlerMiddlewares: options.Middlewares, - ErrorHandler: errorHandler, - } - - router.GET(options.BaseURL+"/kad/:kadInstanceId/componentreleases", wrapper.ListComponentReleases) - router.GET(options.BaseURL+"/kad/:kadInstanceId/componentreleases/:name", wrapper.GetComponentRelease) - router.PUT(options.BaseURL+"/kad/:kadInstanceId/componentreleases/:name", wrapper.CreateOrUpdateComponentRelease) -} diff --git a/api/openapi/v3/_api/components/components-server.go b/api/openapi/v3/_api/components/components-server.go deleted file mode 100644 index 29acf8e..0000000 --- a/api/openapi/v3/_api/components/components-server.go +++ /dev/null @@ -1,153 +0,0 @@ -// Package _components provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. -package _components - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/oapi-codegen/runtime" -) - -// ListComponentsParams defines parameters for ListComponents. -type ListComponentsParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// GetComponentsByNameParams defines parameters for GetComponentsByName. -type GetComponentsByNameParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - // List all components - // (GET /kad/{kadInstanceId}/components) - ListComponents(c *gin.Context, kadInstanceId string, params ListComponentsParams) - // Get a components by name - // (GET /kad/{kadInstanceId}/components/{name}) - GetComponentsByName(c *gin.Context, kadInstanceId string, name string, params GetComponentsByNameParams) -} - -// ServerInterfaceWrapper converts contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface - HandlerMiddlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -type MiddlewareFunc func(c *gin.Context) - -// ListComponents operation middleware -func (siw *ServerInterfaceWrapper) ListComponents(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params ListComponentsParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.ListComponents(c, kadInstanceId, params) -} - -// GetComponentsByName operation middleware -func (siw *ServerInterfaceWrapper) GetComponentsByName(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // ------------- Path parameter "name" ------------- - var name string - - err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params GetComponentsByNameParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.GetComponentsByName(c, kadInstanceId, name, params) -} - -// GinServerOptions provides options for the Gin server. -type GinServerOptions struct { - BaseURL string - Middlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. -func RegisterHandlers(router gin.IRouter, si ServerInterface) { - RegisterHandlersWithOptions(router, si, GinServerOptions{}) -} - -// RegisterHandlersWithOptions creates http.Handler with additional options -func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { - errorHandler := options.ErrorHandler - if errorHandler == nil { - errorHandler = func(c *gin.Context, err error, statusCode int) { - c.JSON(statusCode, gin.H{"msg": err.Error()}) - } - } - - wrapper := ServerInterfaceWrapper{ - Handler: si, - HandlerMiddlewares: options.Middlewares, - ErrorHandler: errorHandler, - } - - router.GET(options.BaseURL+"/kad/:kadInstanceId/components", wrapper.ListComponents) - router.GET(options.BaseURL+"/kad/:kadInstanceId/components/:name", wrapper.GetComponentsByName) -} diff --git a/api/openapi/v3/_api/kad/kad-server.go b/api/openapi/v3/_api/kad/kad-server.go deleted file mode 100644 index fccb608..0000000 --- a/api/openapi/v3/_api/kad/kad-server.go +++ /dev/null @@ -1,99 +0,0 @@ -// Package _kad provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. -package _kad - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/oapi-codegen/runtime" -) - -// ServerInterface represents all server handlers. -type ServerInterface interface { - // List all KAD configured instances - // (GET /kad) - ListKadInstances(c *gin.Context) - // Get KAD instance by name - // (GET /kad/{kadInstanceId}) - GetKadInstance(c *gin.Context, kadInstanceId string) -} - -// ServerInterfaceWrapper converts contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface - HandlerMiddlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -type MiddlewareFunc func(c *gin.Context) - -// ListKadInstances operation middleware -func (siw *ServerInterfaceWrapper) ListKadInstances(c *gin.Context) { - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.ListKadInstances(c) -} - -// GetKadInstance operation middleware -func (siw *ServerInterfaceWrapper) GetKadInstance(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.GetKadInstance(c, kadInstanceId) -} - -// GinServerOptions provides options for the Gin server. -type GinServerOptions struct { - BaseURL string - Middlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. -func RegisterHandlers(router gin.IRouter, si ServerInterface) { - RegisterHandlersWithOptions(router, si, GinServerOptions{}) -} - -// RegisterHandlersWithOptions creates http.Handler with additional options -func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { - errorHandler := options.ErrorHandler - if errorHandler == nil { - errorHandler = func(c *gin.Context, err error, statusCode int) { - c.JSON(statusCode, gin.H{"msg": err.Error()}) - } - } - - wrapper := ServerInterfaceWrapper{ - Handler: si, - HandlerMiddlewares: options.Middlewares, - ErrorHandler: errorHandler, - } - - router.GET(options.BaseURL+"/kad", wrapper.ListKadInstances) - router.GET(options.BaseURL+"/kad/:kadInstanceId", wrapper.GetKadInstance) -} diff --git a/api/openapi/v3/_api/services/services-server.go b/api/openapi/v3/_api/services/services-server.go deleted file mode 100644 index fc99f50..0000000 --- a/api/openapi/v3/_api/services/services-server.go +++ /dev/null @@ -1,99 +0,0 @@ -// Package _services provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. -package _services - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/oapi-codegen/runtime" -) - -// ListServicesParams defines parameters for ListServices. -type ListServicesParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - // List all services - // (GET /kad/{kadInstanceId}/services) - ListServices(c *gin.Context, kadInstanceId string, params ListServicesParams) -} - -// ServerInterfaceWrapper converts contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface - HandlerMiddlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -type MiddlewareFunc func(c *gin.Context) - -// ListServices operation middleware -func (siw *ServerInterfaceWrapper) ListServices(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params ListServicesParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.ListServices(c, kadInstanceId, params) -} - -// GinServerOptions provides options for the Gin server. -type GinServerOptions struct { - BaseURL string - Middlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. -func RegisterHandlers(router gin.IRouter, si ServerInterface) { - RegisterHandlersWithOptions(router, si, GinServerOptions{}) -} - -// RegisterHandlersWithOptions creates http.Handler with additional options -func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { - errorHandler := options.ErrorHandler - if errorHandler == nil { - errorHandler = func(c *gin.Context, err error, statusCode int) { - c.JSON(statusCode, gin.H{"msg": err.Error()}) - } - } - - wrapper := ServerInterfaceWrapper{ - Handler: si, - HandlerMiddlewares: options.Middlewares, - ErrorHandler: errorHandler, - } - - router.GET(options.BaseURL+"/kad/:kadInstanceId/services", wrapper.ListServices) -} diff --git a/api/openapi/v3/_api/spec.go b/api/openapi/v3/_api/spec.go index 27ea258..55a2d35 100644 --- a/api/openapi/v3/_api/spec.go +++ b/api/openapi/v3/_api/spec.go @@ -18,57 +18,27 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "KIs3V5v/BQAA//9CJ63ODGQAAA==", + "H4sIAAAAAAAC/+xYXU8jNxf+K5bf96KVhpksvctVKaBVVJZGC/RmiyrHczLxMmNPbQ+QRvnvlT32fE9C", + "CtoC2hsU7OPz9Tzn2HM2mIosFxy4Vni6wYquICP2ZwxLxplmgv95SjRJRWJWcylykJqBlaESYuCakVT1", + "N6VYCH1CqSi4viQZmDW9zgFPsdKS8QRvg5bQtbgDPiC1DfyKWHwFqs25GBSVLDfuDeplcX85wI9HiTji", + "1hc8OzNyfMyxnNA7kpSRMA3ZQIAjZ01U8FfBJMR4+qWUuh0IwS0QKcnapgJycSNTo3EpZEY0nuJCMhzs", + "DMOe+nzRM8ti7KJrJ6u204ix516AH7O0jhFTx4CtTX1FjHmpYDw1LZjw9QqQ2UFiifQKkLPfi3Ab4HuQ", + "igmu+kpOUMqUNiq8DFoK2dFXIdZT3M76EFYN43vz4i128nIF8h7kuZRC9nOTgVIuaT3vlCa6aDrOuIYE", + "ZO35Prp57ZUud3BvKKrhcyecGwVyLsWSpQNQQ0ZYOhhMIkWRtwtoDxwBTkXChiuaj7eQFA60oorFvvag", + "Cleonfyao97NqsDKHFQRe5/25rxoJHa7NabgUYPkJD0TdID7v/16NkexoEUGXBNXz4XpGXilda6mUSTu", + "4jxkIrJNkC+FbdOCa0J1Ay3MYiZD9jfTouDA4ee7YiE0SUMmfFTOGhVZVnCm1zstdeucKcQUIujz+dU1", + "OpnPkIQlSOAUqmK12stCMQllFLiCRm5OckJXgI7DSc/yw8NDSOx2KGQSubMqupidnl9enR8dh5NwpbPU", + "Qs90WgVTmnNe5awudTzFH8JJODEnRA6c5AxP8U92yfRJvbJoRK4P2n8S0H2ELkxvImmKvOQfBiJTLxau", + "WexkTr0iwy6VC+O/0XY8mXjEgFv9JM9TRu3p6Ksqr7vymm5x/v8SlniK/xfVF3rkbvNo4Crvd8Ieiheu", + "zRqwqrjLxkCKVB/k5hO9u2r1oJ5HDj6oepQqsozI9VDeTd8jBqgvuFq6NWcqDKON+zWLt6N4fgSNiFeK", + "FmvE4gFEP4IH1LJFkgw0SGO8q8+JodmZuaW4vUL0qq65yiXcbDtaFhA00tm9Am6fyaJDydOHxsdlWo55", + "u5jV18qVAUwPY0vUfByOtwGx9C8SZax4g2MMmnulb5JChzYi/3R8QiPyiXlD5Ep34v8v2RZtDMK7e5WT", + "bdtDhMfVjtGxk4C/rC/LV81/wMJgM4w9cg+tAUNu59U1y4rg74DQT2PV82gdNT/5xptq66OPIJUDZUtG", + "vSM7mf27O/ud4d+I4RVar/vduIdTL8TraON+Pa2D1+Ht5PRZJfZ++Txqw3+9DZqpN79d5ZA4tliQdN4Y", + "kpRWOwPA8aKpkX8Tl0LcZODLFkpUh7S3XkpR9ENdAwGyCXvUAQJNf9xZRleloe8l9D5KyKl7C+Wzl7fj", + "VVUokCrK1nk9mx0tk2yNjDhyssPF8Gntp5HPBLE9IjaGD8jrTWsq2h6/WlW3T2DCp3a8r5oKHWwagFuE", + "DdrmjFVStqVyHhqRnEX3H7CpOXeiC/1NW293vNyeqyZMr4pFSEVmh7v2z1Fptp7AO5/6HaUx0nwJM/XI", + "8Xb7TwAAAP//8ILjn6ccAAA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/openapi/v3/_api/templatereleases/templatereleases-server.go b/api/openapi/v3/_api/templatereleases/templatereleases-server.go deleted file mode 100644 index 80593cf..0000000 --- a/api/openapi/v3/_api/templatereleases/templatereleases-server.go +++ /dev/null @@ -1,153 +0,0 @@ -// Package _templatereleases provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. -package _templatereleases - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/oapi-codegen/runtime" -) - -// ListTemplateReleasesParams defines parameters for ListTemplateReleases. -type ListTemplateReleasesParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// GetTemplateReleaseParams defines parameters for GetTemplateRelease. -type GetTemplateReleaseParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - // List all template releases - // (GET /kad/{kadInstanceId}/templatereleases) - ListTemplateReleases(c *gin.Context, kadInstanceId string, params ListTemplateReleasesParams) - // Get a template release by name - // (GET /kad/{kadInstanceId}/templatereleases/{name}) - GetTemplateRelease(c *gin.Context, kadInstanceId string, name string, params GetTemplateReleaseParams) -} - -// ServerInterfaceWrapper converts contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface - HandlerMiddlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -type MiddlewareFunc func(c *gin.Context) - -// ListTemplateReleases operation middleware -func (siw *ServerInterfaceWrapper) ListTemplateReleases(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params ListTemplateReleasesParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.ListTemplateReleases(c, kadInstanceId, params) -} - -// GetTemplateRelease operation middleware -func (siw *ServerInterfaceWrapper) GetTemplateRelease(c *gin.Context) { - - var err error - - // ------------- Path parameter "kadInstanceId" ------------- - var kadInstanceId string - - err = runtime.BindStyledParameterWithOptions("simple", "kadInstanceId", c.Param("kadInstanceId"), &kadInstanceId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kadInstanceId: %w", err), http.StatusBadRequest) - return - } - - // ------------- Path parameter "name" ------------- - var name string - - err = runtime.BindStyledParameterWithOptions("simple", "name", c.Param("name"), &name, runtime.BindStyledParameterOptions{Explode: false, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter name: %w", err), http.StatusBadRequest) - return - } - - // Parameter object where we will unmarshal all parameters from the context - var params GetTemplateReleaseParams - - // ------------- Optional query parameter "catalog" ------------- - - err = runtime.BindQueryParameter("form", true, false, "catalog", c.Request.URL.Query(), ¶ms.Catalog) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter catalog: %w", err), http.StatusBadRequest) - return - } - - for _, middleware := range siw.HandlerMiddlewares { - middleware(c) - if c.IsAborted() { - return - } - } - - siw.Handler.GetTemplateRelease(c, kadInstanceId, name, params) -} - -// GinServerOptions provides options for the Gin server. -type GinServerOptions struct { - BaseURL string - Middlewares []MiddlewareFunc - ErrorHandler func(*gin.Context, error, int) -} - -// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. -func RegisterHandlers(router gin.IRouter, si ServerInterface) { - RegisterHandlersWithOptions(router, si, GinServerOptions{}) -} - -// RegisterHandlersWithOptions creates http.Handler with additional options -func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { - errorHandler := options.ErrorHandler - if errorHandler == nil { - errorHandler = func(c *gin.Context, err error, statusCode int) { - c.JSON(statusCode, gin.H{"msg": err.Error()}) - } - } - - wrapper := ServerInterfaceWrapper{ - Handler: si, - HandlerMiddlewares: options.Middlewares, - ErrorHandler: errorHandler, - } - - router.GET(options.BaseURL+"/kad/:kadInstanceId/templatereleases", wrapper.ListTemplateReleases) - router.GET(options.BaseURL+"/kad/:kadInstanceId/templatereleases/:name", wrapper.GetTemplateRelease) -} diff --git a/api/openapi/v3/_api/types.go b/api/openapi/v3/_api/types.go index d67b7ae..82e4d43 100644 --- a/api/openapi/v3/_api/types.go +++ b/api/openapi/v3/_api/types.go @@ -3,12 +3,6 @@ // Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. package _api -import ( - "encoding/json" - - "github.com/oapi-codegen/runtime" -) - // Catalog defines model for Catalog. type Catalog struct { Credentials *struct { @@ -24,240 +18,6 @@ type Catalog struct { RepoURL string `json:"repoUrl"` } -// Component defines model for Component. -type Component struct { - Kind string `json:"kind"` - Spec struct { - AllowCreateNamespace bool `json:"allowCreateNamespace"` - AllowValues bool `json:"allowValues"` - Catalogs []string `json:"catalogs"` - Config struct { - Install struct { - CreateNamespace bool `json:"createNamespace"` - Remediation struct { - RemediateLastFailure bool `json:"remediateLastFailure"` - Retries float32 `json:"retries"` - } `json:"remediation"` - } `json:"install"` - Timeout string `json:"timeout"` - Upgrade struct { - Remediation struct { - RemediateLastFailure bool `json:"remediateLastFailure"` - Retries float32 `json:"retries"` - } `json:"remediation"` - } `json:"upgrade"` - } `json:"config"` - ContextSchema struct { - File string `json:"File"` - Json string `json:"Json"` - } `json:"contextSchema"` - DependsOn []string `json:"dependsOn"` - Name string `json:"name"` - - // Parameters List of paramters as key/value pairs - Parameters map[string]interface{} `json:"parameters"` - ParametersSchema struct { - File string `json:"File"` - Json string `json:"Json"` - } `json:"parametersSchema"` - Protected bool `json:"protected"` - Roles []string `json:"roles"` - Source struct { - AllowedVersions []string `json:"allowedVersions"` - DefaultVersion string `json:"defaultVersion"` - GitRepository struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Path string `json:"path"` - Unmanaged bool `json:"unmanaged"` - } `json:"gitRepository"` - HelmRepository struct { - CertSecretRef string `json:"certSecretRef"` - Chart string `json:"chart"` - Interval string `json:"interval"` - SecretRef string `json:"secretRef"` - Url string `json:"url"` - } `json:"helmRepository"` - OciRepository struct { - CertSecretRef string `json:"certSecretRef"` - Insecure bool `json:"insecure"` - Interval string `json:"interval"` - SecretRef string `json:"secretRef"` - Url string `json:"url"` - } `json:"ociRepository"` - } `json:"source"` - Suspended bool `json:"suspended"` - Usage Component_Spec_Usage `json:"usage"` - Values Component_Spec_Values `json:"values"` - Version string `json:"version"` - } `json:"spec"` - Status struct { - Error string `json:"error"` - File string `json:"file"` - ParametersSchema map[string]interface{} `json:"parametersSchema"` - Path string `json:"path"` - Releases []string `json:"releases"` - Title string `json:"title"` - } `json:"status"` -} - -// ComponentSpecUsage0 defines model for . -type ComponentSpecUsage0 = string - -// ComponentSpecUsage1 defines model for . -type ComponentSpecUsage1 map[string]interface{} - -// Component_Spec_Usage defines model for Component.Spec.Usage. -type Component_Spec_Usage struct { - union json.RawMessage -} - -// ComponentSpecValues0 defines model for . -type ComponentSpecValues0 = string - -// ComponentSpecValues1 defines model for . -type ComponentSpecValues1 map[string]interface{} - -// Component_Spec_Values defines model for Component.Spec.Values. -type Component_Spec_Values struct { - union json.RawMessage -} - -// ComponentReleasePayload defines model for ComponentReleasePayload. -type ComponentReleasePayload struct { - Component struct { - // Config Additional configuration - Config *map[string]interface{} `json:"config,omitempty"` - Name string `json:"name"` - ParameterFiles *[]struct { - Document *string `json:"document,omitempty"` - File *string `json:"file,omitempty"` - Unwrap *string `json:"unwrap,omitempty"` - Wrap *string `json:"wrap,omitempty"` - } `json:"parameterFiles,omitempty"` - - // Parameters List of paramters as key/value pairs - Parameters *map[string]interface{} `json:"parameters,omitempty"` - Protected *bool `json:"protected,omitempty"` - Source *struct { - Version string `json:"version"` - } `json:"source,omitempty"` - Suspended *bool `json:"suspended,omitempty"` - - // Values List of values as key/value pairs - Values *map[string]interface{} `json:"values,omitempty"` - Version string `json:"version"` - } `json:"component"` - DependsOn *[]string `json:"dependsOn,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Name string `json:"name"` - Namespace *string `json:"namespace,omitempty"` - Roles *[]string `json:"roles,omitempty"` -} - -// ComponentReleaseRequest defines model for ComponentReleaseRequest. -type ComponentReleaseRequest struct { - Comment string `json:"comment"` - ComponentReleases []struct { - Component struct { - // Config Additional configuration - Config *map[string]interface{} `json:"config,omitempty"` - Name string `json:"name"` - ParameterFiles *[]struct { - Document *string `json:"document,omitempty"` - File *string `json:"file,omitempty"` - Unwrap *string `json:"unwrap,omitempty"` - Wrap *string `json:"wrap,omitempty"` - } `json:"parameterFiles,omitempty"` - - // Parameters List of paramters as key/value pairs - Parameters *map[string]interface{} `json:"parameters,omitempty"` - Protected *bool `json:"protected,omitempty"` - Source *struct { - Version string `json:"version"` - } `json:"source,omitempty"` - Suspended *bool `json:"suspended,omitempty"` - - // Values List of values as key/value pairs - Values *map[string]interface{} `json:"values,omitempty"` - Version string `json:"version"` - } `json:"component"` - DependsOn *[]string `json:"dependsOn,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Name string `json:"name"` - Namespace *string `json:"namespace,omitempty"` - Roles *[]string `json:"roles,omitempty"` - } `json:"componentReleases"` - GitRepoFolder string `json:"gitRepoFolder"` -} - -// ComponentReleaseResponse defines model for ComponentReleaseResponse. -type ComponentReleaseResponse struct { - Kind string `json:"kind"` - Spec struct { - Component struct { - Ref struct { - Name string `json:"Name"` - Version string `json:"Version"` - } `json:"Ref"` - Source struct { - Version string `json:"version"` - } `json:"Source"` - - // Config Additional configuration - Config map[string]interface{} `json:"config"` - ParameterFiles []struct { - Document *string `json:"Document,omitempty"` - File *string `json:"File,omitempty"` - Unwrap *string `json:"Unwrap,omitempty"` - Wrap *string `json:"Wrap,omitempty"` - } `json:"parameterFiles"` - - // Parameters List of paramters as key/value pairs - Parameters map[string]interface{} `json:"parameters"` - Protected bool `json:"protected"` - Suspended bool `json:"suspended"` - - // Values List of values as key/value pairs - Values map[string]interface{} `json:"values"` - } `json:"component"` - DependsOn []string `json:"dependsOn"` - Enabled bool `json:"enabled"` - HelmReleaseName string `json:"helmReleaseName__"` - Name string `json:"name"` - Namespace string `json:"namespace"` - Roles []string `json:"roles"` - } `json:"spec"` - Status struct { - Catalogs []string `json:"catalogs"` - Dependencies []string `json:"dependencies"` - Error string `json:"error"` - File string `json:"file"` - - // Parameters List of values as key/value pairs - Parameters map[string]interface{} `json:"parameters"` - Path string `json:"path"` - Usage string `json:"usage"` - } `json:"status"` -} - -// FlatComponent defines model for FlatComponent. -type FlatComponent struct { - Catalogs []string `json:"catalogs"` - ComponentName string `json:"componentName"` - ComponentReleaseName string `json:"componentReleaseName"` - ComponentVersion string `json:"componentVersion"` - Enabled bool `json:"enabled"` - PackageName string `json:"packageName"` - PackageVersion string `json:"packageVersion"` - Protected bool `json:"protected"` - Suspended bool `json:"suspended"` - TemplateName string `json:"templateName"` - TemplateReleaseName string `json:"templateReleaseName"` - TemplateVersion string `json:"templateVersion"` - Usage string `json:"usage"` -} - // GitCommit defines model for GitCommit. type GitCommit struct { // Commit The hash of the commit @@ -279,15 +39,6 @@ type GitCommit struct { TargetPath *string `json:"targetPath,omitempty"` } -// KadInstance defines model for KadInstance. -type KadInstance struct { - APIURL string `json:"apiUrl"` - AuthBearer string `json:"authBearer"` - ID string `json:"id"` - InsecureSkipVerify bool `json:"insecureSkipVerify"` - Name string `json:"name"` -} - // Package defines model for Package. type Package struct { // Name The name of the package @@ -304,56 +55,6 @@ type ServerError struct { Type string `json:"type"` } -// Service defines model for Service. -type Service struct { - Name string `json:"name"` - IsComposition bool `json:"isComposition"` - FlatComponents []struct { - Catalogs []string `json:"catalogs"` - ComponentName string `json:"componentName"` - ComponentReleaseName string `json:"componentReleaseName"` - ComponentVersion string `json:"componentVersion"` - Enabled bool `json:"enabled"` - PackageName string `json:"packageName"` - PackageVersion string `json:"packageVersion"` - Protected bool `json:"protected"` - Suspended bool `json:"suspended"` - TemplateName string `json:"templateName"` - TemplateReleaseName string `json:"templateReleaseName"` - TemplateVersion string `json:"templateVersion"` - Usage string `json:"usage"` - } `json:"flatComponents"` -} - -// TemplateRelease defines model for TemplateRelease. -type TemplateRelease struct { - Kind string `json:"kind"` - Spec struct { - Enabled bool `json:"enabled"` - Name string `json:"name"` - Template struct { - Ref struct { - Name string `json:"Name"` - Version string `json:"Version"` - } `json:"Ref"` - - // Parameters List of paramters as key/value pairs - Parameters map[string]interface{} `json:"parameters"` - } `json:"template"` - } `json:"spec"` - Status struct { - Catalogs []string `json:"catalogs"` - Children []string `json:"children"` - Error string `json:"error"` - File string `json:"file"` - - // Parameters List of paramters as key/value pairs - Parameters map[string]interface{} `json:"parameters"` - Path string `json:"path"` - Usage string `json:"usage"` - } `json:"status"` -} - // UserProfile defines model for UserProfile. type UserProfile struct { Email string `json:"email"` @@ -363,208 +64,3 @@ type UserProfile struct { Roles []string `json:"roles"` Subject string `json:"sub"` } - -// ListComponentReleasesParams defines parameters for ListComponentReleases. -type ListComponentReleasesParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// GetComponentReleaseParams defines parameters for GetComponentRelease. -type GetComponentReleaseParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// CreateOrUpdateComponentReleaseJSONBody defines parameters for CreateOrUpdateComponentRelease. -type CreateOrUpdateComponentReleaseJSONBody struct { - Comment string `json:"comment"` - ComponentReleases []struct { - Component struct { - // Config Additional configuration - Config *map[string]interface{} `json:"config,omitempty"` - Name string `json:"name"` - ParameterFiles *[]struct { - Document *string `json:"document,omitempty"` - File *string `json:"file,omitempty"` - Unwrap *string `json:"unwrap,omitempty"` - Wrap *string `json:"wrap,omitempty"` - } `json:"parameterFiles,omitempty"` - - // Parameters List of paramters as key/value pairs - Parameters *map[string]interface{} `json:"parameters,omitempty"` - Protected *bool `json:"protected,omitempty"` - Source *struct { - Version string `json:"version"` - } `json:"source,omitempty"` - Suspended *bool `json:"suspended,omitempty"` - - // Values List of values as key/value pairs - Values *map[string]interface{} `json:"values,omitempty"` - Version string `json:"version"` - } `json:"component"` - DependsOn *[]string `json:"dependsOn,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Name string `json:"name"` - Namespace *string `json:"namespace,omitempty"` - Roles *[]string `json:"roles,omitempty"` - } `json:"componentReleases"` - GitRepoFolder string `json:"gitRepoFolder"` -} - -// ListComponentsParams defines parameters for ListComponents. -type ListComponentsParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// GetComponentsByNameParams defines parameters for GetComponentsByName. -type GetComponentsByNameParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// ListServicesParams defines parameters for ListServices. -type ListServicesParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// ListTemplateReleasesParams defines parameters for ListTemplateReleases. -type ListTemplateReleasesParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// GetTemplateReleaseParams defines parameters for GetTemplateRelease. -type GetTemplateReleaseParams struct { - // Catalog Filter by catalogs (comma separated) - Catalog *string `form:"catalog,omitempty" json:"catalog,omitempty"` -} - -// CreateOrUpdateComponentReleaseJSONRequestBody defines body for CreateOrUpdateComponentRelease for application/json ContentType. -type CreateOrUpdateComponentReleaseJSONRequestBody CreateOrUpdateComponentReleaseJSONBody - -// AsComponentSpecUsage0 returns the union data inside the Component_Spec_Usage as a ComponentSpecUsage0 -func (t Component_Spec_Usage) AsComponentSpecUsage0() (ComponentSpecUsage0, error) { - var body ComponentSpecUsage0 - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromComponentSpecUsage0 overwrites any union data inside the Component_Spec_Usage as the provided ComponentSpecUsage0 -func (t *Component_Spec_Usage) FromComponentSpecUsage0(v ComponentSpecUsage0) error { - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeComponentSpecUsage0 performs a merge with any union data inside the Component_Spec_Usage, using the provided ComponentSpecUsage0 -func (t *Component_Spec_Usage) MergeComponentSpecUsage0(v ComponentSpecUsage0) error { - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsComponentSpecUsage1 returns the union data inside the Component_Spec_Usage as a ComponentSpecUsage1 -func (t Component_Spec_Usage) AsComponentSpecUsage1() (ComponentSpecUsage1, error) { - var body ComponentSpecUsage1 - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromComponentSpecUsage1 overwrites any union data inside the Component_Spec_Usage as the provided ComponentSpecUsage1 -func (t *Component_Spec_Usage) FromComponentSpecUsage1(v ComponentSpecUsage1) error { - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeComponentSpecUsage1 performs a merge with any union data inside the Component_Spec_Usage, using the provided ComponentSpecUsage1 -func (t *Component_Spec_Usage) MergeComponentSpecUsage1(v ComponentSpecUsage1) error { - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t Component_Spec_Usage) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *Component_Spec_Usage) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// AsComponentSpecValues0 returns the union data inside the Component_Spec_Values as a ComponentSpecValues0 -func (t Component_Spec_Values) AsComponentSpecValues0() (ComponentSpecValues0, error) { - var body ComponentSpecValues0 - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromComponentSpecValues0 overwrites any union data inside the Component_Spec_Values as the provided ComponentSpecValues0 -func (t *Component_Spec_Values) FromComponentSpecValues0(v ComponentSpecValues0) error { - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeComponentSpecValues0 performs a merge with any union data inside the Component_Spec_Values, using the provided ComponentSpecValues0 -func (t *Component_Spec_Values) MergeComponentSpecValues0(v ComponentSpecValues0) error { - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsComponentSpecValues1 returns the union data inside the Component_Spec_Values as a ComponentSpecValues1 -func (t Component_Spec_Values) AsComponentSpecValues1() (ComponentSpecValues1, error) { - var body ComponentSpecValues1 - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromComponentSpecValues1 overwrites any union data inside the Component_Spec_Values as the provided ComponentSpecValues1 -func (t *Component_Spec_Values) FromComponentSpecValues1(v ComponentSpecValues1) error { - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeComponentSpecValues1 performs a merge with any union data inside the Component_Spec_Values, using the provided ComponentSpecValues1 -func (t *Component_Spec_Values) MergeComponentSpecValues1(v ComponentSpecValues1) error { - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t Component_Spec_Values) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *Component_Spec_Values) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} diff --git a/api/openapi/v3/api.yaml b/api/openapi/v3/api.yaml index 08c07d3..6e73e83 100644 --- a/api/openapi/v3/api.yaml +++ b/api/openapi/v3/api.yaml @@ -26,28 +26,6 @@ tags: description: Catalogs externalDocs: url: https://github.com/okdp/okdp-server - - - - name: kad - description: Kad instances configuration - externalDocs: - url: https://github.com/okdp/okdp-server - - name: services - description: Services - externalDocs: - url: https://github.com/okdp/okdp-server - - name: templatereleases - description: Template releases - externalDocs: - url: https://github.com/okdp/okdp-server - - name: componentreleases - description: Component releases - externalDocs: - url: https://github.com/okdp/okdp-server - - name: components - description: Components - externalDocs: - url: https://github.com/okdp/okdp-server paths: ### Users @@ -69,31 +47,6 @@ paths: /catalogs/{catalogId}/packages/{name}/versions/{version}/schema: $ref: ./paths/catalogs/package-schema.yaml - ###### Remove all this - ### KAD instances - /kad: - $ref: ./paths/kad/kad-instance.yaml - /kad/{kadInstanceId}: - $ref: ./paths/kad/kad-instance-by-name.yaml - ### Services API - /kad/{kadInstanceId}/services: - $ref: ./paths/services/service.yaml - ### KAD Component Releases API - /kad/{kadInstanceId}/componentreleases: - $ref: ./paths/componentreleases/component-releases.yaml - /kad/{kadInstanceId}/componentreleases/{name}: - $ref: ./paths/componentreleases/component-releases-by-name.yaml - ### KAD Template Releases API - /kad/{kadInstanceId}/templatereleases: - $ref: ./paths/templatereleases/template-releases.yaml - /kad/{kadInstanceId}/templatereleases/{name}: - $ref: ./paths/templatereleases/template-releases-by-name.yaml - ### KAD Components API - /kad/{kadInstanceId}/components: - $ref: ./paths/components/component.yaml - /kad/{kadInstanceId}/components/{name}: - $ref: ./paths/components/component-by-name.yaml - components: schemas: UserProfile: @@ -102,28 +55,7 @@ components: $ref: './definition/Catalog.yaml' Package: $ref: './definition/Package.yaml' - - - - - TemplateRelease: - $ref: './definition/TemplateRelease.yaml' - ComponentReleasePayload: - $ref: './definition/ComponentReleasePayload.yaml' - ComponentReleaseRequest: - $ref: './definition/ComponentReleaseRequest.yaml' - ComponentReleaseResponse: - $ref: './definition/ComponentReleaseResponse.yaml' - Component: - $ref: './definition/Component.yaml' - Service: - $ref: './definition/Service.yaml' - FlatComponent: - $ref: './definition/FlatComponent.yaml' - KadInstance: - $ref: './definition/KadInstance.yaml' GitCommit: $ref: './definition/GitCommit.yaml' ServerError: - $ref: './definition/ServerError.yaml' - + $ref: './definition/ServerError.yaml' \ No newline at end of file diff --git a/api/openapi/v3/definition/Component.yaml b/api/openapi/v3/definition/Component.yaml deleted file mode 100644 index 3e859c0..0000000 --- a/api/openapi/v3/definition/Component.yaml +++ /dev/null @@ -1,226 +0,0 @@ -# https://swagger-toolbox.firebaseapp.com/ -type: object -xml: - name: component -required: -- "kind" -- "spec" -- "status" -properties: - kind: - type: "string" - spec: - required: - - "name" - - "version" - - "catalogs" - - "usage" - - "config" - - "suspended" - - "protected" - - "source" - - "parameters" - - "parametersSchema" - - "contextSchema" - - "values" - - "allowValues" - - "allowCreateNamespace" - - "roles" - - "dependsOn" - properties: - name: - type: "string" - version: - type: "string" - catalogs: - type: "array" - items: - type: "string" - usage: - oneOf: - - type: string - - type: object - additionalProperties: true - config: - required: - - "install" - - "timeout" - - "upgrade" - properties: - install: - required: - - "createNamespace" - - "remediation" - properties: - createNamespace: - type: "boolean" - remediation: - required: - - "remediateLastFailure" - - "retries" - properties: - remediateLastFailure: - type: "boolean" - retries: - type: "number" - type: "object" - type: "object" - timeout: - type: "string" - upgrade: - required: - - "remediation" - properties: - remediation: - required: - - "remediateLastFailure" - - "retries" - properties: - remediateLastFailure: - type: "boolean" - retries: - type: "number" - type: "object" - type: "object" - type: "object" - suspended: - type: "boolean" - protected: - type: "boolean" - source: - required: - - "allowedVersions" - - "defaultVersion" - - "gitRepository" - - "ociRepository" - - "helmRepository" - properties: - allowedVersions: - type: "array" - items: - type: "string" - defaultVersion: - type: "string" - gitRepository: - required: - - "name" - - "path" - - "unmanaged" - - "namespace" - properties: - name: - type: "string" - path: - type: "string" - unmanaged: - type: "boolean" - namespace: - type: "string" - type: "object" - ociRepository: - required: - - "url" - - "insecure" - - "interval" - - "secretRef" - - "certSecretRef" - properties: - url: - type: "string" - insecure: - type: "boolean" - interval: - type: "string" - secretRef: - type: "string" - certSecretRef: - type: "string" - type: "object" - helmRepository: - required: - - "url" - - "chart" - - "interval" - - "secretRef" - - "certSecretRef" - properties: - url: - type: "string" - chart: - type: "string" - interval: - type: "string" - secretRef: - type: "string" - certSecretRef: - type: "string" - type: "object" - type: "object" - parameters: - description: List of paramters as key/value pairs - additionalProperties: true - type: "object" - parametersSchema: - required: - - "File" - - "Json" - - "Yaml" - properties: - File: - type: "string" - Json: - type: "string" - type: "object" - contextSchema: - required: - - "File" - - "Json" - - "Yaml" - properties: - File: - type: "string" - Json: - type: "string" - type: "object" - values: - oneOf: - - type: string - - type: object - additionalProperties: true - allowValues: - type: "boolean" - allowCreateNamespace: - type: "boolean" - roles: - type: "array" - items: - type: "string" - dependsOn: - type: "array" - items: - type: "string" - type: "object" - status: - required: - - "file" - - "path" - - "error" - - "parametersSchema" - - "releases" - - "title" - properties: - file: - type: "string" - path: - type: "string" - error: - type: "string" - parametersSchema: - type: "object" - releases: - type: "array" - items: - type: "string" - title: - type: "string" - type: "object" diff --git a/api/openapi/v3/definition/ComponentReleasePayload.yaml b/api/openapi/v3/definition/ComponentReleasePayload.yaml deleted file mode 100644 index fc80da7..0000000 --- a/api/openapi/v3/definition/ComponentReleasePayload.yaml +++ /dev/null @@ -1,67 +0,0 @@ -type: object -required: - - "name" - - "component" -properties: - name: - type: "string" - enabled: - type: "boolean" - namespace: - type: "string" - roles: - type: array - items: - type: string - dependsOn: - type: array - items: - type: string - component: - required: - - "name" - - "version" - properties: - name: - type: "string" - version: - type: "string" - suspended: - type: "boolean" - protected: - type: "boolean" - source: - required: - - "version" - properties: - version: - type: "string" - type: "object" - parameters: - description: List of paramters as key/value pairs - additionalProperties: true - type: "object" - parameterFiles: - type: "array" - items: - type: "object" - properties: - document: - type: "string" - file: - type: "string" - unwrap: - type: "string" - wrap: - type: "string" - values: - description: List of values as key/value pairs - additionalProperties: true - type: "object" - config: - description: Additional configuration - additionalProperties: true - type: "object" - - - diff --git a/api/openapi/v3/definition/ComponentReleaseRequest.yaml b/api/openapi/v3/definition/ComponentReleaseRequest.yaml deleted file mode 100644 index 7f94626..0000000 --- a/api/openapi/v3/definition/ComponentReleaseRequest.yaml +++ /dev/null @@ -1,17 +0,0 @@ -type: object -required: - - "gitRepoFolder" - - "comment" - - "componentReleases" -properties: - gitRepoFolder: - type: "string" - comment: - type: "string" - componentReleases: - type: "array" - items: - $ref: './ComponentReleasePayload.yaml' - - - diff --git a/api/openapi/v3/definition/ComponentReleaseResponse.yaml b/api/openapi/v3/definition/ComponentReleaseResponse.yaml deleted file mode 100644 index 3561c31..0000000 --- a/api/openapi/v3/definition/ComponentReleaseResponse.yaml +++ /dev/null @@ -1,125 +0,0 @@ -type: object -required: - - "kind" - - "spec" - - "status" -properties: - kind: - type: "string" - spec: - required: - - "name" - - "enabled" - - "component" - - "namespace" - - "helmReleaseName__" - - "roles" - - "dependsOn" - properties: - name: - type: "string" - enabled: - type: "boolean" - component: - required: - - "Ref" - - "suspended" - - "protected" - - "Source" - - "parameters" - - "parameterFiles" - - "config" - - "values" - properties: - Ref: - required: - - "Name" - - "Version" - properties: - Name: - type: "string" - Version: - type: "string" - type: "object" - suspended: - type: "boolean" - protected: - type: "boolean" - Source: - required: - - "version" - properties: - version: - type: "string" - type: "object" - parameters: - description: List of paramters as key/value pairs - additionalProperties: true - type: "object" - parameterFiles: - type: "array" - items: - type: "object" - properties: - Document: - type: "string" - File: - type: "string" - Unwrap: - type: "string" - Wrap: - type: "string" - values: - description: List of values as key/value pairs - additionalProperties: true - type: "object" - config: - description: Additional configuration - additionalProperties: true - type: "object" - type: "object" - namespace: - type: "string" - helmReleaseName__: - type: "string" - roles: - type: "array" - items: - type: "string" - dependsOn: - type: "array" - items: - type: "string" - type: "object" - status: - required: - - "file" - - "path" - - "error" - - "parameters" - - "dependencies" - - "usage" - - "catalogs" - properties: - file: - type: "string" - path: - type: "string" - error: - type: "string" - parameters: - description: List of values as key/value pairs - additionalProperties: true - type: "object" - dependencies: - type: "array" - items: - type: "string" - usage: - type: "string" - catalogs: - type: "array" - items: - type: "string" - type: "object" - diff --git a/api/openapi/v3/definition/FlatComponent.yaml b/api/openapi/v3/definition/FlatComponent.yaml deleted file mode 100644 index 592e6d0..0000000 --- a/api/openapi/v3/definition/FlatComponent.yaml +++ /dev/null @@ -1,47 +0,0 @@ -type: "object" -xml: - name: flatComponent -required: -- "packageName" -- "packageVersion" -- "componentName" -- "componentVersion" -- "templateName" -- "templateVersion" -- "componentReleaseName" -- "templateReleaseName" -- "enabled" -- "suspended" -- "protected" -- "catalogs" -- "usage" -properties: - packageName: - type: string - packageVersion: - type: string - componentName: - type: string - componentVersion: - type: string - templateName: - type: string - templateVersion: - type: string - componentReleaseName: - type: string - templateReleaseName: - type: string - enabled: - type: boolean - suspended: - type: boolean - protected: - type: boolean - catalogs: - type: array - items: - type: string - usage: - type: string - default: "" diff --git a/api/openapi/v3/definition/KadInstance.yaml b/api/openapi/v3/definition/KadInstance.yaml deleted file mode 100644 index fc13f9f..0000000 --- a/api/openapi/v3/definition/KadInstance.yaml +++ /dev/null @@ -1,23 +0,0 @@ -type: object -xml: - name: kadInstance -required: -- id -- name -- apiUrl -- authBearer -- insecureSkipVerify -properties: - id: - type: string - x-go-name: ID - name: - type: string - apiUrl: - type: string - x-go-name: APIURL - authBearer: - type: string - insecureSkipVerify: - type: boolean - default: true diff --git a/api/openapi/v3/definition/Service.yaml b/api/openapi/v3/definition/Service.yaml deleted file mode 100644 index 47eb441..0000000 --- a/api/openapi/v3/definition/Service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -type: object -xml: - name: service -required: -- "name" -- "isComposition" -- "flatComponents" -properties: - name: - type: string - x-order: 1 - isComposition: - type: "boolean" - default: false - x-order: 3 - flatComponents: - type: "array" - x-order: 4 - items: - $ref: './FlatComponent.yaml' - - - diff --git a/api/openapi/v3/definition/TemplateRelease.yaml b/api/openapi/v3/definition/TemplateRelease.yaml deleted file mode 100644 index 4b275fe..0000000 --- a/api/openapi/v3/definition/TemplateRelease.yaml +++ /dev/null @@ -1,73 +0,0 @@ -type: object -xml: - name: templateRelease -required: - - "kind" - - "spec" - - "status" -properties: - kind: - type: "string" - spec: - required: - - "name" - - "template" - - "enabled" - properties: - name: - type: "string" - template: - required: - - "Ref" - - "parameters" - - "parameterFiles" - properties: - Ref: - required: - - "Name" - - "Version" - properties: - Name: - type: "string" - Version: - type: "string" - type: "object" - parameters: - description: List of paramters as key/value pairs - additionalProperties: true - type: "object" - type: "object" - enabled: - type: "boolean" - type: "object" - status: - required: - - "file" - - "path" - - "error" - - "parameters" - - "children" - - "usage" - - "catalogs" - properties: - file: - type: "string" - path: - type: "string" - error: - type: "string" - parameters: - description: List of paramters as key/value pairs - additionalProperties: true - type: "object" - children: - type: "array" - items: - type: "string" - usage: - type: "string" - catalogs: - type: "array" - items: - type: "string" - type: "object" diff --git a/api/openapi/v3/paths/componentreleases/component-releases-by-name.yaml b/api/openapi/v3/paths/componentreleases/component-releases-by-name.yaml deleted file mode 100644 index 9e5ef56..0000000 --- a/api/openapi/v3/paths/componentreleases/component-releases-by-name.yaml +++ /dev/null @@ -1,88 +0,0 @@ -get: - summary: Get a component release by name - description: | - Get a component release by name - tags: - - componentreleases - operationId: getComponentRelease - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: path - name: name - schema: - type: string - required: true - description: Component release name - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: Component release information - content: - application/json: - schema: - $ref: '../../definition/ComponentReleaseResponse.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - - -put: - summary: Create or update a component release - description: | - Create or update a component release - tags: - - componentreleases - operationId: createOrUpdateComponentRelease - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: path - name: name - schema: - type: string - required: true - description: Component release name - requestBody: - description: Component release payload - required: true - content: - application/json: - schema: - $ref: '../../definition/ComponentReleaseRequest.yaml' - responses: - '200': - description: Commit updated successfully - content: - application/json: - schema: - $ref: '../../definition/GitCommit.yaml' - '201': - description: Commit created successfully - content: - application/json: - schema: - $ref: '../../definition/GitCommit.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/componentreleases/component-releases.yaml b/api/openapi/v3/paths/componentreleases/component-releases.yaml deleted file mode 100644 index 08faf76..0000000 --- a/api/openapi/v3/paths/componentreleases/component-releases.yaml +++ /dev/null @@ -1,41 +0,0 @@ -get: - summary: List all component releases - description: | - todo - tags: - - componentreleases - operationId: listComponentReleases - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: List of the component releases - content: - application/json: - schema: - type: object - required: [componentreleases] - properties: - componentreleases: - type: array - items: - $ref: '../../definition/ComponentReleaseResponse.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - - diff --git a/api/openapi/v3/paths/components/component-by-name.yaml b/api/openapi/v3/paths/components/component-by-name.yaml deleted file mode 100644 index 5913e5f..0000000 --- a/api/openapi/v3/paths/components/component-by-name.yaml +++ /dev/null @@ -1,46 +0,0 @@ -get: - summary: Get a components by name - description: | - Get a components by name - tags: - - components - operationId: getComponentsByName - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: path - name: name - schema: - type: string - required: true - description: Component name - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: List of components by name - content: - application/json: - schema: - type: object - required: [components] - properties: - components: - type: array - items: - $ref: '../../definition/Component.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/components/component.yaml b/api/openapi/v3/paths/components/component.yaml deleted file mode 100644 index a26a802..0000000 --- a/api/openapi/v3/paths/components/component.yaml +++ /dev/null @@ -1,40 +0,0 @@ -get: - summary: List all components - description: | - List all components - tags: - - components - operationId: listComponents - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: List of the components - content: - application/json: - schema: - type: object - required: [components] - properties: - components: - type: array - items: - $ref: '../../definition/Component.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/kad/kad-instance-by-name.yaml b/api/openapi/v3/paths/kad/kad-instance-by-name.yaml deleted file mode 100644 index ebc7a8b..0000000 --- a/api/openapi/v3/paths/kad/kad-instance-by-name.yaml +++ /dev/null @@ -1,33 +0,0 @@ -get: - summary: Get KAD instance by name - description: Get KAD instance by name - tags: - - kad - operationId: getKadInstance - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - responses: - '200': - description: KAD instance configuration - content: - application/json: - schema: - type: object - required: [instances] - properties: - instances: - type: array - items: - $ref: '../../definition/KadInstance.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/kad/kad-instance.yaml b/api/openapi/v3/paths/kad/kad-instance.yaml deleted file mode 100644 index a98c9b2..0000000 --- a/api/openapi/v3/paths/kad/kad-instance.yaml +++ /dev/null @@ -1,26 +0,0 @@ -get: - summary: List all KAD configured instances - description: List all KAD configured instances - tags: - - kad - operationId: listKadInstances - responses: - '200': - description: List of KAD instances - content: - application/json: - schema: - type: object - required: [instances] - properties: - instances: - type: array - items: - $ref: '../../definition/KadInstance.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/services/service.yaml b/api/openapi/v3/paths/services/service.yaml deleted file mode 100644 index acfd1f4..0000000 --- a/api/openapi/v3/paths/services/service.yaml +++ /dev/null @@ -1,40 +0,0 @@ -get: - summary: List all services - description: | - List all services - tags: - - services - operationId: listServices - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: List of the services - content: - application/json: - schema: - type: object - required: [services] - properties: - services: - type: array - items: - $ref: '../../definition/Service.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/templatereleases/template-releases-by-name.yaml b/api/openapi/v3/paths/templatereleases/template-releases-by-name.yaml deleted file mode 100644 index cd648ad..0000000 --- a/api/openapi/v3/paths/templatereleases/template-releases-by-name.yaml +++ /dev/null @@ -1,40 +0,0 @@ -get: - summary: Get a template release by name - description: | - Get a template release by name - tags: - - templatereleases - operationId: getTemplateRelease - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: path - name: name - schema: - type: string - required: true - description: Template release name - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: Template release information - content: - application/json: - schema: - $ref: '../../definition/TemplateRelease.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/api/openapi/v3/paths/templatereleases/template-releases.yaml b/api/openapi/v3/paths/templatereleases/template-releases.yaml deleted file mode 100644 index 94be0ab..0000000 --- a/api/openapi/v3/paths/templatereleases/template-releases.yaml +++ /dev/null @@ -1,40 +0,0 @@ -get: - summary: List all template releases - description: | - List all template releases - tags: - - templatereleases - operationId: listTemplateReleases - parameters: - - in: path - name: kadInstanceId - schema: - type: string - required: true - description: KAD instance ID - - in: query - name: catalog - schema: - type: string - required: false - description: Filter by catalogs (comma separated) - responses: - '200': - description: List of template releases - content: - application/json: - schema: - type: object - required: [templatereleases] - properties: - templatereleases: - type: array - items: - $ref: '../../definition/TemplateRelease.yaml' - default: - description: Server error - content: - application/json: - schema: - $ref: '../../definition/ServerError.yaml' - diff --git a/go.mod b/go.mod index 97e1264..0c7ea6a 100644 --- a/go.mod +++ b/go.mod @@ -77,6 +77,9 @@ require ( github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fluxcd/pkg/apis/acl v0.6.0 // indirect + github.com/fluxcd/pkg/apis/meta v1.10.0 // indirect + github.com/fluxcd/source-controller/api v1.5.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gin-contrib/sse v1.0.0 // indirect @@ -96,7 +99,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/gomodule/redigo v1.9.2 // indirect - github.com/google/btree v1.0.1 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-containerregistry v0.20.3 // indirect @@ -221,6 +224,7 @@ require ( k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect oras.land/oras-go v1.2.5 // indirect oras.land/oras-go/v2 v2.5.0 // indirect + sigs.k8s.io/controller-runtime v0.20.1 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/kustomize/api v0.18.0 // indirect sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect diff --git a/go.sum b/go.sum index 9173e8d..6bc2662 100644 --- a/go.sum +++ b/go.sum @@ -121,6 +121,12 @@ github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBD github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fluxcd/pkg/apis/acl v0.6.0 h1:rllf5uQLzTow81ZCslkQ6LPpDNqVQr6/fWaNksdUEtc= +github.com/fluxcd/pkg/apis/acl v0.6.0/go.mod h1:IVDZx3MAoDWjlLrJHMF9Z27huFuXAEQlnbWw0M6EcTs= +github.com/fluxcd/pkg/apis/meta v1.10.0 h1:rqbAuyl5ug7A5jjRf/rNwBXmNl6tJ9wG2iIsriwnQUk= +github.com/fluxcd/pkg/apis/meta v1.10.0/go.mod h1:n7NstXHDaleAUMajcXTVkhz0MYkvEXy1C/eLI/t1xoI= +github.com/fluxcd/source-controller/api v1.5.0 h1:caSR+u/r2Vh0jq/0pNR0r1zLxyvgatWuGSV2mxgTB/I= +github.com/fluxcd/source-controller/api v1.5.0/go.mod h1:OZPuHMlLH2E2mnj6Q5DLkWfUOmJ20zA1LIvUVfNsYl8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= @@ -197,6 +203,7 @@ github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -583,6 +590,8 @@ oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= +sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= +sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= diff --git a/internal/config/config.go b/internal/config/config.go index 6f91c12..47f156c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -28,12 +28,11 @@ import ( // Application configuration type ApplicationConfig struct { - Server Server `mapstructure:"server"` - Security Security `mapstructure:"security"` - Logging Logging `mapstructure:"logging"` - Swagger Swagger `mapstructure:"swagger"` - Kad []model.KadInstance `mapstructure:"kad"` - Catalogs []*model.Catalog `mapstructure:"catalog"` + Server Server `mapstructure:"server"` + Security Security `mapstructure:"security"` + Logging Logging `mapstructure:"logging"` + Swagger Swagger `mapstructure:"swagger"` + Catalogs []*model.Catalog `mapstructure:"catalog"` } // Server configuration diff --git a/internal/config/config_test.go b/internal/config/config_test.go index aa85d83..75ec670 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -196,19 +196,6 @@ func Test_LoadConfig_Catalog(t *testing.T) { assert.False(t, catalog.IsAuthenticated(), fmt.Sprintf("The catalog '%s' should not be authenticated", catalog.ID)) } -func Test_LoadConfig_Kad(t *testing.T) { - // Given - viper.Set("config", "testdata/application.yaml") - // When - KadInstances := GetAppConfig().Kad - // Then - assert.Equal(t, "sandbox", KadInstances[0].ID, "Id") - assert.Equal(t, "Sandbox de idir", KadInstances[0].Name, "Name") - assert.Equal(t, "https://host.docker.internal:6553/api/kad/v1", KadInstances[0].APIURL, "ApiUrl") - assert.Equal(t, "JUDtoP55C2dLfeaXqSbehhKKRdmAWTfj", KadInstances[0].AuthBearer, "AuthBearer") - assert.True(t, KadInstances[0].InsecureSkipVerify, "InsecureSkipVerify should be true") -} - func Test_LoadConfig_ConfigFileNotFound(t *testing.T) { defer func() { if r := recover(); r != nil { diff --git a/internal/config/testdata/application.yaml b/internal/config/testdata/application.yaml index 9b1fc6b..80b4bd8 100644 --- a/internal/config/testdata/application.yaml +++ b/internal/config/testdata/application.yaml @@ -74,13 +74,6 @@ swagger: security: - oauth2: [openid, email, profile, roles] -kad: - - id: sandbox - name: Sandbox de idir - apiUrl: https://host.docker.internal:6553/api/kad/v1 - authBearer: JUDtoP55C2dLfeaXqSbehhKKRdmAWTfj - insecureSkipVerify: true - catalog: - id: infra01 name: infra01 catalog diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 98770b4..48001f3 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -32,14 +32,4 @@ const ( SwaggerAPIDocsURI = OkdpServerBaseURL + "/api-docs" HealthzURI = "/healthz" ReadinessURI = "/readiness" - // ComponentURL is the kad components URI - ComponentURL = "/api/kad/v1/mycluster/components" - // ComponentURL is the kad component releases URI - ComponentReleaseURL = "/api/kad/v1/mycluster/component-releases" - // ComponentURL is the kad template releases URI - TemplateReleaseURL = "/api/kad/v1/mycluster/template-releases" - // ComponentURL is the kad catalogs URI - CatalogURL = "/api/kad/v1/mycluster/catalogs" - // GitURL is the kad GIT URI - GitURL = "/api/git/v1/mycluster" ) diff --git a/internal/controllers/component_controller.go b/internal/controllers/component_controller.go deleted file mode 100644 index 0b82e40..0000000 --- a/internal/controllers/component_controller.go +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package controllers - -import ( - "net/http" - - "github.com/gin-gonic/gin" - _component "github.com/okdp/okdp-server/api/openapi/v3/_api/components" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/services" -) - -type IComponentController struct { - componentService *services.ComponentService -} - -func ComponentController() *IComponentController { - return &IComponentController{ - componentService: services.NewComponentService(), - } -} - -func (r IComponentController) ListComponents(c *gin.Context, kadInstanceID string, params _component.ListComponentsParams) { - components, err := r.componentService.List(kadInstanceID, params.Catalog) - if err != nil { - log.Error("Unable to list Components on kad instance %s, details: %+v", kadInstanceID, err) - c.JSON(err.Status, err) - return - } - c.JSON(http.StatusOK, components) -} - -func (r IComponentController) GetComponentsByName(c *gin.Context, kadInstanceID string, name string, params _component.GetComponentsByNameParams) { - // Workaround - Kad should return a components by name - log.Info("Get component by name '%s' and catalog '%s' on kad instanceId '%s'", name, params.Catalog, kadInstanceID) - components, err := r.componentService.List(kadInstanceID, params.Catalog) - if err != nil { - log.Error("Unable to list Components on kad instance %s, details: %+v", kadInstanceID, err) - c.JSON(err.Status, err) - return - } - var filtered model.Components = []*model.Component{} - for _, component := range *components { - if component.Spec.Name == name { - filtered = append(filtered, component) - } - } - c.JSON(http.StatusOK, filtered) -} diff --git a/internal/controllers/component_release_controller.go b/internal/controllers/component_release_controller.go deleted file mode 100644 index b6ad5db..0000000 --- a/internal/controllers/component_release_controller.go +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package controllers - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - _component "github.com/okdp/okdp-server/api/openapi/v3/_api/componentreleases" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/model" - auth "github.com/okdp/okdp-server/internal/security/authc/model" - "github.com/okdp/okdp-server/internal/services" -) - -type IComponentReleaseController struct { - componentReleaseService *services.ComponentReleaseService -} - -func ComponentReleaseController() *IComponentReleaseController { - return &IComponentReleaseController{ - componentReleaseService: services.NewComponentReleaseService(), - } -} - -func (r IComponentReleaseController) ListComponentReleases(c *gin.Context, kadInstanceID string, params _component.ListComponentReleasesParams) { - components, err := r.componentReleaseService.List(kadInstanceID, params.Catalog) - if err != nil { - log.Error("Unable to list Component Releases on kad instance %s, details: %+v", kadInstanceID, err) - c.JSON(err.Status, err) - return - } - c.JSON(http.StatusOK, components) -} - -func (r IComponentReleaseController) GetComponentRelease(c *gin.Context, kadInstanceID string, name string, params _component.GetComponentReleaseParams) { - component, err := r.componentReleaseService.Get(kadInstanceID, name, params.Catalog) - if err != nil { - log.Error("Unable to get Component Release '%s' on kad instance %s, details: %+v", name, kadInstanceID, err) - c.JSON(err.Status, err) - return - } - if component == nil { - c.JSON(http.StatusNotFound, fmt.Sprintf("Component with id %s not found", name)) - return - } - c.JSON(http.StatusOK, component) - -} - -func (r IComponentReleaseController) CreateOrUpdateComponentRelease(c *gin.Context, kadInstanceID string, name string) { - - var componentReleaseRequest model.ComponentReleaseRequest - if err := c.ShouldBindJSON(&componentReleaseRequest); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - - maybeUserInfo, _ := c.Get(constants.OAuth2UserInfo) - userInfo, _ := maybeUserInfo.(*auth.UserInfo) - commitData := map[string]string{ - "commit-message": componentReleaseRequest.Comment, - "committer-name": userInfo.Name, - "committer-email": userInfo.Email, - } - - gitCommitReponse, err := r.componentReleaseService.CreateOrUpdateComponentRelease(kadInstanceID, name, componentReleaseRequest, commitData) - if err != nil { - log.Error("Unable to create or update component release '%s' in Git folder '%s' on kad instance %s, details: %+v", name, componentReleaseRequest.GitRepoFolder, kadInstanceID, err) - c.JSON(err.Status, err) - return - } - - c.JSON(http.StatusOK, gitCommitReponse) - -} diff --git a/internal/controllers/kad_contoller.go b/internal/controllers/kad_contoller.go deleted file mode 100644 index b643235..0000000 --- a/internal/controllers/kad_contoller.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package controllers - -import ( - "net/http" - - "github.com/gin-gonic/gin" - "github.com/okdp/okdp-server/internal/kad/client" -) - -type IKadController struct { - clients *client.KadClients -} - -func KadController() *IKadController { - clients := client.GetClients() - return &IKadController{ - clients: clients, - } -} - -func (r IKadController) GetKadInstance(c *gin.Context, kadInstanceID string) { - instance, err := client.GetInstanceByID(kadInstanceID) - if err != nil { - c.JSON(err.Status, err) - } else { - c.JSON(http.StatusOK, instance) - } -} - -func (r IKadController) ListKadInstances(c *gin.Context) { - instances := client.ListInstances() - c.JSON(http.StatusOK, instances) -} diff --git a/internal/controllers/register.go b/internal/controllers/register.go index 35880b1..496c176 100644 --- a/internal/controllers/register.go +++ b/internal/controllers/register.go @@ -19,11 +19,6 @@ package controllers import ( "github.com/gin-gonic/gin" _catalog "github.com/okdp/okdp-server/api/openapi/v3/_api/catalogs" - _componentrelease "github.com/okdp/okdp-server/api/openapi/v3/_api/componentreleases" - _component "github.com/okdp/okdp-server/api/openapi/v3/_api/components" - _kad "github.com/okdp/okdp-server/api/openapi/v3/_api/kad" - _service "github.com/okdp/okdp-server/api/openapi/v3/_api/services" - _templaterelease "github.com/okdp/okdp-server/api/openapi/v3/_api/templatereleases" _user "github.com/okdp/okdp-server/api/openapi/v3/_api/users" "github.com/okdp/okdp-server/internal/config" "github.com/okdp/okdp-server/internal/constants" @@ -40,12 +35,6 @@ type Group struct { func (g *Group) RegisterControllers() { _user.RegisterHandlers(g, UserProfileController()) _catalog.RegisterHandlers(g, CatalogController()) - - _componentrelease.RegisterHandlers(g, ComponentReleaseController()) - _templaterelease.RegisterHandlers(g, TemplateReleaseController()) - _component.RegisterHandlers(g, ComponentController()) - _service.RegisterHandlers(g, ServiceController()) - _kad.RegisterHandlers(g, KadController()) } func (r *Router) RegisterSwaggerAPIDoc(swaggerConf config.Swagger) { diff --git a/internal/controllers/service_controller.go b/internal/controllers/service_controller.go deleted file mode 100644 index 67c7c59..0000000 --- a/internal/controllers/service_controller.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package controllers - -import ( - "net/http" - - "github.com/gin-gonic/gin" - _services "github.com/okdp/okdp-server/api/openapi/v3/_api/services" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/services" -) - -type IServiceController struct { - service *services.Service -} - -func ServiceController() *IServiceController { - service, err := services.NewService() - if err != nil { - return nil - } - return &IServiceController{ - service: service, - } -} - -func (r IServiceController) ListServices(c *gin.Context, kadInstanceID string, params _services.ListServicesParams) { - services, err := r.service.List(kadInstanceID, params.Catalog) - if err != nil { - log.Error("Unable to list services, details: %+v", err) - c.JSON(err.Status, err) - return - } - c.JSON(http.StatusOK, services) -} diff --git a/internal/controllers/template_release_controller.go b/internal/controllers/template_release_controller.go deleted file mode 100644 index b27106a..0000000 --- a/internal/controllers/template_release_controller.go +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package controllers - -import ( - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - _component "github.com/okdp/okdp-server/api/openapi/v3/_api/templatereleases" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/services" -) - -type ITemplateReleaseController struct { - templateReleaseService *services.TemplateReleaseService -} - -func TemplateReleaseController() *ITemplateReleaseController { - return &ITemplateReleaseController{ - templateReleaseService: services.NewTemplateReleaseService(), - } -} - -func (r ITemplateReleaseController) ListTemplateReleases(c *gin.Context, kadInstanceID string, params _component.ListTemplateReleasesParams) { - components, err := r.templateReleaseService.List(kadInstanceID, params.Catalog) - if err != nil { - log.Error("Unable to list Template Releases on kad instance '%s', details: %+v", kadInstanceID, err) - c.JSON(err.Status, err) - return - } - c.JSON(http.StatusOK, components) -} - -func (r ITemplateReleaseController) GetTemplateRelease(c *gin.Context, kadInstanceID string, name string, params _component.GetTemplateReleaseParams) { - component, err := r.templateReleaseService.Get(kadInstanceID, name, params.Catalog) - if err != nil { - log.Error("Unable to get Template Release: '%s' on kad instance '%s', details: %+v", name, kadInstanceID, err) - c.JSON(err.Status, err) - return - } - if component == nil { - c.JSON(http.StatusNotFound, fmt.Sprintf("Component with id %s not found", name)) - return - } - c.JSON(http.StatusOK, component) - -} diff --git a/internal/model/kad.go b/internal/integrations/git/client/client.go similarity index 80% rename from internal/model/kad.go rename to internal/integrations/git/client/client.go index 016d89c..24d20b3 100644 --- a/internal/model/kad.go +++ b/internal/integrations/git/client/client.go @@ -1,5 +1,5 @@ /* - * Copyright 2024 okdp.io + * Copyright 2025 okdp.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,4 @@ * limitations under the License. */ -package model - -import ( - "github.com/okdp/okdp-server/api/openapi/v3/_api" -) - -type KadInstance = _api.KadInstance +package git diff --git a/internal/model/component.go b/internal/integrations/git/git_repo.go similarity index 77% rename from internal/model/component.go rename to internal/integrations/git/git_repo.go index bf3c2f1..24d20b3 100644 --- a/internal/model/component.go +++ b/internal/integrations/git/git_repo.go @@ -1,5 +1,5 @@ /* - * Copyright 2024 okdp.io + * Copyright 2025 okdp.io * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,4 @@ * limitations under the License. */ -package model - -import ( - "github.com/okdp/okdp-server/api/openapi/v3/_api" -) - -type Component = _api.Component -type Components = []*Component +package git diff --git a/internal/kad/client/client.go b/internal/kad/client/client.go deleted file mode 100644 index 59d5a69..0000000 --- a/internal/kad/client/client.go +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package client - -import ( - "crypto/tls" - "encoding/json" - "net/http" - "sync" - - "github.com/go-resty/resty/v2" - "github.com/okdp/okdp-server/internal/config" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" - "github.com/okdp/okdp-server/internal/utils" -) - -var ( - instance *KadClients - once sync.Once -) - -type KadClients struct { - clients map[string]*KadClient -} - -type KadClient struct { - *resty.Client -} - -type Request struct { - *resty.Request -} - -// KAD errors response are plain text -// type KadError struct { -// message string -// statusCode int -// } - -func GetClients() *KadClients { - once.Do(func() { - clients := make(map[string]*KadClient) - kadsConf := config.GetAppConfig().Kad - for _, kadConf := range kadsConf { - log.Info("KAD configuration: %s", kadConf) - client := resty.New() - client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: kadConf.InsecureSkipVerify}). - SetAuthToken(kadConf.AuthBearer). - SetHeader("Content-Type", "application/json"). - SetBaseURL(kadConf.APIURL) - clients[kadConf.ID] = &KadClient{client} - } - instance = &KadClients{clients: clients} - }) - return instance -} - -func (c *KadClients) ID(id string) (*KadClient, *servererrors.ServerError) { - client, found := c.clients[id] - if !found { - return nil, invalidInstanceError(id) - } - return client, nil -} - -func ListInstances() []model.KadInstance { - return config.GetAppConfig().Kad -} - -func GetInstanceByID(id string) (model.KadInstance, *servererrors.ServerError) { - instances := ListInstances() - for _, i := range instances { - if i.ID == id { - return i, nil - } - } - return model.KadInstance{}, servererrors.OfType(servererrors.OkdpServer). - NotFoundError("kad instance with id %s not found", id) -} - -func DoGet[T any](request *resty.Request) (*T, *servererrors.ServerError) { - request.Method = resty.MethodGet - return doExecute[T](request) -} - -func DoPut[T any](request *resty.Request) (*T, *servererrors.ServerError) { - request.Method = resty.MethodPut - return doExecute[T](request) -} - -func (c *KadClient) NewRequest(url string) *resty.Request { - req := c.R() - req.URL = url - return req -} - -func doExecute[T any](request *resty.Request) (*T, *servererrors.ServerError) { - log.Info("Sending %s request to KAD at the endpoint %s:", request.Method, request.URL) - var object T - // request.SetError(&KadError{}) - resp, err := request.Send() - - if err != nil { - return nil, servererrors.OfType(servererrors.Kad).Forbidden(err) - } - - if resp.IsError() { - // KAD errors response are plain text - return nil, servererrors.OfType(servererrors.Kad). - GenericError(resp.StatusCode(), "Kad rejected the request, reason: %s", resp.String()) - } - - err = json.Unmarshal([]byte(resp.String()), &object) - - if err != nil { - return &object, servererrors.OfType(servererrors.OkdpServer). - GenericError(http.StatusUnprocessableEntity, "Unable to process kad response, reason: %+v", err) - } - - return &object, nil -} - -func invalidInstanceError(provided string) *servererrors.ServerError { - instances := utils.Map(ListInstances(), func(k model.KadInstance) string { return k.ID }) - return servererrors.OfType(servererrors.OkdpServer). - NotFoundError("kad instance with id %s not found, valid ones: %+v", provided, instances) -} diff --git a/internal/kad/component_client.go b/internal/kad/component_client.go deleted file mode 100644 index 997710b..0000000 --- a/internal/kad/component_client.go +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kad - -import ( - "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/kad/client" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type ComponentClient struct { - KAD *client.KadClients -} - -func NewComponentClient() *ComponentClient { - return &ComponentClient{ - KAD: client.GetClients(), - } -} - -func (c ComponentClient) Get(kadInstanceID string, name string, catalog *string) (*model.Component, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.ComponentURL + "/" + name) - if catalog != nil { - req = req.SetQueryParam("catalog", *catalog) - } - return client.DoGet[model.Component](req) -} - -func (c ComponentClient) List(kadInstanceID string, catalog *string) (*model.Components, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.ComponentURL) - if catalog != nil { - req = req.SetQueryParam("catalog", *catalog) - } - return client.DoGet[model.Components](req) -} diff --git a/internal/kad/component_release_client.go b/internal/kad/component_release_client.go deleted file mode 100644 index 9910244..0000000 --- a/internal/kad/component_release_client.go +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kad - -import ( - "bytes" - "net/http" - - "github.com/go-resty/resty/v2" - "github.com/goccy/go-yaml" - "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/kad/client" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type ComponentReleaseClient struct { - KAD *client.KadClients -} - -func NewComponentReleaseClient() *ComponentReleaseClient { - return &ComponentReleaseClient{ - KAD: client.GetClients(), - } -} - -func (c ComponentReleaseClient) Get(kadInstanceID string, name string, catalog *string) (*model.ComponentReleaseResponse, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.ComponentReleaseURL + "/" + name) - if catalog != nil { - req = req.SetQueryParam("catalog", *catalog) - } - return client.DoGet[model.ComponentReleaseResponse](req) -} - -func (c ComponentReleaseClient) List(kadInstanceID string, catalog *string) (*model.ComponentReleasesResponse, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.ComponentReleaseURL) - if catalog != nil { - req = req.SetQueryParam("catalog", *catalog) - } - return client.DoGet[model.ComponentReleasesResponse](req) -} - -func (c ComponentReleaseClient) UploadAsYaml(kadInstanceID string, name string, - componentReleaseRequest model.ComponentReleaseRequest, - commitData map[string]string) (*model.GitCommit, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - - // Convert the ComponentReleases into YAML - result := map[string]interface{}{ - "componentReleases": componentReleaseRequest.ComponentReleases, - } - componentReleasesYAML, err2 := yaml.Marshal(result) - if err2 != nil { - log.Error("Error marshaling ComponentReleases to YAML: %v", err) - return nil, servererrors.OfType(servererrors.OkdpServer). - GenericError(http.StatusBadRequest, "Unable to parse json to yaml: %+v", err2) - } - - log.Info("Uploading Component release (Name: %s, Git Path: %s): \n%s, \n Author Info: %s", name, componentReleaseRequest.GitRepoFolder, - string(componentReleasesYAML), commitData) - - req := kadClient.NewRequest(constants.GitURL + "/" + componentReleaseRequest.GitRepoFolder + "/" + name + ".yaml"). - SetMultipartFields( - &resty.MultipartField{ - Param: "kadfile", - FileName: name + ".yaml", - ContentType: "application/x-yaml", - Reader: bytes.NewReader(componentReleasesYAML), - }, - ). - SetFormData(commitData) - - return client.DoPut[model.GitCommit](req) -} diff --git a/internal/kad/template_release_client.go b/internal/kad/template_release_client.go deleted file mode 100644 index cae8d37..0000000 --- a/internal/kad/template_release_client.go +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kad - -import ( - "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/kad/client" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type TemplateReleaseClient struct { - KAD *client.KadClients -} - -func NewTemplateReleaseClient() *TemplateReleaseClient { - return &TemplateReleaseClient{ - KAD: client.GetClients(), - } -} - -func (c TemplateReleaseClient) Get(kadInstanceID string, name string, catalog *string) (*model.TemplateRelease, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.TemplateReleaseURL + "/" + name) - if catalog != nil { - req = req.SetQueryParam("catalog", *catalog) - } - return client.DoGet[model.TemplateRelease](req) -} - -func (c TemplateReleaseClient) List(kadInstanceID string, catalog *string) (*model.TemplateReleases, *servererrors.ServerError) { - kadClient, err := c.KAD.ID(kadInstanceID) - if err != nil { - return nil, err - } - req := kadClient.NewRequest(constants.TemplateReleaseURL) - if catalog != nil { - req = req.SetQueryParam("catalog", *catalog) - } - return client.DoGet[model.TemplateReleases](req) -} diff --git a/internal/model/catalog.go b/internal/model/catalog.go index 59967be..cfb9c0b 100644 --- a/internal/model/catalog.go +++ b/internal/model/catalog.go @@ -39,4 +39,3 @@ func (c Catalog) RepoHost() string { func (c Catalog) IsAuthenticated() bool { return c.Credentials != nil } - diff --git a/internal/model/component_release.go b/internal/model/component_release.go deleted file mode 100644 index d93bd8e..0000000 --- a/internal/model/component_release.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package model - -import ( - "github.com/okdp/okdp-server/api/openapi/v3/_api" - "github.com/okdp/okdp-server/internal/utils" -) - -type ComponentReleaseRequest _api.ComponentReleaseRequest -type ComponentReleaseResponse _api.ComponentReleaseResponse -type ComponentReleasesResponse []*ComponentReleaseResponse -type FlatComponent _api.FlatComponent -type FlatComponents []*FlatComponent - -func (r *ComponentReleasesResponse) Flatten() *FlatComponents { - var flatComponents = make(FlatComponents, 0, 100) - for _, c := range *r { - extC := &FlatComponent{ - ComponentName: c.Spec.Component.Ref.Name, - ComponentVersion: c.Spec.Component.Ref.Version, - PackageName: c.Spec.HelmReleaseName, - PackageVersion: c.Spec.Component.Source.Version, - ComponentReleaseName: c.Spec.Name, - Enabled: c.Spec.Enabled, - Suspended: c.Spec.Component.Suspended, - Protected: c.Spec.Component.Protected, - Catalogs: utils.ArrayNullToEmpty(c.Status.Catalogs), - Usage: c.Status.Usage, - } - flatComponents = append(flatComponents, extC) - } - return &flatComponents -} - -func (f *FlatComponents) AddTemplateReleaseInfo(tri *TemplateReleaseInfo) *FlatComponents { - for _, c := range *f { - summary, found := tri.GetByComponentReleaseName(c.ComponentReleaseName) - if found { - c.TemplateName = summary.TemplateName - c.TemplateVersion = summary.TemplateVersion - c.TemplateReleaseName = summary.TemplateReleaseName - c.Catalogs = append(c.Catalogs, summary.Catalogs...) - } - } - return f -} - -func (f *FlatComponents) ConvertToService() *Services { - var services Services - - componentsByServiceName := make(map[string][]FlatComponent) - for _, c := range *f { - var serviceName string - if c.TemplateReleaseName != "" { - serviceName = c.TemplateReleaseName - } else { - serviceName = c.ComponentReleaseName - } - componentsByServiceName[serviceName] = append(componentsByServiceName[serviceName], *c) - } - - for serviceName, components := range componentsByServiceName { - services = append(services, &Service{ - Name: serviceName, - IsComposition: len(components) > 1, - FlatComponents: components, - }) - } - - return &services - -} diff --git a/internal/model/service.go b/internal/model/service.go deleted file mode 100644 index 6fc5199..0000000 --- a/internal/model/service.go +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package model - -// https://github.com/oapi-codegen/oapi-codegen/issues/1139 -type Service struct { - Name string `json:"name"` - IsComposition bool `json:"isComposition"` - FlatComponents []FlatComponent `json:"flatComponents"` -} - -type Services []*Service diff --git a/internal/model/template_release.go b/internal/model/template_release.go deleted file mode 100644 index c9ed61e..0000000 --- a/internal/model/template_release.go +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package model - -import ( - "github.com/okdp/okdp-server/api/openapi/v3/_api" -) - -type TemplateRelease _api.TemplateRelease -type TemplateReleases []TemplateRelease - -type TemplateReleaseSummary struct { - TemplateName string - TemplateVersion string - TemplateReleaseName string - Catalogs []string -} - -type TemplateReleaseInfo struct { - mapping map[string]TemplateReleaseSummary -} - -func (r *TemplateReleases) GroupTemplateReleaseInfoByComponentRelease() *TemplateReleaseInfo { - m := &TemplateReleaseInfo{ - mapping: make(map[string]TemplateReleaseSummary), - } - - for _, t := range *r { - for _, c := range t.Status.Children { - m.mapping[c] = TemplateReleaseSummary{ - TemplateName: t.Spec.Template.Ref.Name, - TemplateVersion: t.Spec.Template.Ref.Version, - TemplateReleaseName: t.Spec.Name, - Catalogs: t.Status.Catalogs, - } - } - } - - return m -} - -func (r *TemplateReleaseInfo) GetByComponentReleaseName(name string) (*TemplateReleaseSummary, bool) { - s, found := r.mapping[name] - if !found { - return nil, false - } - return &s, true -} diff --git a/internal/servererrors/server_errors.go b/internal/servererrors/server_errors.go index 5ae16e1..2059d00 100644 --- a/internal/servererrors/server_errors.go +++ b/internal/servererrors/server_errors.go @@ -13,7 +13,6 @@ const ( // Error types OkdpServer = "okdp_server" Registry = "registry" - Kad = "kad" ) func OfType(errorType string) *ServerError { diff --git a/internal/services/component.go b/internal/services/component.go deleted file mode 100644 index 039f796..0000000 --- a/internal/services/component.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package services - -import ( - "github.com/okdp/okdp-server/internal/kad" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type ComponentService struct { - component *kad.ComponentClient -} - -func NewComponentService() *ComponentService { - return &ComponentService{ - component: kad.NewComponentClient(), - } -} - -func (s ComponentService) Get(kadInstanceID string, name string, catalog *string) (*model.Component, *servererrors.ServerError) { - return s.component.Get(kadInstanceID, name, catalog) -} - -func (s ComponentService) List(kadInstanceID string, catalog *string) (*model.Components, *servererrors.ServerError) { - return s.component.List(kadInstanceID, catalog) -} diff --git a/internal/services/component_releases.go b/internal/services/component_releases.go deleted file mode 100644 index a8ef60c..0000000 --- a/internal/services/component_releases.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package services - -import ( - "github.com/okdp/okdp-server/internal/kad" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type ComponentReleaseService struct { - componentRelease *kad.ComponentReleaseClient -} - -func NewComponentReleaseService() *ComponentReleaseService { - return &ComponentReleaseService{ - componentRelease: kad.NewComponentReleaseClient(), - } -} - -func (s ComponentReleaseService) Get(kadInstanceID string, name string, catalog *string) (*model.ComponentReleaseResponse, *servererrors.ServerError) { - return s.componentRelease.Get(kadInstanceID, name, catalog) -} - -func (s ComponentReleaseService) List(kadInstanceID string, catalog *string) (*model.ComponentReleasesResponse, *servererrors.ServerError) { - return s.componentRelease.List(kadInstanceID, catalog) -} - -func (s ComponentReleaseService) CreateOrUpdateComponentRelease(kadInstanceID string, name string, componentReleaseRequest model.ComponentReleaseRequest, commitData map[string]string) (*model.GitCommit, *servererrors.ServerError) { - return s.componentRelease.UploadAsYaml(kadInstanceID, name, componentReleaseRequest, commitData) -} diff --git a/internal/services/service.go b/internal/services/service.go deleted file mode 100644 index c9c3762..0000000 --- a/internal/services/service.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package services - -import ( - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type Service struct { - componentReleaseService *ComponentReleaseService - templateReleaseService *TemplateReleaseService -} - -func NewService() (*Service, error) { - return &Service{ - componentReleaseService: NewComponentReleaseService(), - templateReleaseService: NewTemplateReleaseService(), - }, nil -} - -func (s Service) List(kadInstanceID string, catalog *string) (*model.Services, *servererrors.ServerError) { - componentReleases, err := s.componentReleaseService.List(kadInstanceID, catalog) - if err != nil { - return nil, err - } - temmplateReleases, err := s.templateReleaseService.List(kadInstanceID, catalog) - if err != nil { - return nil, err - } - tri := temmplateReleases.GroupTemplateReleaseInfoByComponentRelease() - return componentReleases.Flatten().AddTemplateReleaseInfo(tri).ConvertToService(), nil -} diff --git a/internal/services/template_release.go b/internal/services/template_release.go deleted file mode 100644 index 0ca3e71..0000000 --- a/internal/services/template_release.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2024 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package services - -import ( - "github.com/okdp/okdp-server/internal/kad" - "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" -) - -type TemplateReleaseService struct { - templateRelease *kad.TemplateReleaseClient -} - -func NewTemplateReleaseService() *TemplateReleaseService { - return &TemplateReleaseService{ - templateRelease: kad.NewTemplateReleaseClient(), - } -} - -func (s TemplateReleaseService) Get(kadInstanceID string, name string, catalog *string) (*model.TemplateRelease, *servererrors.ServerError) { - return s.templateRelease.Get(kadInstanceID, name, catalog) -} - -func (s TemplateReleaseService) List(kadInstanceID string, catalog *string) (*model.TemplateReleases, *servererrors.ServerError) { - return s.templateRelease.List(kadInstanceID, catalog) -} From 7206f35a0195b6a2278afe7a20828bfb0dce8208 Mon Sep 17 00:00:00 2001 From: iizitounene Date: Wed, 14 May 2025 10:36:00 +0200 Subject: [PATCH 04/14] refactor: refactoring --- .../v3/_api/catalogs/catalogs-server.go | 30 ++--- api/openapi/v3/definition/Catalog.yaml | 4 +- api/openapi/v3/definition/GitCommit.yaml | 2 + api/openapi/v3/definition/ServerError.yaml | 14 -- api/openapi/v3/definition/UserProfile.yaml | 2 +- .../v3/paths/catalogs/catalog-by-id.yaml | 4 +- .../v3/paths/catalogs/catalog-list.yaml | 4 +- .../v3/paths/catalogs/package-by-name.yaml | 4 +- .../v3/paths/catalogs/package-definition.yaml | 4 +- .../v3/paths/catalogs/package-list.yaml | 4 +- .../v3/paths/catalogs/package-schema.yaml | 4 +- .../catalogs/package-versions-by-name.yaml | 4 +- cmd/root.go | 4 +- internal/{ => common}/constants/constants.go | 2 + internal/{ => common}/logging/logging.go | 0 internal/controllers/catalog_controller.go | 12 +- .../{registry => oci}/client/client.go | 123 ++++++++++-------- .../{registry => oci}/repo_catalog.go | 15 +-- internal/model/catalog.go | 10 ++ internal/model/server_response.go | 118 +++++++++++++++++ internal/security/authc/auth.go | 9 +- .../authc/provider/basic/basic_auth.go | 2 +- .../authc/provider/basic/basic_auth_test.go | 2 +- .../security/authc/provider/bearer/bearer.go | 20 +-- internal/security/authc/provider/oidc/oidc.go | 45 ++++--- internal/security/authz/authz.go | 23 ++-- internal/security/authz/authz_test.go | 4 +- internal/servererrors/server_errors.go | 53 -------- internal/services/catalog.go | 25 ++-- internal/utils/auth_utils.go | 51 ++++++++ internal/utils/auth_utils_test.go | 75 +++++++++++ internal/utils/collection_utils.go | 42 ++++++ internal/utils/collection_utils_test.go | 79 +++++++++++ internal/utils/env_utils.go | 5 +- internal/utils/env_utils_test.go | 8 +- internal/utils/file_utils.go | 42 ++++++ internal/utils/file_utils_test.go | 86 ++++++++++++ internal/utils/hash_utils.go | 30 +++++ internal/utils/hash_utils_tests.go | 59 +++++++++ internal/utils/parameter_utils.go | 39 ++++++ internal/utils/parameter_utils_test.go | 80 ++++++++++++ 41 files changed, 906 insertions(+), 237 deletions(-) delete mode 100644 api/openapi/v3/definition/ServerError.yaml rename internal/{ => common}/constants/constants.go (95%) rename internal/{ => common}/logging/logging.go (100%) rename internal/integrations/{registry => oci}/client/client.go (64%) rename internal/integrations/{registry => oci}/repo_catalog.go (73%) create mode 100644 internal/model/server_response.go delete mode 100644 internal/servererrors/server_errors.go create mode 100644 internal/utils/auth_utils_test.go create mode 100644 internal/utils/file_utils.go create mode 100644 internal/utils/file_utils_test.go create mode 100644 internal/utils/hash_utils.go create mode 100644 internal/utils/hash_utils_tests.go create mode 100644 internal/utils/parameter_utils.go create mode 100644 internal/utils/parameter_utils_test.go diff --git a/api/openapi/v3/_api/catalogs/catalogs-server.go b/api/openapi/v3/_api/catalogs/catalogs-server.go index b684597..4453c75 100644 --- a/api/openapi/v3/_api/catalogs/catalogs-server.go +++ b/api/openapi/v3/_api/catalogs/catalogs-server.go @@ -21,13 +21,13 @@ type ServerInterface interface { GetCatalog(c *gin.Context, catalogId string) // Get a list of packages by catalog id // (GET /catalogs/{catalogId}/packages) - GetPackages(c *gin.Context, catalogId string) + ListPackages(c *gin.Context, catalogId string) // Get package by catalog id and package name // (GET /catalogs/{catalogId}/packages/{name}) - GetPackageByName(c *gin.Context, catalogId string, name string) + GetPackage(c *gin.Context, catalogId string, name string) // List versions for a specific package // (GET /catalogs/{catalogId}/packages/{name}/versions) - GetPackageVersionsByName(c *gin.Context, catalogId string, name string) + GetPackageVersions(c *gin.Context, catalogId string, name string) // Get package definition // (GET /catalogs/{catalogId}/packages/{name}/versions/{version}) GetPackageDefinition(c *gin.Context, catalogId string, name string, version string) @@ -82,8 +82,8 @@ func (siw *ServerInterfaceWrapper) GetCatalog(c *gin.Context) { siw.Handler.GetCatalog(c, catalogId) } -// GetPackages operation middleware -func (siw *ServerInterfaceWrapper) GetPackages(c *gin.Context) { +// ListPackages operation middleware +func (siw *ServerInterfaceWrapper) ListPackages(c *gin.Context) { var err error @@ -103,11 +103,11 @@ func (siw *ServerInterfaceWrapper) GetPackages(c *gin.Context) { } } - siw.Handler.GetPackages(c, catalogId) + siw.Handler.ListPackages(c, catalogId) } -// GetPackageByName operation middleware -func (siw *ServerInterfaceWrapper) GetPackageByName(c *gin.Context) { +// GetPackage operation middleware +func (siw *ServerInterfaceWrapper) GetPackage(c *gin.Context) { var err error @@ -136,11 +136,11 @@ func (siw *ServerInterfaceWrapper) GetPackageByName(c *gin.Context) { } } - siw.Handler.GetPackageByName(c, catalogId, name) + siw.Handler.GetPackage(c, catalogId, name) } -// GetPackageVersionsByName operation middleware -func (siw *ServerInterfaceWrapper) GetPackageVersionsByName(c *gin.Context) { +// GetPackageVersions operation middleware +func (siw *ServerInterfaceWrapper) GetPackageVersions(c *gin.Context) { var err error @@ -169,7 +169,7 @@ func (siw *ServerInterfaceWrapper) GetPackageVersionsByName(c *gin.Context) { } } - siw.Handler.GetPackageVersionsByName(c, catalogId, name) + siw.Handler.GetPackageVersions(c, catalogId, name) } // GetPackageDefinition operation middleware @@ -285,9 +285,9 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options router.GET(options.BaseURL+"/catalogs", wrapper.ListCatalogs) router.GET(options.BaseURL+"/catalogs/:catalogId", wrapper.GetCatalog) - router.GET(options.BaseURL+"/catalogs/:catalogId/packages", wrapper.GetPackages) - router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name", wrapper.GetPackageByName) - router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions", wrapper.GetPackageVersionsByName) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages", wrapper.ListPackages) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name", wrapper.GetPackage) + router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions", wrapper.GetPackageVersions) router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions/:version", wrapper.GetPackageDefinition) router.GET(options.BaseURL+"/catalogs/:catalogId/packages/:name/versions/:version/schema", wrapper.GetPackageSchema) } diff --git a/api/openapi/v3/definition/Catalog.yaml b/api/openapi/v3/definition/Catalog.yaml index d203248..8ce4f67 100644 --- a/api/openapi/v3/definition/Catalog.yaml +++ b/api/openapi/v3/definition/Catalog.yaml @@ -1,6 +1,6 @@ type: object xml: - name: catalog + name: Catalog required: - "id" - "name" @@ -26,6 +26,8 @@ properties: type: string robotAccountToken: type: string + dockerconfigjson: + type: string packages: type: array items: diff --git a/api/openapi/v3/definition/GitCommit.yaml b/api/openapi/v3/definition/GitCommit.yaml index a0c4b8c..c7b02e7 100644 --- a/api/openapi/v3/definition/GitCommit.yaml +++ b/api/openapi/v3/definition/GitCommit.yaml @@ -1,4 +1,6 @@ type: object +xml: + name: GitCommit properties: committerName: type: string diff --git a/api/openapi/v3/definition/ServerError.yaml b/api/openapi/v3/definition/ServerError.yaml deleted file mode 100644 index 268d27e..0000000 --- a/api/openapi/v3/definition/ServerError.yaml +++ /dev/null @@ -1,14 +0,0 @@ -type: object -xml: - name: serverError -required: - - message - - status - - type -properties: - message: - type: string - status: - type: integer - type: - type: string diff --git a/api/openapi/v3/definition/UserProfile.yaml b/api/openapi/v3/definition/UserProfile.yaml index 51df29d..985d654 100644 --- a/api/openapi/v3/definition/UserProfile.yaml +++ b/api/openapi/v3/definition/UserProfile.yaml @@ -1,6 +1,6 @@ type: object xml: - name: userProfile + name: UserProfile required: - sub - login diff --git a/api/openapi/v3/paths/catalogs/catalog-by-id.yaml b/api/openapi/v3/paths/catalogs/catalog-by-id.yaml index e1626c2..3eeb306 100644 --- a/api/openapi/v3/paths/catalogs/catalog-by-id.yaml +++ b/api/openapi/v3/paths/catalogs/catalog-by-id.yaml @@ -4,7 +4,7 @@ get: Get a catalog by id tags: - catalogs - operationId: getCatalog + operationId: GetCatalog parameters: - in: path name: catalogId @@ -24,5 +24,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/api/openapi/v3/paths/catalogs/catalog-list.yaml b/api/openapi/v3/paths/catalogs/catalog-list.yaml index 990c50f..c212b02 100644 --- a/api/openapi/v3/paths/catalogs/catalog-list.yaml +++ b/api/openapi/v3/paths/catalogs/catalog-list.yaml @@ -4,7 +4,7 @@ get: List all catalogs tags: - catalogs - operationId: listCatalogs + operationId: ListCatalogs responses: '200': description: List of the catalogs @@ -19,5 +19,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/api/openapi/v3/paths/catalogs/package-by-name.yaml b/api/openapi/v3/paths/catalogs/package-by-name.yaml index e3a5a9a..9219f68 100644 --- a/api/openapi/v3/paths/catalogs/package-by-name.yaml +++ b/api/openapi/v3/paths/catalogs/package-by-name.yaml @@ -4,7 +4,7 @@ get: Get package by catalog id and package name tags: - catalogs - operationId: getPackageByName + operationId: GetPackage parameters: - in: path name: catalogId @@ -30,5 +30,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/api/openapi/v3/paths/catalogs/package-definition.yaml b/api/openapi/v3/paths/catalogs/package-definition.yaml index 98ae98b..4b5a70d 100644 --- a/api/openapi/v3/paths/catalogs/package-definition.yaml +++ b/api/openapi/v3/paths/catalogs/package-definition.yaml @@ -4,7 +4,7 @@ get: Get package definition tags: - catalogs - operationId: getPackageDefinition + operationId: GetPackageDefinition parameters: - in: path name: catalogId @@ -37,5 +37,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/api/openapi/v3/paths/catalogs/package-list.yaml b/api/openapi/v3/paths/catalogs/package-list.yaml index bd7aec2..7326561 100644 --- a/api/openapi/v3/paths/catalogs/package-list.yaml +++ b/api/openapi/v3/paths/catalogs/package-list.yaml @@ -4,7 +4,7 @@ get: List of packages by catalog id tags: - catalogs - operationId: getPackages + operationId: ListPackages parameters: - in: path name: catalogId @@ -26,5 +26,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/api/openapi/v3/paths/catalogs/package-schema.yaml b/api/openapi/v3/paths/catalogs/package-schema.yaml index 355b512..c84944b 100644 --- a/api/openapi/v3/paths/catalogs/package-schema.yaml +++ b/api/openapi/v3/paths/catalogs/package-schema.yaml @@ -4,7 +4,7 @@ get: Get package schema (parameters, context, etc) tags: - catalogs - operationId: getPackageSchema + operationId: GetPackageSchema parameters: - in: path name: catalogId @@ -37,5 +37,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml b/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml index 488e033..41021ca 100644 --- a/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml +++ b/api/openapi/v3/paths/catalogs/package-versions-by-name.yaml @@ -4,7 +4,7 @@ get: List versions for a specific package tags: - catalogs - operationId: getPackageVersionsByName + operationId: GetPackageVersions parameters: - in: path name: catalogId @@ -30,5 +30,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/cmd/root.go b/cmd/root.go index 9d18195..93da255 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,9 +19,9 @@ package cmd import ( "os" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/server" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/internal/constants/constants.go b/internal/common/constants/constants.go similarity index 95% rename from internal/constants/constants.go rename to internal/common/constants/constants.go index 48001f3..00be64e 100644 --- a/internal/constants/constants.go +++ b/internal/common/constants/constants.go @@ -32,4 +32,6 @@ const ( SwaggerAPIDocsURI = OkdpServerBaseURL + "/api-docs" HealthzURI = "/healthz" ReadinessURI = "/readiness" + All = "All" + GitRepository = "GitRepository" ) diff --git a/internal/logging/logging.go b/internal/common/logging/logging.go similarity index 100% rename from internal/logging/logging.go rename to internal/common/logging/logging.go diff --git a/internal/controllers/catalog_controller.go b/internal/controllers/catalog_controller.go index 595bccd..0f12e2d 100644 --- a/internal/controllers/catalog_controller.go +++ b/internal/controllers/catalog_controller.go @@ -20,7 +20,7 @@ import ( "net/http" "github.com/gin-gonic/gin" - log "github.com/okdp/okdp-server/internal/logging" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/services" ) @@ -49,7 +49,7 @@ func (r ICatalogController) GetCatalog(c *gin.Context, catalogID string) { c.JSON(http.StatusOK, catalog) } -func (r ICatalogController) GetPackages(c *gin.Context, catalogID string) { +func (r ICatalogController) ListPackages(c *gin.Context, catalogID string) { packages, err := r.catalogService.GetPackages(catalogID) if err != nil { log.Error("Unable to find the packages with Catalog ID '%s', details: %+v", catalogID, err) @@ -59,8 +59,8 @@ func (r ICatalogController) GetPackages(c *gin.Context, catalogID string) { c.JSON(http.StatusOK, packages) } -func (r ICatalogController) GetPackageByName(c *gin.Context, catalogID string, name string) { - result, err := r.catalogService.GetPackageByName(catalogID, name) +func (r ICatalogController) GetPackage(c *gin.Context, catalogID string, name string) { + result, err := r.catalogService.GetPackage(catalogID, name) if err != nil { log.Error("Unable to find the package '%s' with Catalog ID '%s', details: %+v", name, catalogID, err) c.JSON(err.Status, err) @@ -69,8 +69,8 @@ func (r ICatalogController) GetPackageByName(c *gin.Context, catalogID string, n c.JSON(http.StatusOK, result) } -func (r ICatalogController) GetPackageVersionsByName(c *gin.Context, catalogID string, name string) { - r.GetPackageByName(c, catalogID, name) +func (r ICatalogController) GetPackageVersions(c *gin.Context, catalogID string, name string) { + r.GetPackage(c, catalogID, name) } func (r ICatalogController) GetPackageDefinition(c *gin.Context, catalogID string, name string, version string) { diff --git a/internal/integrations/registry/client/client.go b/internal/integrations/oci/client/client.go similarity index 64% rename from internal/integrations/registry/client/client.go rename to internal/integrations/oci/client/client.go index 7969ca4..4189b9b 100644 --- a/internal/integrations/registry/client/client.go +++ b/internal/integrations/oci/client/client.go @@ -33,10 +33,9 @@ import ( "oras.land/oras-go/v2/registry/remote/errcode" "oras.land/oras-go/v2/registry/remote/retry" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" "github.com/okdp/okdp-server/internal/utils" ) @@ -59,41 +58,24 @@ func GetClients() *RepositoryClients { catalogs := config.GetAppConfig().Catalogs for _, catalog := range catalogs { log.Info("Container Registry configuration: %+v", catalog) - - var creds auth.CredentialFunc = func(_ context.Context, _ string) (auth.Credential, error) { - return auth.EmptyCredential, nil - } - - if catalog.IsAuthenticated() { - log.Info("The catalog ID '%s' is authenticated", catalog.ID) - username := utils.GetEnv(*catalog.Credentials.RobotAccountName) - password := utils.GetEnv(*catalog.Credentials.RobotAccountToken) - if username == "" || password == "" { - log.Fatal("Robot account name and robot account token: %s/%s are empty for catalog %s", - *catalog.Credentials.RobotAccountName, *catalog.Credentials.RobotAccountToken, catalog.ID) - } - - creds = auth.StaticCredential(catalog.RepoHost(), auth.Credential{ - Username: username, - Password: password, - }) - } else { - log.Info("The catalog ID '%s' is not authenticated", catalog.ID) - } - - authClient := &auth.Client{ - Client: retry.DefaultClient, - Cache: auth.NewCache(), - Credential: creds, - } - for _, p := range catalog.Packages { repo, err := remote.NewRepository(strings.TrimSuffix(catalog.RepoURL, "/") + "/" + p.Name) if err != nil { log.Fatal("Failed to create a client to the remote repository %s: %v", catalog.RepoURL, err) } - repo.Client = authClient - clients[repoClientKey(catalog.ID, p.Name)] = &RepositoryClient{repo} + + creds, err := getOCIRepoCredentials(catalog) + + if err != nil { + log.Fatal("Unable to get login and password from dockerconfigjson for the repo: %s/%s", catalog.ID, catalog.RepoURL) + } + + repo.Client = &auth.Client{ + Client: retry.DefaultClient, + Cache: auth.NewCache(), + Credential: creds, + } + clients[utils.MapKey(catalog.ID, p.Name)] = &RepositoryClient{repo} } } instance = &RepositoryClients{clients: clients} @@ -109,17 +91,17 @@ func ListCatalogs() []*model.Catalog { return catalogs } -func GetCatalog(catalogID string) (*model.Catalog, *servererrors.ServerError) { +func GetCatalog(catalogID string) (*model.Catalog, *model.ServerResponse) { catalogs := config.GetAppConfig().Catalogs for _, catalog := range catalogs { if strings.EqualFold(catalog.ID, catalogID) { return catalog, nil } } - return nil, CatalogNotFoundError(catalogID) + return nil, model.CatalogNotFoundError(catalogID) } -func GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) { +func GetPackages(catalogID string) ([]*model.Package, *model.ServerResponse) { catalog, err := GetCatalog(catalogID) if err != nil { return nil, err @@ -135,7 +117,7 @@ func GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) return packages, nil } -func GetPackageByName(catalogID string, name string) (*model.Package, *servererrors.ServerError) { +func GetPackage(catalogID string, name string) (*model.Package, *model.ServerResponse) { catalog, err := GetCatalog(catalogID) if err != nil { return nil, err @@ -145,10 +127,10 @@ func GetPackageByName(catalogID string, name string) (*model.Package, *servererr return getPackage(catalogID, p.Name) } } - return nil, CatalogPackageNotFoundError(catalogID, name) + return nil, model.CatalogPackageNotFoundError(catalogID, name) } -func GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *servererrors.ServerError) { +func GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *model.ServerResponse) { repo, err := getRepoClient(catalogID, name) if err != nil { return nil, err @@ -156,7 +138,7 @@ func GetPackageDefinition(catalogID string, name string, version string) (map[st return repo.fetchDefinition(version) } -func getPackage(catalogID string, name string) (*model.Package, *servererrors.ServerError) { +func getPackage(catalogID string, name string) (*model.Package, *model.ServerResponse) { repo, err := getRepoClient(catalogID, name) if err != nil { return nil, err @@ -171,11 +153,11 @@ func getPackage(catalogID string, name string) (*model.Package, *servererrors.Se }, nil } -func (r RepositoryClient) listTags() ([]string, *servererrors.ServerError) { +func (r RepositoryClient) listTags() ([]string, *model.ServerResponse) { ctx := context.Background() var allTags []string var last string - var err *servererrors.ServerError + var err *model.ServerResponse for { er := r.Tags(ctx, last, func(tags []string) error { if len(tags) == 0 { @@ -191,9 +173,11 @@ func (r RepositoryClient) listTags() ([]string, *servererrors.ServerError) { if er != io.EOF { var httpErr *errcode.ErrorResponse if errors.As(er, &httpErr) { - err = servererrors.OfType(servererrors.Registry).GenericError(httpErr.StatusCode, httpErr.Error()) + err = model. + NewServerResponse(model.RegistryResponse).GenericError(httpErr.StatusCode, httpErr.Error()) } else { - err = servererrors.OfType(servererrors.Registry).GenericError(statusCode, er.Error()) + err = model. + NewServerResponse(model.RegistryResponse).GenericError(statusCode, er.Error()) } } break @@ -203,53 +187,84 @@ func (r RepositoryClient) listTags() ([]string, *servererrors.ServerError) { return allTags, err } -func (r RepositoryClient) fetchDefinition(version string) (map[string]interface{}, *servererrors.ServerError) { +func (r RepositoryClient) fetchDefinition(version string) (map[string]interface{}, *model.ServerResponse) { ctx := context.Background() // Pull to memory memStore := memory.New() desc, err := oras.Copy(ctx, r.Repository, version, memStore, version, oras.DefaultCopyOptions) if err != nil { log.Error("Failed to copy definition into the memstore: %v", err) - return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + return nil, model. + NewServerResponse(model.OkdpServerResponse).UnprocessableEntity(err.Error()) } // Decode manifest manifestReader, err := memStore.Fetch(ctx, desc) if err != nil { log.Error("Failed to fetch definition from the memstore: %v", err) - return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + return nil, model. + NewServerResponse(model.OkdpServerResponse).UnprocessableEntity(err.Error()) } defer manifestReader.Close() var manifest ocispec.Manifest if err := json.NewDecoder(manifestReader).Decode(&manifest); err != nil { log.Error("Failed to decode definition: %v", err) - return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + return nil, model. + NewServerResponse(model.OkdpServerResponse).UnprocessableEntity(err.Error()) } configReader, err := memStore.Fetch(ctx, manifest.Config) if err != nil { log.Error("Failed to fetch the definition content: %v", err) - return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + return nil, model. + NewServerResponse(model.OkdpServerResponse).UnprocessableEntity(err.Error()) } defer configReader.Close() var definition map[string]interface{} if err := json.NewDecoder(configReader).Decode(&definition); err != nil { log.Error("Failed to decode the definition content: %v", err) - return nil, servererrors.OfType(servererrors.OkdpServer).UnprocessableEntity(err.Error()) + return nil, model. + NewServerResponse(model.OkdpServerResponse).UnprocessableEntity(err.Error()) } return definition, nil } -func getRepoClient(catalogID string, packageName string) (*RepositoryClient, *servererrors.ServerError) { - instance, found := instance.clients[repoClientKey(catalogID, packageName)] +func getRepoClient(catalogID string, packageName string) (*RepositoryClient, *model.ServerResponse) { + instance, found := instance.clients[utils.MapKey(catalogID, packageName)] if !found { - return nil, CatalogPackageNotFoundError(catalogID, packageName) + return nil, model.CatalogPackageNotFoundError(catalogID, packageName) } return instance, nil } -func repoClientKey(catalogID string, packageName string) string { - return catalogID + packageName +func getOCIRepoCredentials(catalog *model.Catalog) (auth.CredentialFunc, error) { + + var empty auth.CredentialFunc = func(_ context.Context, _ string) (auth.Credential, error) { + return auth.EmptyCredential, nil + } + + if !catalog.IsAuthenticated() { + return empty, nil + } + + login := utils.ResolveEnv(*catalog.Credentials.RobotAccountName) + passwd := utils.ResolveEnv(*catalog.Credentials.RobotAccountToken) + dockerjson := utils.ResolveEnv(*catalog.Credentials.Dockerconfigjson) + + if login == "" && passwd == "" { + if dockerjson == "" { + return empty, nil + } + var err error + login, passwd, err = utils.ToLoginPassword(dockerjson) + if err != nil { + return nil, err + } + } + return auth.StaticCredential(catalog.RepoHost(), auth.Credential{ + Username: login, + Password: passwd, + }), nil } diff --git a/internal/integrations/registry/repo_catalog.go b/internal/integrations/oci/repo_catalog.go similarity index 73% rename from internal/integrations/registry/repo_catalog.go rename to internal/integrations/oci/repo_catalog.go index 13d19da..ff1138f 100644 --- a/internal/integrations/registry/repo_catalog.go +++ b/internal/integrations/oci/repo_catalog.go @@ -14,12 +14,11 @@ * limitations under the License. */ -package registry +package oci import ( - "github.com/okdp/okdp-server/internal/integrations/registry/client" + "github.com/okdp/okdp-server/internal/integrations/oci/client" "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" ) type RepoCatalog struct { @@ -36,18 +35,18 @@ func (r RepoCatalog) ListCatalogs() []*model.Catalog { return client.ListCatalogs() } -func (r RepoCatalog) GetCatalog(catalogID string) (*model.Catalog, *servererrors.ServerError) { +func (r RepoCatalog) GetCatalog(catalogID string) (*model.Catalog, *model.ServerResponse) { return client.GetCatalog(catalogID) } -func (r RepoCatalog) GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) { +func (r RepoCatalog) GetPackages(catalogID string) ([]*model.Package, *model.ServerResponse) { return client.GetPackages(catalogID) } -func (r RepoCatalog) GetPackageByName(catalogID string, name string) (*model.Package, *servererrors.ServerError) { - return client.GetPackageByName(catalogID, name) +func (r RepoCatalog) GetPackage(catalogID string, name string) (*model.Package, *model.ServerResponse) { + return client.GetPackage(catalogID, name) } -func (r RepoCatalog) GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *servererrors.ServerError) { +func (r RepoCatalog) GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *model.ServerResponse) { return client.GetPackageDefinition(catalogID, name, version) } diff --git a/internal/model/catalog.go b/internal/model/catalog.go index cfb9c0b..12a9d87 100644 --- a/internal/model/catalog.go +++ b/internal/model/catalog.go @@ -39,3 +39,13 @@ func (c Catalog) RepoHost() string { func (c Catalog) IsAuthenticated() bool { return c.Credentials != nil } + +func CatalogNotFoundError(catalogID string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("The catalog with id %s not found.", catalogID) +} + +func CatalogPackageNotFoundError(catalogID string, packageName string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("The package %s not found in the catalog ID %s.", packageName, catalogID) +} diff --git a/internal/model/server_response.go b/internal/model/server_response.go new file mode 100644 index 0000000..05faa10 --- /dev/null +++ b/internal/model/server_response.go @@ -0,0 +1,118 @@ +/* + * Copyright 2024 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package model + +import ( + "fmt" + "net/http" + + "github.com/okdp/okdp-server/api/openapi/v3/_api" +) + +type ServerResponse _api.ServerResponse +type ServerResponseType _api.ServerResponseType + +const ( + OkdpServerResponse ServerResponseType = "okdp_server" + RegistryResponse ServerResponseType = "registry" + GitRepoResponse ServerResponseType = "git_repo" + K8sClusterResponse ServerResponseType = "k8s_cluster" +) + +func NewServerResponse(errorType ServerResponseType) *ServerResponse { + return &ServerResponse{ + Type: _api.ServerResponseType(errorType), + } +} + +func (s *ServerResponse) NotFoundError(messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = http.StatusNotFound + return s +} + +func (s *ServerResponse) BadRequest(messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = http.StatusBadRequest + return s +} + +func (s *ServerResponse) Unauthorized(messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = http.StatusUnauthorized + return s +} + +func (s *ServerResponse) Forbidden(messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = http.StatusForbidden + return s +} + +func (s *ServerResponse) ConflictError(messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = http.StatusConflict + return s +} + +func (s *ServerResponse) UnprocessableEntity(messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = http.StatusUnprocessableEntity + return s +} + +func (s *ServerResponse) GenericError(statusCode int, messages ...interface{}) *ServerResponse { + s.Message = toError(messages...) + s.Status = statusCode + return s +} + +func (s *ServerResponse) Created(messages ...interface{}) *ServerResponse { + s.Message = toSuccess(messages...) + s.Status = http.StatusCreated + return s +} + +func (s *ServerResponse) Updated(messages ...interface{}) *ServerResponse { + s.Message = toSuccess(messages...) + s.Status = http.StatusOK + return s +} + +func (s *ServerResponse) Deleted(messages ...interface{}) *ServerResponse { + s.Message = toSuccess(messages...) + s.Status = http.StatusOK + return s +} + +func (s *ServerResponse) IsNotfound() bool { + return s.Status == http.StatusNotFound +} + +func toError(messages ...interface{}) string { + if len(messages) == 1 { + return fmt.Errorf("%+v", messages...).Error() + } + return fmt.Errorf(messages[0].(string), messages[1:]...).Error() +} + +func toSuccess(messages ...interface{}) string { + if len(messages) == 1 { + return messages[0].(string) + } + return fmt.Sprintf(messages[0].(string), messages[1:]...) +} diff --git a/internal/security/authc/auth.go b/internal/security/authc/auth.go index 6f334c4..8056a33 100644 --- a/internal/security/authc/auth.go +++ b/internal/security/authc/auth.go @@ -20,13 +20,13 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" + "github.com/okdp/okdp-server/internal/model" "github.com/okdp/okdp-server/internal/security/authc/provider/basic" "github.com/okdp/okdp-server/internal/security/authc/provider/bearer" "github.com/okdp/okdp-server/internal/security/authc/provider/oidc" - "github.com/okdp/okdp-server/internal/servererrors" ) func Authenticator(authNConfig config.AuthN) []gin.HandlerFunc { @@ -64,7 +64,8 @@ func ensureUserAuthenticated() gin.HandlerFunc { _, found := c.Get(constants.OAuth2UserInfo) if !found { log.Warn("Failed to authenticate user") - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Authentication failed")) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Authentication failed")) return } } diff --git a/internal/security/authc/provider/basic/basic_auth.go b/internal/security/authc/provider/basic/basic_auth.go index 9cd41da..14495c7 100644 --- a/internal/security/authc/provider/basic/basic_auth.go +++ b/internal/security/authc/provider/basic/basic_auth.go @@ -18,8 +18,8 @@ package basic import ( "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" "github.com/okdp/okdp-server/internal/security/authc/model" ) diff --git a/internal/security/authc/provider/basic/basic_auth_test.go b/internal/security/authc/provider/basic/basic_auth_test.go index d1b6d49..87e5567 100644 --- a/internal/security/authc/provider/basic/basic_auth_test.go +++ b/internal/security/authc/provider/basic/basic_auth_test.go @@ -23,8 +23,8 @@ import ( "testing" "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" "github.com/okdp/okdp-server/internal/security/authc/model" "github.com/stretchr/testify/assert" ) diff --git a/internal/security/authc/provider/bearer/bearer.go b/internal/security/authc/provider/bearer/bearer.go index d89adc3..6ff43f3 100644 --- a/internal/security/authc/provider/bearer/bearer.go +++ b/internal/security/authc/provider/bearer/bearer.go @@ -23,11 +23,11 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/security/authc/model" - "github.com/okdp/okdp-server/internal/servererrors" + "github.com/okdp/okdp-server/internal/model" + authc "github.com/okdp/okdp-server/internal/security/authc/model" "golang.org/x/net/context" ) @@ -65,7 +65,7 @@ func (p *Provider) Auth() []gin.HandlerFunc { func (p *Provider) authenticate() gin.HandlerFunc { return func(c *gin.Context) { var ( - userInfo model.UserInfo + userInfo authc.UserInfo ) authorization := c.Request.Header.Get("Authorization") @@ -73,14 +73,16 @@ func (p *Provider) authenticate() gin.HandlerFunc { err := p.verifyAccessToken(accessToken) if err != nil { log.Warn("Failed to verify access Token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to verify access Token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Failed to verify access Token: "+err.Error())) return } userInfo, err = p.getUserInfo(accessToken) if err != nil { log.Warn("Unable to get user roles/groups from access token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) return } log.Debug("Successfully authenticated user : %s", userInfo.AsJSONString()) @@ -101,7 +103,7 @@ func (p *Provider) verifyAccessToken(accessToken string) error { return nil } -func (p *Provider) getUserInfo(accessToken string) (model.UserInfo, error) { - token := &model.Token{AccessToken: accessToken} +func (p *Provider) getUserInfo(accessToken string) (authc.UserInfo, error) { + token := &authc.Token{AccessToken: accessToken} return token.GetUserInfo(rolesAttributePath, groupsAttributePath) } diff --git a/internal/security/authc/provider/oidc/oidc.go b/internal/security/authc/provider/oidc/oidc.go index 83b54d0..05cabc1 100644 --- a/internal/security/authc/provider/oidc/oidc.go +++ b/internal/security/authc/provider/oidc/oidc.go @@ -25,11 +25,11 @@ import ( "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/security/authc/model" - "github.com/okdp/okdp-server/internal/servererrors" + "github.com/okdp/okdp-server/internal/model" + authc "github.com/okdp/okdp-server/internal/security/authc/model" "github.com/okdp/okdp-server/internal/utils" "golang.org/x/net/context" "golang.org/x/oauth2" @@ -49,7 +49,7 @@ var ( ) func init() { - gob.Register(model.UserInfo{}) + gob.Register(authc.UserInfo{}) } func NewProvider(oidcConf config.OpenIDAuth) (*Provider, error) { @@ -81,12 +81,14 @@ func NewProvider(oidcConf config.OpenIDAuth) (*Provider, error) { func (p *Provider) AuthLogin(c *gin.Context) { state, err := utils.RandomString() if err != nil { - c.JSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 state")) + c.JSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 state")) return } nonce, err := utils.RandomString() if err != nil { - c.JSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 nonce")) + c.JSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Failed to to create OAuth2 nonce")) return } url := p.Config.AuthCodeURL(state, oidc.Nonce(nonce)) @@ -94,7 +96,8 @@ func (p *Provider) AuthLogin(c *gin.Context) { session.Set(constants.OAuth2State, state) session.Set(constants.OAuth2Nonce, nonce) if err = session.Save(); err != nil { - c.JSON(http.StatusInternalServerError, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusInternalServerError, "Failed to save user session in cookie")) + c.JSON(http.StatusInternalServerError, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusInternalServerError, "Failed to save user session in cookie")) } c.Redirect(http.StatusTemporaryRedirect, url) } @@ -111,12 +114,12 @@ func (p *Provider) authenticate() gin.HandlerFunc { var ( ok bool - userInfo model.UserInfo + userInfo authc.UserInfo ) session := sessions.Default(c) maybeUserInfo := session.Get(constants.OAuth2UserInfo) - if userInfo, ok = maybeUserInfo.(model.UserInfo); ok { + if userInfo, ok = maybeUserInfo.(authc.UserInfo); ok { c.Set(constants.OAuth2UserInfo, userInfo) log.Debug("The user (Email: %s, Subject: %s) was already authenticated", userInfo.Email, userInfo.Subject) c.Next() @@ -126,40 +129,46 @@ func (p *Provider) authenticate() gin.HandlerFunc { state := session.Get(constants.OAuth2State) if c.Query("state") != state { log.Warn("Invalid authentication OAuth2 state") - c.AbortWithStatusJSON(http.StatusBadRequest, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusBadRequest, "Invalid authentication OAuth2 'state': "+state.(string))) + c.AbortWithStatusJSON(http.StatusBadRequest, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusBadRequest, "Invalid authentication OAuth2 'state': "+state.(string))) return } // Exchange the authorization code for an access token token, err := p.Config.Exchange(p.Context, c.Query("code")) if err != nil { log.Warn("Failed to exchange the authorization code with an access token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to exchange authorization code with an access token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Failed to exchange authorization code with an access token: "+err.Error())) return } rawIDToken, ok := token.Extra("id_token").(string) if !ok { log.Warn("No id_token field found in the OAuth2 token") - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "No id_token field found in the OAuth2 token")) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "No id_token field found in the OAuth2 token")) return } idToken, err := p.Verify(p.Context, rawIDToken) if err != nil { log.Warn("Failed to verify the ID Token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Failed to verify the ID Token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Failed to verify the ID Token: "+err.Error())) return } nonce := session.Get(constants.OAuth2Nonce) if idToken.Nonce != nonce { log.Warn("Invalid authentication OAuth2 'nonce': %s", nonce.(string)) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Invalid authentication OAuth2 'nonce': "+nonce.(string))) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Invalid authentication OAuth2 'nonce': "+nonce.(string))) return } userInfo, err = p.getUserInfo(token.AccessToken) if err != nil { log.Warn("Unable to get user roles/groups from the access token: %w", err) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Unable to get user roles/groups from access token: "+err.Error())) return } // Retrieve the user information from the access token @@ -185,8 +194,8 @@ func (p *Provider) authenticate() gin.HandlerFunc { } } -func (p *Provider) getUserInfo(accessToken string) (model.UserInfo, error) { - token := &model.Token{AccessToken: accessToken} +func (p *Provider) getUserInfo(accessToken string) (authc.UserInfo, error) { + token := &authc.Token{AccessToken: accessToken} return token.GetUserInfo(rolesAttributePath, groupsAttributePath) } diff --git a/internal/security/authz/authz.go b/internal/security/authz/authz.go index 51d92d5..7094bb1 100644 --- a/internal/security/authz/authz.go +++ b/internal/security/authz/authz.go @@ -26,11 +26,11 @@ import ( "github.com/casbin/casbin/v2" "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" - "github.com/okdp/okdp-server/internal/security/authc/model" - "github.com/okdp/okdp-server/internal/servererrors" + "github.com/okdp/okdp-server/internal/model" + authc "github.com/okdp/okdp-server/internal/security/authc/model" "github.com/okdp/okdp-server/internal/utils" ) @@ -80,13 +80,14 @@ func (e *Enforcer) authorize() gin.HandlerFunc { userInfo, ok := c.Get(constants.OAuth2UserInfo) if !ok { log.Warn("Unable to authorize user, no user informtaion found in context") - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unable to authorize user, no user informtaion found in context")) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Unable to authorize user, no user informtaion found in context")) return } - email := userInfo.(*model.UserInfo).Email - sub := userInfo.(*model.UserInfo).Subject + email := userInfo.(*authc.UserInfo).Email + sub := userInfo.(*authc.UserInfo).Subject - rSub := userInfo.(*model.UserInfo).Roles + rSub := userInfo.(*authc.UserInfo).Roles rObj := c.Request.URL.Path rAct := c.Request.Method @@ -106,12 +107,14 @@ func (e *Enforcer) authorize() gin.HandlerFunc { if err != nil { log.Warn("Unable to authorize user (%s/%s): %s", email, sub, err.Error()) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, err.Error())) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, err.Error())) return } if !allowed { log.Warn("User (%s/%s) not allowed to execute the action", email, sub) - c.AbortWithStatusJSON(http.StatusUnauthorized, servererrors.OfType(servererrors.OkdpServer).GenericError(http.StatusUnauthorized, "Unauthorized action")) + c.AbortWithStatusJSON(http.StatusUnauthorized, model. + NewServerResponse(model.OkdpServerResponse).GenericError(http.StatusUnauthorized, "Unauthorized action")) return } diff --git a/internal/security/authz/authz_test.go b/internal/security/authz/authz_test.go index 4f76699..81c3f98 100644 --- a/internal/security/authz/authz_test.go +++ b/internal/security/authz/authz_test.go @@ -22,9 +22,9 @@ import ( "testing" "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" - log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/security/authc/model" "github.com/stretchr/testify/assert" ) diff --git a/internal/servererrors/server_errors.go b/internal/servererrors/server_errors.go deleted file mode 100644 index 2059d00..0000000 --- a/internal/servererrors/server_errors.go +++ /dev/null @@ -1,53 +0,0 @@ -package servererrors - -import ( - "fmt" - "net/http" - - "github.com/okdp/okdp-server/api/openapi/v3/_api" -) - -type ServerError _api.ServerError - -const ( - // Error types - OkdpServer = "okdp_server" - Registry = "registry" -) - -func OfType(errorType string) *ServerError { - return &ServerError{ - Type: errorType, - } -} - -func (s *ServerError) NotFoundError(messages ...interface{}) *ServerError { - s.Message = toError(messages...) - s.Status = http.StatusNotFound - return s -} - -func (s *ServerError) Forbidden(messages ...interface{}) *ServerError { - s.Message = toError(messages...) - s.Status = http.StatusForbidden - return s -} - -func (s *ServerError) UnprocessableEntity(messages ...interface{}) *ServerError { - s.Message = toError(messages...) - s.Status = http.StatusUnprocessableEntity - return s -} - -func (s *ServerError) GenericError(statusCode int, messages ...interface{}) *ServerError { - s.Message = toError(messages...) - s.Status = statusCode - return s -} - -func toError(messages ...interface{}) string { - if len(messages) == 1 { - return fmt.Errorf("%+v", messages...).Error() - } - return fmt.Errorf(messages[0].(string), messages[1:]...).Error() -} diff --git a/internal/services/catalog.go b/internal/services/catalog.go index 26c29e5..bc4f419 100644 --- a/internal/services/catalog.go +++ b/internal/services/catalog.go @@ -17,18 +17,17 @@ package services import ( - "github.com/okdp/okdp-server/internal/integrations/registry" + "github.com/okdp/okdp-server/internal/integrations/oci" "github.com/okdp/okdp-server/internal/model" - "github.com/okdp/okdp-server/internal/servererrors" ) type CatalogService struct { - catalog *registry.RepoCatalog + catalog *oci.RepoCatalog } func NewCatalogService() *CatalogService { return &CatalogService{ - catalog: registry.NewRepoCatalog(), + catalog: oci.NewRepoCatalog(), } } @@ -36,26 +35,18 @@ func (s CatalogService) ListCatalogs() []*model.Catalog { return s.catalog.ListCatalogs() } -func (s CatalogService) GetCatalog(catalogID string) (*model.Catalog, *servererrors.ServerError) { +func (s CatalogService) GetCatalog(catalogID string) (*model.Catalog, *model.ServerResponse) { return s.catalog.GetCatalog(catalogID) } -func (s CatalogService) GetPackages(catalogID string) ([]*model.Package, *servererrors.ServerError) { +func (s CatalogService) GetPackages(catalogID string) ([]*model.Package, *model.ServerResponse) { return s.catalog.GetPackages(catalogID) } -func (s CatalogService) GetPackageByName(catalogID string, name string) (*model.Package, *servererrors.ServerError) { - return s.catalog.GetPackageByName(catalogID, name) +func (s CatalogService) GetPackage(catalogID string, name string) (*model.Package, *model.ServerResponse) { + return s.catalog.GetPackage(catalogID, name) } -func (s CatalogService) GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *servererrors.ServerError) { +func (s CatalogService) GetPackageDefinition(catalogID string, name string, version string) (map[string]interface{}, *model.ServerResponse) { return s.catalog.GetPackageDefinition(catalogID, name, version) } - -// func (s CatalogService) GetDefinition(name string) (*model.Catalog, *errors.ServerError) { -// return s.catalog.GetDefinition(name) -// } - -// func (s CatalogService) GetTags(name string) (*model.Catalog, *errors.ServerError) { -// return s.catalog.GetTags(name) -// } diff --git a/internal/utils/auth_utils.go b/internal/utils/auth_utils.go index 6accc6e..659844a 100644 --- a/internal/utils/auth_utils.go +++ b/internal/utils/auth_utils.go @@ -19,7 +19,11 @@ package utils import ( "crypto/rand" "encoding/base64" + "encoding/json" + "errors" + "fmt" "io" + "strings" ) func RandomString() (string, error) { @@ -29,3 +33,50 @@ func RandomString() (string, error) { } return base64.RawURLEncoding.EncodeToString(b), nil } + +type dockerConfig struct { + Auths map[string]dockerAuthEntry `json:"auths"` +} + +type dockerAuthEntry struct { + Auth string `json:"auth"` // base64("username:password") +} + +// ToLoginPassword decodes a base64-encoded .dockerconfigjson value and extracts the first +// username and password found in the `auths` section. +// It returns the username, password, and an error if decoding or parsing fails. +func ToLoginPassword(encodedDockerJSON string) (string, string, error) { + jsonBytes, err := base64.StdEncoding.DecodeString(encodedDockerJSON) + if err != nil { + return "", "", fmt.Errorf("failed to base64-decode dockerjson: %w", err) + } + + var config dockerConfig + if err := json.Unmarshal(jsonBytes, &config); err != nil { + return "", "", fmt.Errorf("failed to unmarshal docker config json: %w", err) + } + + if len(config.Auths) == 0 { + return "", "", errors.New("no auth entries found in docker config") + } + + for registry, entry := range config.Auths { + if entry.Auth == "" { + continue + } + + decodedAuth, err := base64.StdEncoding.DecodeString(entry.Auth) + if err != nil { + return "", "", fmt.Errorf("failed to decode auth for registry '%s': %w", registry, err) + } + + parts := strings.SplitN(string(decodedAuth), ":", 2) + if len(parts) != 2 { + return "", "", fmt.Errorf("invalid auth format for registry '%s'", registry) + } + + return parts[0], parts[1], nil + } + + return "", "", errors.New("no valid auth credentials found") +} diff --git a/internal/utils/auth_utils_test.go b/internal/utils/auth_utils_test.go new file mode 100644 index 0000000..681b82a --- /dev/null +++ b/internal/utils/auth_utils_test.go @@ -0,0 +1,75 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "encoding/base64" + "testing" +) + +func TestToLoginPassword(t *testing.T) { + // Setup test values + username := "myuser" + password := "mypassword" + auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) + + dockerJSON := `{ + "auths": { + "https://index.docker.io/v1/": { + "auth": "` + auth + `" + } + } + }` + + encodedDockerJSON := base64.StdEncoding.EncodeToString([]byte(dockerJSON)) + + user, pass, err := ToLoginPassword(encodedDockerJSON) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if user != username { + t.Errorf("expected username '%s', got '%s'", username, user) + } + if pass != password { + t.Errorf("expected password '%s', got '%s'", password, pass) + } +} + +func TestToLoginPassword_InvalidBase64(t *testing.T) { + _, _, err := ToLoginPassword("not-base64!") + if err == nil { + t.Fatal("expected error for invalid base64, got none") + } +} + +func TestToLoginPassword_InvalidJSON(t *testing.T) { + encoded := base64.StdEncoding.EncodeToString([]byte("not json")) + _, _, err := ToLoginPassword(encoded) + if err == nil { + t.Fatal("expected error for invalid JSON, got none") + } +} + +func TestToLoginPassword_MissingAuth(t *testing.T) { + dockerJSON := `{"auths": {}}` + encoded := base64.StdEncoding.EncodeToString([]byte(dockerJSON)) + _, _, err := ToLoginPassword(encoded) + if err == nil { + t.Fatal("expected error for missing auths, got none") + } +} diff --git a/internal/utils/collection_utils.go b/internal/utils/collection_utils.go index a357212..3526f86 100644 --- a/internal/utils/collection_utils.go +++ b/internal/utils/collection_utils.go @@ -30,3 +30,45 @@ func ArrayNullToEmpty[T any](a []T) []T { } return []T{} } + +func MapKey(keys ...string) string { + var result string + for _, key := range keys { + result += key + } + return result +} + +// Filter filters a slice of objects based on a predicate function. +// It returns a new slice containing only the elements that satisfy the predicate. +func Filter[T any](objects []T, predicate func(T) bool) []*T { + var filtered []*T + for _, obj := range objects { + if predicate(obj) { + filtered = append(filtered, &obj) + } + } + return filtered +} + +// Filter filters a slice of objects based on a predicate function. +// It returns a new slice containing only the elements that satisfy the predicate. +func Filter2[T any](objects []*T, predicate func(T) bool) []*T { + var filtered []*T + for _, obj := range objects { + if predicate(*obj) { + filtered = append(filtered, obj) + } + } + return filtered +} + +// Contains checks if a given string is in the namespaces slice. +func Contains(values []string, value string) bool { + for _, ns := range values { + if ns == value { + return true + } + } + return false +} diff --git a/internal/utils/collection_utils_test.go b/internal/utils/collection_utils_test.go index 01be831..6a6222f 100644 --- a/internal/utils/collection_utils_test.go +++ b/internal/utils/collection_utils_test.go @@ -32,3 +32,82 @@ func TestMapfunction(t *testing.T) { // Then assert.Equal(t, []int{2, 4, 6}, result) } + +func TestFilter(t *testing.T) { + type MyObject struct { + Name string + Value int + } + // Test case 1: Filtering even numbers + objects := []MyObject{ + {Name: "Object 1", Value: 10}, + {Name: "Object 2", Value: 15}, + {Name: "Object 3", Value: 20}, + } + isEven := func(obj MyObject) bool { + return obj.Value%2 == 0 + } + + filtered := Filter(objects, isEven) + if len(filtered) != 2 { + t.Errorf("Expected 2 objects, but got %d", len(filtered)) + } + if filtered[0].Value != 10 || filtered[1].Value != 20 { + t.Errorf("Expected filtered objects to be [10, 20], but got %v", filtered) + } + + // Test case 2: Filtering objects with value greater than 15 + isGreaterThan15 := func(obj MyObject) bool { + return obj.Value > 15 + } + + filtered = Filter(objects, isGreaterThan15) + if len(filtered) != 1 { + t.Errorf("Expected 1 object, but got %d", len(filtered)) + } + if filtered[0].Value != 20 { + t.Errorf("Expected filtered object to be 20, but got %v", filtered[0]) + } + + // Test case 3: Empty list + filtered = Filter([]MyObject{}, isEven) + if len(filtered) != 0 { + t.Errorf("Expected 0 objects, but got %d", len(filtered)) + } +} + +func TestContains(t *testing.T) { + // Test case 1: Value exists in the slice + namespaces := []string{"flux-system", "kube-system", "default"} + value := "flux-system" + if !Contains(namespaces, "flux-system") { + t.Errorf("Expected '%s' to be in the namespaces slice", value) + } + + // Test case 2: Value does not exist in the slice + value = "dev-namespace" + if Contains(namespaces, value) { + t.Errorf("Expected '%s' to NOT be in the namespaces slice", value) + } + + // Test case 3: Empty slice + namespaces = []string{} + value = "release-system" + if Contains(namespaces, value) { + t.Errorf("Expected '%s' to NOT be in the namespaces slice", value) + } + + // Test case 4: Single element slice, value exists + namespaces = []string{"default"} + value = "default" + if !Contains(namespaces, value) { + t.Errorf("Expected '%s' to be in the namespaces slice", value) + } + + // Test case 5: Single element slice, value does not exist + namespaces = []string{"default"} + value = "dev1" + if Contains(namespaces, value) { + t.Errorf("Expected '%s' to NOT be in the namespaces slice", value) + } +} diff --git a/internal/utils/env_utils.go b/internal/utils/env_utils.go index 1c05eb2..055cd9d 100644 --- a/internal/utils/env_utils.go +++ b/internal/utils/env_utils.go @@ -21,11 +21,10 @@ import ( "strings" ) -// GetEnv reads an environment variable. If the value is a placeholder like $(VAR_NAME), +// ResolveEnv reads an environment variable. If the value is a placeholder like $(VAR_NAME), // it will replace it with the actual value from the environment variable. // If the value is not a placeholder, it returns the value as is. -func GetEnv(key string) string { - // Check if the key has the $(...) format +func ResolveEnv(key string) string { if strings.HasPrefix(key, "$(") && strings.HasSuffix(key, ")") { varName := strings.TrimPrefix(key, "$(") varName = strings.TrimSuffix(varName, ")") diff --git a/internal/utils/env_utils_test.go b/internal/utils/env_utils_test.go index e1d8005..f00a688 100644 --- a/internal/utils/env_utils_test.go +++ b/internal/utils/env_utils_test.go @@ -21,22 +21,22 @@ import ( "testing" ) -func TestGetEnv(t *testing.T) { +func TestResolveEnv(t *testing.T) { // Test the behavior when the environment variable is set os.Setenv("OCI_USERNAME", "myusername") defer os.Unsetenv("OCI_USERNAME") - if got := GetEnv("$(OCI_USERNAME)"); got != "myusername" { + if got := ResolveEnv("$(OCI_USERNAME)"); got != "myusername" { t.Errorf("expected 'myusername', got %s", got) } // Test when the environment variable does not exist - if got := GetEnv("$(NON_EXISTENT_VAR)"); got != "" { + if got := ResolveEnv("$(NON_EXISTENT_VAR)"); got != "" { t.Errorf("expected '', got %s", got) } // Test non-placeholder value - if got := GetEnv("JustSomeOtherValue"); got != "JustSomeOtherValue" { + if got := ResolveEnv("JustSomeOtherValue"); got != "JustSomeOtherValue" { t.Errorf("expected 'JustSomeOtherValue', got %s", got) } } diff --git a/internal/utils/file_utils.go b/internal/utils/file_utils.go new file mode 100644 index 0000000..7a73775 --- /dev/null +++ b/internal/utils/file_utils.go @@ -0,0 +1,42 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "path/filepath" + "strings" +) + +// IsYaml checks if the given filename has a .yaml or .yml extension (case-insensitive). +func IsYaml(filePath string) bool { + ext := strings.ToLower(filepath.Ext(filePath)) + return ext == ".yaml" || ext == ".yml" +} + +// PathOrFallback returns the given `path` if it contains a slash ("/"), +// indicating it is a likely full or relative path. +// Otherwise, it returns the provided `fallback` value. +// +// This is useful in cases where you want to prefer a user-supplied +// file or directory path, but fall back to a default if not provided. +func PathOrFallback(path string, fallback string) string { + if strings.Contains(path, "/") { + return path + } + return fallback + +} diff --git a/internal/utils/file_utils_test.go b/internal/utils/file_utils_test.go new file mode 100644 index 0000000..ace15cc --- /dev/null +++ b/internal/utils/file_utils_test.go @@ -0,0 +1,86 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import "testing" + +func TestIsYaml(t *testing.T) { + tests := []struct { + name string + filename string + expected bool + }{ + {"Valid .yaml file", "config.yaml", true}, + {"Valid .yml file", "config.yml", true}, + {"Uppercase .YAML", "CONFIG.YAML", true}, + {"Uppercase .YML", "CONFIG.YML", true}, + {"Not a YAML file (.json)", "data.json", false}, + {"No extension", "README", false}, + {"Empty string", "", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if result := IsYaml(tt.filename); result != tt.expected { + t.Errorf("IsYaml(%q) = %v; want %v", tt.filename, result, tt.expected) + } + }) + } +} + +func TestPathOrFallback(t *testing.T) { + tests := []struct { + name string + path string + fallback string + want string + }{ + { + name: "Path contains slash", + path: "./config/file.yaml", + fallback: "default.yaml", + want: "./config/file.yaml", + }, + { + name: "Path does not contain slash", + path: "file.yaml", + fallback: "default.yaml", + want: "default.yaml", + }, + { + name: "Empty path returns fallback", + path: "", + fallback: "default.yaml", + want: "default.yaml", + }, + { + name: "Path is slash only", + path: "/", + fallback: "default.yaml", + want: "/", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := PathOrFallback(tt.path, tt.fallback) + if got != tt.want { + t.Errorf("PathOrFallback() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/utils/hash_utils.go b/internal/utils/hash_utils.go new file mode 100644 index 0000000..fef7080 --- /dev/null +++ b/internal/utils/hash_utils.go @@ -0,0 +1,30 @@ +/* + * Copyright 2024 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "crypto/sha1" + "encoding/hex" + "strings" +) + +// FromString generates a short deterministic ID from a string +func FromString(input string) string { + normalized := strings.TrimSpace(input) + hash := sha1.Sum([]byte(normalized)) + return hex.EncodeToString(hash[:6]) // 6 bytes -> 12 hex chars +} diff --git a/internal/utils/hash_utils_tests.go b/internal/utils/hash_utils_tests.go new file mode 100644 index 0000000..3a2c552 --- /dev/null +++ b/internal/utils/hash_utils_tests.go @@ -0,0 +1,59 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "testing" +) + +func TestFromString(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "Basic Git URL", + input: "ssh://git@github.com/kubocd/kubocd-infra-ii", + expected: "ff7b5b726d45", + }, + { + name: "Leading and trailing spaces", + input: " ssh://git@github.com/kubocd/kubocd-infra-ii ", + expected: "ff7b5b726d45", + }, + { + name: "Empty string", + input: "", + expected: "da39a3ee5e6b", + }, + { + name: "Different strings produce different IDs", + input: "ssh://git@github.com/kubocd/another-repo", + expected: "c79dc88f5600", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := FromString(tt.input) + if got != tt.expected { + t.Errorf("FromString(%q) = %v; want %v", tt.input, got, tt.expected) + } + }) + } +} diff --git a/internal/utils/parameter_utils.go b/internal/utils/parameter_utils.go new file mode 100644 index 0000000..39b6a4a --- /dev/null +++ b/internal/utils/parameter_utils.go @@ -0,0 +1,39 @@ +/* + * Copyright 2024 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +func OrFalse(b *bool) bool { + if b != nil { + return *b + } + return false +} + +// DefaultIfEmpty returns `value` if it is not an empty string, +// otherwise it returns `defaultValue`. +// Useful for setting defaults in configurations. +// +// Example: +// +// DefaultIfEmpty("", "default") // returns "default" +// DefaultIfEmpty("foo", "default") // returns "foo" +func DefaultIfEmpty(value, defaultValue string) string { + if value != "" { + return value + } + return defaultValue +} diff --git a/internal/utils/parameter_utils_test.go b/internal/utils/parameter_utils_test.go new file mode 100644 index 0000000..52d28d3 --- /dev/null +++ b/internal/utils/parameter_utils_test.go @@ -0,0 +1,80 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "testing" +) + +func TestOrFalse(t *testing.T) { + trueVal := true + falseVal := false + + tests := []struct { + name string + input *bool + expected bool + }{ + { + name: "nil input returns false", + input: nil, + expected: false, + }, + { + name: "true input returns true", + input: &trueVal, + expected: true, + }, + { + name: "false input returns false", + input: &falseVal, + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := OrFalse(tt.input) + if result != tt.expected { + t.Errorf("OrFalse(%v) = %v; want %v", tt.input, result, tt.expected) + } + }) + } +} + +func TestDefaultIfEmpty(t *testing.T) { + tests := []struct { + name string + value string + defaultValue string + expected string + }{ + {"Empty value", "", "default", "default"}, + {"Non-empty value", "foo", "default", "foo"}, + {"Both empty", "", "", ""}, + {"Default value ignored", "bar", "ignored", "bar"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := DefaultIfEmpty(tt.value, tt.defaultValue) + if result != tt.expected { + t.Errorf("Expected %q, got %q", tt.expected, result) + } + }) + } +} From e6604eebae9fbc51929bd7cbe40da08f5aa4c279 Mon Sep 17 00:00:00 2001 From: iizitounene Date: Wed, 14 May 2025 17:39:28 +0200 Subject: [PATCH 05/14] feat: implement multi cluster interactions --- .local/application-local.yaml | 30 +- .local/authz-policy.csv | 4 + .local/keycloak.sh | 4 +- README.md | 2 +- .../v3/_api/clusters/clusters-server.go | 164 ++ api/openapi/v3/_api/spec.go | 118 +- api/openapi/v3/_api/types.go | 1630 ++++++++++++++++- api/openapi/v3/api.yaml | 58 +- api/openapi/v3/definition/Cluster.yaml | 71 + .../v3/paths/clusters/cluster-by-id.yaml | 28 + .../v3/paths/clusters/cluster-list.yaml | 23 + .../v3/paths/clusters/namespace-by-name.yaml | 34 + .../v3/paths/clusters/namespace-list.yaml | 29 + api/openapi/v3/paths/users/user-profile.yaml | 4 +- docker-compose.yml | 2 + go.mod | 173 +- go.sum | 415 +---- internal/config/config.go | 1 + internal/config/config_test.go | 25 + internal/config/testdata/application.yaml | 21 + internal/controllers/cluster_controller.go | 70 + internal/controllers/register.go | 8 +- internal/controllers/user_profile.go | 24 +- .../integrations/registry/client/error.go | 31 - internal/model/{git_commit.go => cluster.go} | 7 +- internal/server/server.go | 4 +- internal/services/cluster.go | 48 + 27 files changed, 2495 insertions(+), 533 deletions(-) create mode 100644 api/openapi/v3/_api/clusters/clusters-server.go create mode 100644 api/openapi/v3/definition/Cluster.yaml create mode 100644 api/openapi/v3/paths/clusters/cluster-by-id.yaml create mode 100644 api/openapi/v3/paths/clusters/cluster-list.yaml create mode 100644 api/openapi/v3/paths/clusters/namespace-by-name.yaml create mode 100644 api/openapi/v3/paths/clusters/namespace-list.yaml create mode 100644 internal/controllers/cluster_controller.go delete mode 100644 internal/integrations/registry/client/error.go rename internal/model/{git_commit.go => cluster.go} (77%) create mode 100644 internal/services/cluster.go diff --git a/.local/application-local.yaml b/.local/application-local.yaml index 03e17f9..34a0a40 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -92,6 +92,7 @@ catalog: #credentials: # robotAccountName: $(OCI_USERNAME) # robotAccountToken: $(OCI_PASSWORD) + # dockerconfigjson: $(DOCKER_CONFIG_JSON) packages: - name: redis - name: minio @@ -101,10 +102,6 @@ catalog: name: Auth catalog description: My Auth packages repoUrl: quay.io/kubocd/packages - ### public registry, no credentials needed - #credentials: - # robotAccountName: $(OCI_USERNAME) - # robotAccountToken: $(OCI_PASSWORD) packages: - name: openldap @@ -112,10 +109,6 @@ catalog: name: Infra catalog description: My Infra packages repoUrl: quay.io/kubocd/packages - ### public registry, no credentials needed - #credentials: - # robotAccountName: $(OCI_USERNAME) - # robotAccountToken: $(OCI_PASSWORD) packages: - name: podinfo - name: cert-manager @@ -126,11 +119,24 @@ catalog: name: Stack catalog description: My Stack packages repoUrl: quay.io/kubocd/packages - ### public registry, no credentials needed - #credentials: - # robotAccountName: $(OCI_USERNAME) - # robotAccountToken: $(OCI_PASSWORD) packages: - name: stack1 +clusters: + - id: kubo2 + env: dev + auth: + kubeconfig: + apiServer: https://host.docker.internal:56660 + path: /tmp/.kube/config + context: dev-context + insecureSkipTlsVerify: true + # certificate: + # apiServer: https://k8s-api-server-url:6443 + # clientKey: /path/to/client-key.pem + # clientCert: /path/to/client-cert.pem + # caCert: /path/to/ca-cert.pem + # bearer: + # apiServer: https://k8s-api-server-url:6443 + # bearerToken: $(BEARER_TOKEN) diff --git a/.local/authz-policy.csv b/.local/authz-policy.csv index 358e6bc..d93e87b 100644 --- a/.local/authz-policy.csv +++ b/.local/authz-policy.csv @@ -2,6 +2,10 @@ p, role:viewers, /api/v1/users/myprofile, * p, role:viewers, /api/v1/catalogs, * p, role:viewers, /api/v1/catalogs/*, * +p, role:viewers, /api/v1/clusters, * +p, role:viewers, /api/v1/clusters/*/gitrepos, * +p, role:viewers, /api/v1/clusters/*/gitrepos/*, * + g, role:admins, role:developers g, role:developers, role:viewers diff --git a/.local/keycloak.sh b/.local/keycloak.sh index 42265b2..ff3e327 100644 --- a/.local/keycloak.sh +++ b/.local/keycloak.sh @@ -43,8 +43,8 @@ echo "Creating users, roles and clients ..." -s 'webOrigins=["http://localhost:8090", "http://localhost:8092", "http://localhost:4200"]' # Update access token lifetime -echo "Update access token lifetime to 1H" -/opt/keycloak/bin/kcadm.sh update realms/master -s accessTokenLifespan=3600 +echo "Update access token lifetime to 8H" +/opt/keycloak/bin/kcadm.sh update realms/master -s accessTokenLifespan=28800 echo "Users, roles and clients created successfuly" exit 0 diff --git a/README.md b/README.md index 7b57b9e..ea3f648 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Manually add the following entry in /etc/hosts Start docker compose using your robot account token to access private registries: ```shell docker-compose rm -f -OCI_USERNAME=okdp+okdp_quay_robot OCI_PASSWORD=****** docker-compose up --build +docker-compose up --build ``` Open swagger UI at: http://localhost:8092/ diff --git a/api/openapi/v3/_api/clusters/clusters-server.go b/api/openapi/v3/_api/clusters/clusters-server.go new file mode 100644 index 0000000..fff3bad --- /dev/null +++ b/api/openapi/v3/_api/clusters/clusters-server.go @@ -0,0 +1,164 @@ +// Package _clusters provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. +package _clusters + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/oapi-codegen/runtime" +) + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // List all kubernetes clusters + // (GET /clusters) + ListClusters(c *gin.Context) + // Get a kubernetes cluster by id + // (GET /clusters/{clusterId}) + GetCluster(c *gin.Context, clusterId string) + // List all kubernetes namespaces + // (GET /clusters/{clusterId}/namespaces) + ListNamespaces(c *gin.Context, clusterId string) + // Get a kubernetes namespace by name + // (GET /clusters/{clusterId}/namespaces/{namespace}) + GetNamespace(c *gin.Context, clusterId string, namespace string) +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +type MiddlewareFunc func(c *gin.Context) + +// ListClusters operation middleware +func (siw *ServerInterfaceWrapper) ListClusters(c *gin.Context) { + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.ListClusters(c) +} + +// GetCluster operation middleware +func (siw *ServerInterfaceWrapper) GetCluster(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetCluster(c, clusterId) +} + +// ListNamespaces operation middleware +func (siw *ServerInterfaceWrapper) ListNamespaces(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.ListNamespaces(c, clusterId) +} + +// GetNamespace operation middleware +func (siw *ServerInterfaceWrapper) GetNamespace(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetNamespace(c, clusterId, namespace) +} + +// GinServerOptions provides options for the Gin server. +type GinServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router gin.IRouter, si ServerInterface) { + RegisterHandlersWithOptions(router, si, GinServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { + errorHandler := options.ErrorHandler + if errorHandler == nil { + errorHandler = func(c *gin.Context, err error, statusCode int) { + c.JSON(statusCode, gin.H{"msg": err.Error()}) + } + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + HandlerMiddlewares: options.Middlewares, + ErrorHandler: errorHandler, + } + + router.GET(options.BaseURL+"/clusters", wrapper.ListClusters) + router.GET(options.BaseURL+"/clusters/:clusterId", wrapper.GetCluster) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces", wrapper.ListNamespaces) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace", wrapper.GetNamespace) +} diff --git a/api/openapi/v3/_api/spec.go b/api/openapi/v3/_api/spec.go index 55a2d35..b094ac6 100644 --- a/api/openapi/v3/_api/spec.go +++ b/api/openapi/v3/_api/spec.go @@ -18,27 +18,103 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYXU8jNxf+K5bf96KVhpksvctVKaBVVJZGC/RmiyrHczLxMmNPbQ+QRvnvlT32fE9C", - "CtoC2hsU7OPz9Tzn2HM2mIosFxy4Vni6wYquICP2ZwxLxplmgv95SjRJRWJWcylykJqBlaESYuCakVT1", - "N6VYCH1CqSi4viQZmDW9zgFPsdKS8QRvg5bQtbgDPiC1DfyKWHwFqs25GBSVLDfuDeplcX85wI9HiTji", - "1hc8OzNyfMyxnNA7kpSRMA3ZQIAjZ01U8FfBJMR4+qWUuh0IwS0QKcnapgJycSNTo3EpZEY0nuJCMhzs", - "DMOe+nzRM8ti7KJrJ6u204ix516AH7O0jhFTx4CtTX1FjHmpYDw1LZjw9QqQ2UFiifQKkLPfi3Ab4HuQ", - "igmu+kpOUMqUNiq8DFoK2dFXIdZT3M76EFYN43vz4i128nIF8h7kuZRC9nOTgVIuaT3vlCa6aDrOuIYE", - "ZO35Prp57ZUud3BvKKrhcyecGwVyLsWSpQNQQ0ZYOhhMIkWRtwtoDxwBTkXChiuaj7eQFA60oorFvvag", - "Cleonfyao97NqsDKHFQRe5/25rxoJHa7NabgUYPkJD0TdID7v/16NkexoEUGXBNXz4XpGXilda6mUSTu", - "4jxkIrJNkC+FbdOCa0J1Ay3MYiZD9jfTouDA4ee7YiE0SUMmfFTOGhVZVnCm1zstdeucKcQUIujz+dU1", - "OpnPkIQlSOAUqmK12stCMQllFLiCRm5OckJXgI7DSc/yw8NDSOx2KGQSubMqupidnl9enR8dh5NwpbPU", - "Qs90WgVTmnNe5awudTzFH8JJODEnRA6c5AxP8U92yfRJvbJoRK4P2n8S0H2ELkxvImmKvOQfBiJTLxau", - "WexkTr0iwy6VC+O/0XY8mXjEgFv9JM9TRu3p6Ksqr7vymm5x/v8SlniK/xfVF3rkbvNo4Crvd8Ieiheu", - "zRqwqrjLxkCKVB/k5hO9u2r1oJ5HDj6oepQqsozI9VDeTd8jBqgvuFq6NWcqDKON+zWLt6N4fgSNiFeK", - "FmvE4gFEP4IH1LJFkgw0SGO8q8+JodmZuaW4vUL0qq65yiXcbDtaFhA00tm9Am6fyaJDydOHxsdlWo55", - "u5jV18qVAUwPY0vUfByOtwGx9C8SZax4g2MMmnulb5JChzYi/3R8QiPyiXlD5Ep34v8v2RZtDMK7e5WT", - "bdtDhMfVjtGxk4C/rC/LV81/wMJgM4w9cg+tAUNu59U1y4rg74DQT2PV82gdNT/5xptq66OPIJUDZUtG", - "vSM7mf27O/ud4d+I4RVar/vduIdTL8TraON+Pa2D1+Ht5PRZJfZ++Txqw3+9DZqpN79d5ZA4tliQdN4Y", - "kpRWOwPA8aKpkX8Tl0LcZODLFkpUh7S3XkpR9ENdAwGyCXvUAQJNf9xZRleloe8l9D5KyKl7C+Wzl7fj", - "VVUokCrK1nk9mx0tk2yNjDhyssPF8Gntp5HPBLE9IjaGD8jrTWsq2h6/WlW3T2DCp3a8r5oKHWwagFuE", - "DdrmjFVStqVyHhqRnEX3H7CpOXeiC/1NW293vNyeqyZMr4pFSEVmh7v2z1Fptp7AO5/6HaUx0nwJM/XI", - "8Xb7TwAAAP//8ILjn6ccAAA=", + "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", + "BJOH64f/DQAA///Dy+n9WY0AAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/openapi/v3/_api/types.go b/api/openapi/v3/_api/types.go index 82e4d43..1093b6b 100644 --- a/api/openapi/v3/_api/types.go +++ b/api/openapi/v3/_api/types.go @@ -3,9 +3,95 @@ // Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. package _api +import ( + "encoding/json" + "fmt" + + "github.com/oapi-codegen/runtime" +) + +// Defines values for ReleaseSpecPackageProvider. +const ( + ReleaseSpecPackageProviderAws ReleaseSpecPackageProvider = "aws" + ReleaseSpecPackageProviderAzure ReleaseSpecPackageProvider = "azure" + ReleaseSpecPackageProviderGcp ReleaseSpecPackageProvider = "gcp" + ReleaseSpecPackageProviderGeneric ReleaseSpecPackageProvider = "generic" +) + +// Defines values for ReleaseSpecPackageVerifyProvider. +const ( + ReleaseSpecPackageVerifyProviderCosign ReleaseSpecPackageVerifyProvider = "cosign" + ReleaseSpecPackageVerifyProviderNotation ReleaseSpecPackageVerifyProvider = "notation" +) + +// Defines values for ServerResponseType. +const ( + GitRepo ServerResponseType = "git_repo" + K8sCluster ServerResponseType = "k8s_cluster" + OkdpServer ServerResponseType = "okdp_server" + Registry ServerResponseType = "registry" +) + +// Defines values for CreateGitReleaseJSONBodySpecPackageProvider. +const ( + CreateGitReleaseJSONBodySpecPackageProviderAws CreateGitReleaseJSONBodySpecPackageProvider = "aws" + CreateGitReleaseJSONBodySpecPackageProviderAzure CreateGitReleaseJSONBodySpecPackageProvider = "azure" + CreateGitReleaseJSONBodySpecPackageProviderGcp CreateGitReleaseJSONBodySpecPackageProvider = "gcp" + CreateGitReleaseJSONBodySpecPackageProviderGeneric CreateGitReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for CreateGitReleaseJSONBodySpecPackageVerifyProvider. +const ( + CreateGitReleaseJSONBodySpecPackageVerifyProviderCosign CreateGitReleaseJSONBodySpecPackageVerifyProvider = "cosign" + CreateGitReleaseJSONBodySpecPackageVerifyProviderNotation CreateGitReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// Defines values for UpdateGitReleaseJSONBodySpecPackageProvider. +const ( + UpdateGitReleaseJSONBodySpecPackageProviderAws UpdateGitReleaseJSONBodySpecPackageProvider = "aws" + UpdateGitReleaseJSONBodySpecPackageProviderAzure UpdateGitReleaseJSONBodySpecPackageProvider = "azure" + UpdateGitReleaseJSONBodySpecPackageProviderGcp UpdateGitReleaseJSONBodySpecPackageProvider = "gcp" + UpdateGitReleaseJSONBodySpecPackageProviderGeneric UpdateGitReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for UpdateGitReleaseJSONBodySpecPackageVerifyProvider. +const ( + UpdateGitReleaseJSONBodySpecPackageVerifyProviderCosign UpdateGitReleaseJSONBodySpecPackageVerifyProvider = "cosign" + UpdateGitReleaseJSONBodySpecPackageVerifyProviderNotation UpdateGitReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// Defines values for CreateK8sReleaseJSONBodySpecPackageProvider. +const ( + CreateK8sReleaseJSONBodySpecPackageProviderAws CreateK8sReleaseJSONBodySpecPackageProvider = "aws" + CreateK8sReleaseJSONBodySpecPackageProviderAzure CreateK8sReleaseJSONBodySpecPackageProvider = "azure" + CreateK8sReleaseJSONBodySpecPackageProviderGcp CreateK8sReleaseJSONBodySpecPackageProvider = "gcp" + CreateK8sReleaseJSONBodySpecPackageProviderGeneric CreateK8sReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for CreateK8sReleaseJSONBodySpecPackageVerifyProvider. +const ( + CreateK8sReleaseJSONBodySpecPackageVerifyProviderCosign CreateK8sReleaseJSONBodySpecPackageVerifyProvider = "cosign" + CreateK8sReleaseJSONBodySpecPackageVerifyProviderNotation CreateK8sReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// Defines values for UpdateK8sReleaseJSONBodySpecPackageProvider. +const ( + Aws UpdateK8sReleaseJSONBodySpecPackageProvider = "aws" + Azure UpdateK8sReleaseJSONBodySpecPackageProvider = "azure" + Gcp UpdateK8sReleaseJSONBodySpecPackageProvider = "gcp" + Generic UpdateK8sReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for UpdateK8sReleaseJSONBodySpecPackageVerifyProvider. +const ( + Cosign UpdateK8sReleaseJSONBodySpecPackageVerifyProvider = "cosign" + Notation UpdateK8sReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + // Catalog defines model for Catalog. type Catalog struct { Credentials *struct { + Dockerconfigjson *string `json:"dockerconfigjson,omitempty"` RobotAccountName *string `json:"robotAccountName,omitempty"` RobotAccountToken *string `json:"robotAccountToken,omitempty"` } `json:"credentials,omitempty"` @@ -18,6 +104,43 @@ type Catalog struct { RepoURL string `json:"repoUrl"` } +// Cluster defines model for Cluster. +type Cluster struct { + Auth *Cluster_Auth `json:"auth,omitempty"` + Env string `json:"env"` + ID string `json:"id"` +} + +// ClusterAuth0 defines model for . +type ClusterAuth0 = interface{} + +// ClusterAuth1 defines model for . +type ClusterAuth1 = interface{} + +// ClusterAuth2 defines model for . +type ClusterAuth2 = interface{} + +// Cluster_Auth defines model for Cluster.Auth. +type Cluster_Auth struct { + Bearer *struct { + APIServer string `json:"apiServer"` + BearerToken string `json:"bearerToken"` + } `json:"bearer,omitempty"` + Certificate *struct { + APIServer string `json:"apiServer"` + CACert string `json:"caCert"` + ClientCert string `json:"clientCert"` + ClientKey string `json:"clientKey"` + } `json:"certificate,omitempty"` + Kubeconfig *struct { + APIServer string `json:"apiServer"` + Context string `json:"context"` + InsecureSkipTlsVerify bool `json:"insecureSkipTlsVerify"` + Path string `json:"path"` + } `json:"kubeconfig,omitempty"` + union json.RawMessage +} + // GitCommit defines model for GitCommit. type GitCommit struct { // Commit The hash of the commit @@ -39,6 +162,18 @@ type GitCommit struct { TargetPath *string `json:"targetPath,omitempty"` } +// GitRepository defines model for GitRepository. +type GitRepository struct { + Credentials struct { + SecretRef string `json:"secretRef"` + } `json:"credentials"` + Name string `json:"name"` + Namespace string `json:"namespace"` + Path string `json:"path"` + Ref string `json:"ref"` + RepoURL string `json:"repoUrl"` +} + // Package defines model for Package. type Package struct { // Name The name of the package @@ -48,13 +183,338 @@ type Package struct { Versions []string `json:"versions"` } -// ServerError defines model for ServerError. -type ServerError struct { +// Release Release is the Schema for the releases API. +type Release struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *ReleaseSpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider ReleaseSpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// ReleaseSpecPackageProvider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator +// All following fields will be replicated in this object +// The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. +// When not specified, defaults to 'generic'. +// -kubebuilder:default:=generic +type ReleaseSpecPackageProvider string + +// ReleaseSpecPackageVerifyProvider Provider specifies the technology used to sign the OCI Artifact. +type ReleaseSpecPackageVerifyProvider string + +// ReleaseInfo defines model for ReleaseInfo. +type ReleaseInfo struct { + Description *string `json:"description,omitempty"` + Git struct { + Path string `json:"path"` + URL string `json:"url"` + } `json:"git"` + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + Package struct { + Repository string `json:"repository"` + Tag string `json:"tag"` + } `json:"package"` +} + +// ReleaseStatus Release is the Schema for the releases API. +type ReleaseStatus struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` +} + +// ServerResponse defines model for ServerResponse. +type ServerResponse struct { + // Message The response message from the server Message string `json:"message"` - Status int `json:"status"` - Type string `json:"type"` + + // Status The HTTP status code + Status int `json:"status"` + + // Type The type of the server response + Type ServerResponseType `json:"type"` } +// ServerResponseType The type of the server response +type ServerResponseType string + // UserProfile defines model for UserProfile. type UserProfile struct { Email string `json:"email"` @@ -64,3 +524,1165 @@ type UserProfile struct { Roles []string `json:"roles"` Subject string `json:"sub"` } + +// CreateGitReleaseJSONBody defines parameters for CreateGitRelease. +type CreateGitReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *CreateGitReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider CreateGitReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// CreateGitReleaseJSONBodySpecPackageProvider defines parameters for CreateGitRelease. +type CreateGitReleaseJSONBodySpecPackageProvider string + +// CreateGitReleaseJSONBodySpecPackageVerifyProvider defines parameters for CreateGitRelease. +type CreateGitReleaseJSONBodySpecPackageVerifyProvider string + +// UpdateGitReleaseJSONBody defines parameters for UpdateGitRelease. +type UpdateGitReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *UpdateGitReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider UpdateGitReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// UpdateGitReleaseJSONBodySpecPackageProvider defines parameters for UpdateGitRelease. +type UpdateGitReleaseJSONBodySpecPackageProvider string + +// UpdateGitReleaseJSONBodySpecPackageVerifyProvider defines parameters for UpdateGitRelease. +type UpdateGitReleaseJSONBodySpecPackageVerifyProvider string + +// CreateK8sReleaseJSONBody defines parameters for CreateK8sRelease. +type CreateK8sReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *CreateK8sReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider CreateK8sReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// CreateK8sReleaseParams defines parameters for CreateK8sRelease. +type CreateK8sReleaseParams struct { + // DryRun If true, performs a server-side dry run without persisting the resource + DryRun *bool `form:"dryRun,omitempty" json:"dryRun,omitempty"` +} + +// CreateK8sReleaseJSONBodySpecPackageProvider defines parameters for CreateK8sRelease. +type CreateK8sReleaseJSONBodySpecPackageProvider string + +// CreateK8sReleaseJSONBodySpecPackageVerifyProvider defines parameters for CreateK8sRelease. +type CreateK8sReleaseJSONBodySpecPackageVerifyProvider string + +// UpdateK8sReleaseJSONBody defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *UpdateK8sReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider UpdateK8sReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// UpdateK8sReleaseParams defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseParams struct { + // DryRun If true, performs a server-side dry run without persisting the resource + DryRun *bool `form:"dryRun,omitempty" json:"dryRun,omitempty"` +} + +// UpdateK8sReleaseJSONBodySpecPackageProvider defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseJSONBodySpecPackageProvider string + +// UpdateK8sReleaseJSONBodySpecPackageVerifyProvider defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseJSONBodySpecPackageVerifyProvider string + +// CreateGitReleaseJSONRequestBody defines body for CreateGitRelease for application/json ContentType. +type CreateGitReleaseJSONRequestBody CreateGitReleaseJSONBody + +// UpdateGitReleaseJSONRequestBody defines body for UpdateGitRelease for application/json ContentType. +type UpdateGitReleaseJSONRequestBody UpdateGitReleaseJSONBody + +// CreateK8sReleaseJSONRequestBody defines body for CreateK8sRelease for application/json ContentType. +type CreateK8sReleaseJSONRequestBody CreateK8sReleaseJSONBody + +// UpdateK8sReleaseJSONRequestBody defines body for UpdateK8sRelease for application/json ContentType. +type UpdateK8sReleaseJSONRequestBody UpdateK8sReleaseJSONBody + +// AsClusterAuth0 returns the union data inside the Cluster_Auth as a ClusterAuth0 +func (t Cluster_Auth) AsClusterAuth0() (ClusterAuth0, error) { + var body ClusterAuth0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromClusterAuth0 overwrites any union data inside the Cluster_Auth as the provided ClusterAuth0 +func (t *Cluster_Auth) FromClusterAuth0(v ClusterAuth0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeClusterAuth0 performs a merge with any union data inside the Cluster_Auth, using the provided ClusterAuth0 +func (t *Cluster_Auth) MergeClusterAuth0(v ClusterAuth0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsClusterAuth1 returns the union data inside the Cluster_Auth as a ClusterAuth1 +func (t Cluster_Auth) AsClusterAuth1() (ClusterAuth1, error) { + var body ClusterAuth1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromClusterAuth1 overwrites any union data inside the Cluster_Auth as the provided ClusterAuth1 +func (t *Cluster_Auth) FromClusterAuth1(v ClusterAuth1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeClusterAuth1 performs a merge with any union data inside the Cluster_Auth, using the provided ClusterAuth1 +func (t *Cluster_Auth) MergeClusterAuth1(v ClusterAuth1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsClusterAuth2 returns the union data inside the Cluster_Auth as a ClusterAuth2 +func (t Cluster_Auth) AsClusterAuth2() (ClusterAuth2, error) { + var body ClusterAuth2 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromClusterAuth2 overwrites any union data inside the Cluster_Auth as the provided ClusterAuth2 +func (t *Cluster_Auth) FromClusterAuth2(v ClusterAuth2) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeClusterAuth2 performs a merge with any union data inside the Cluster_Auth, using the provided ClusterAuth2 +func (t *Cluster_Auth) MergeClusterAuth2(v ClusterAuth2) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Cluster_Auth) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + if err != nil { + return nil, err + } + object := make(map[string]json.RawMessage) + if t.union != nil { + err = json.Unmarshal(b, &object) + if err != nil { + return nil, err + } + } + + if t.Bearer != nil { + object["bearer"], err = json.Marshal(t.Bearer) + if err != nil { + return nil, fmt.Errorf("error marshaling 'bearer': %w", err) + } + } + + if t.Certificate != nil { + object["certificate"], err = json.Marshal(t.Certificate) + if err != nil { + return nil, fmt.Errorf("error marshaling 'certificate': %w", err) + } + } + + if t.Kubeconfig != nil { + object["kubeconfig"], err = json.Marshal(t.Kubeconfig) + if err != nil { + return nil, fmt.Errorf("error marshaling 'kubeconfig': %w", err) + } + } + b, err = json.Marshal(object) + return b, err +} + +func (t *Cluster_Auth) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + if err != nil { + return err + } + object := make(map[string]json.RawMessage) + err = json.Unmarshal(b, &object) + if err != nil { + return err + } + + if raw, found := object["bearer"]; found { + err = json.Unmarshal(raw, &t.Bearer) + if err != nil { + return fmt.Errorf("error reading 'bearer': %w", err) + } + } + + if raw, found := object["certificate"]; found { + err = json.Unmarshal(raw, &t.Certificate) + if err != nil { + return fmt.Errorf("error reading 'certificate': %w", err) + } + } + + if raw, found := object["kubeconfig"]; found { + err = json.Unmarshal(raw, &t.Kubeconfig) + if err != nil { + return fmt.Errorf("error reading 'kubeconfig': %w", err) + } + } + + return err +} diff --git a/api/openapi/v3/api.yaml b/api/openapi/v3/api.yaml index 6e73e83..cce9a8b 100644 --- a/api/openapi/v3/api.yaml +++ b/api/openapi/v3/api.yaml @@ -26,11 +26,24 @@ tags: description: Catalogs externalDocs: url: https://github.com/okdp/okdp-server - + - name: clusters + description: Kubernetes Clusters + externalDocs: + url: https://github.com/okdp/okdp-server + - name: repositories + description: KuboCD Git Releases + externalDocs: + url: https://github.com/okdp/okdp-server + - name: k8s + description: KuboCD K8S Releases + externalDocs: + url: https://github.com/okdp/okdp-server + paths: ### Users /users/myprofile: $ref: ./paths/users/user-profile.yaml + ### Registry Catalogs /catalogs: $ref: ./paths/catalogs/catalog-list.yaml @@ -46,6 +59,34 @@ paths: $ref: ./paths/catalogs/package-definition.yaml /catalogs/{catalogId}/packages/{name}/versions/{version}/schema: $ref: ./paths/catalogs/package-schema.yaml + + ### Clusters + /clusters: + $ref: ./paths/clusters/cluster-list.yaml + /clusters/{clusterId}: + $ref: ./paths/clusters/cluster-by-id.yaml + /clusters/{clusterId}/namespaces: + $ref: ./paths/clusters/namespace-list.yaml + /clusters/{clusterId}/namespaces/{namespace}: + $ref: ./paths/clusters/namespace-by-name.yaml + + ### Git repositories KuboCD releases + /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations: + $ref: ./paths/repositories/repo-list.yaml + /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}: + $ref: ./paths/repositories/repo-by-name.yaml + /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases: + $ref: ./paths/repositories/releases.yaml + /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases/{releaseName}: + $ref: ./paths/repositories/release-by-name.yaml + + ### k8s + /clusters/{clusterId}/namespaces/{namespace}/releases: + $ref: ./paths/k8s/releases.yaml + /clusters/{clusterId}/namespaces/{namespace}/releases/{releaseName}: + $ref: ./paths/k8s/release-by-name.yaml + /clusters/{clusterId}/namespaces/{namespace}/releases/{releaseName}/status: + $ref: ./paths/k8s/release-status.yaml components: schemas: @@ -53,9 +94,20 @@ components: $ref: './definition/UserProfile.yaml' Catalog: $ref: './definition/Catalog.yaml' + Cluster: + $ref: './definition/Cluster.yaml' Package: $ref: './definition/Package.yaml' + Release: + $ref: './definition/Release.yaml' + ReleaseInfo: + $ref: './definition/ReleaseInfo.yaml' + ReleaseStatus: + $ref: './definition/ReleaseStatus.yaml' + GitRepository: + $ref: './definition/GitRepository.yaml' GitCommit: $ref: './definition/GitCommit.yaml' - ServerError: - $ref: './definition/ServerError.yaml' \ No newline at end of file + ServerResponse: + $ref: './definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/definition/Cluster.yaml b/api/openapi/v3/definition/Cluster.yaml new file mode 100644 index 0000000..dca27c0 --- /dev/null +++ b/api/openapi/v3/definition/Cluster.yaml @@ -0,0 +1,71 @@ +type: object +xml: + name: Cluster +required: + - id + - env + - k8s +properties: + id: + type: string + x-go-name: ID + env: + type: string + auth: + type: object + oneOf: + - required: [kubeconfig] + - required: [certificate] + - required: [bearer] + properties: + kubeconfig: + type: object + required: + - apiServer + - path + - context + - insecureSkipTlsVerify + properties: + apiServer: + type: string + format: uri + x-go-name: APIServer + path: + type: string + context: + type: string + insecureSkipTlsVerify: + type: boolean + certificate: + type: object + required: + - apiServer + - clientKey + - clientCert + - caCert + properties: + apiServer: + type: string + format: uri + x-go-name: APIServer + clientKey: + type: string + clientCert: + type: string + caCert: + type: string + x-go-name: CACert + bearer: + type: object + required: + - apiServer + - bearerToken + properties: + apiServer: + type: string + format: uri + x-go-name: APIServer + bearerToken: + type: string + + diff --git a/api/openapi/v3/paths/clusters/cluster-by-id.yaml b/api/openapi/v3/paths/clusters/cluster-by-id.yaml new file mode 100644 index 0000000..78a1fc7 --- /dev/null +++ b/api/openapi/v3/paths/clusters/cluster-by-id.yaml @@ -0,0 +1,28 @@ +get: + summary: Get a kubernetes cluster by id + description: | + Get a kubernetes cluster by id + tags: + - clusters + operationId: GetCluster + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Cluster ID + responses: + '200': + description: Cluster information + content: + application/json: + schema: + $ref: '../../definition/Cluster.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/paths/clusters/cluster-list.yaml b/api/openapi/v3/paths/clusters/cluster-list.yaml new file mode 100644 index 0000000..e803e7d --- /dev/null +++ b/api/openapi/v3/paths/clusters/cluster-list.yaml @@ -0,0 +1,23 @@ +get: + summary: List all kubernetes clusters + description: | + List all kubernetes clusters + tags: + - clusters + operationId: ListClusters + responses: + '200': + description: List of the clusters + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/Cluster.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/paths/clusters/namespace-by-name.yaml b/api/openapi/v3/paths/clusters/namespace-by-name.yaml new file mode 100644 index 0000000..37d4b61 --- /dev/null +++ b/api/openapi/v3/paths/clusters/namespace-by-name.yaml @@ -0,0 +1,34 @@ +get: + summary: Get a kubernetes namespace by name + description: | + Get a kubernetes namespace by name + tags: + - clusters + operationId: GetNamespace + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + responses: + '200': + description: Namespace information + content: + application/json: + schema: + type: string + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/paths/clusters/namespace-list.yaml b/api/openapi/v3/paths/clusters/namespace-list.yaml new file mode 100644 index 0000000..1445423 --- /dev/null +++ b/api/openapi/v3/paths/clusters/namespace-list.yaml @@ -0,0 +1,29 @@ +get: + summary: List all kubernetes namespaces + description: | + List all kubernetes namespaces + tags: + - clusters + operationId: ListNamespaces + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Cluster ID + responses: + '200': + description: List of the namespaces + content: + application/json: + schema: + type: array + items: + type: string + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' \ No newline at end of file diff --git a/api/openapi/v3/paths/users/user-profile.yaml b/api/openapi/v3/paths/users/user-profile.yaml index e8060f8..a970e26 100644 --- a/api/openapi/v3/paths/users/user-profile.yaml +++ b/api/openapi/v3/paths/users/user-profile.yaml @@ -4,7 +4,7 @@ get: Get my user profile tags: - users - operationId: getMyProfile + operationId: GetMyProfile responses: '200': description: My user profile @@ -21,5 +21,5 @@ get: content: application/json: schema: - $ref: '../../definition/ServerError.yaml' + $ref: '../../definition/ServerResponse.yaml' diff --git a/docker-compose.yml b/docker-compose.yml index 2101c76..1004f73 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,10 +28,12 @@ services: - .local:/workspace/.local - .go-cache/go-build:/go-build - .go-cache/go-mod:/go/pkg + - ~/.kube/config:/tmp/.kube/config:ro working_dir: /workspace environment: - OCI_USERNAME=${OCI_USERNAME} - OCI_PASSWORD=${OCI_PASSWORD} + - DOCKER_CONFIG_JSON=${DOCKER_CONFIG_JSON} - GOCACHE=/go-build - GOMODCACHE=/go/pkg depends_on: diff --git a/go.mod b/go.mod index 0c7ea6a..a60d686 100644 --- a/go.mod +++ b/go.mod @@ -4,172 +4,111 @@ go 1.23.0 toolchain go1.23.6 +require kubocd v0.2.1 + +replace kubocd => github.com/kubocd/kubocd v0.2.1 + require ( + github.com/Masterminds/semver/v3 v3.3.0 github.com/casbin/casbin/v2 v2.103.0 github.com/coreos/go-oidc/v3 v3.12.0 + github.com/fluxcd/kustomize-controller/api v1.5.1 + github.com/fluxcd/source-controller/api v1.5.0 github.com/fsnotify/fsnotify v1.8.0 github.com/getkin/kin-openapi v0.129.0 github.com/gin-contrib/cors v1.7.3 github.com/gin-contrib/sessions v1.0.2 github.com/gin-contrib/zap v1.1.4 github.com/gin-gonic/gin v1.10.0 - github.com/go-resty/resty/v2 v2.16.5 - github.com/goccy/go-yaml v1.15.23 + github.com/go-git/go-billy/v5 v5.6.2 + github.com/go-git/go-git/v5 v5.16.0 github.com/oapi-codegen/runtime v1.1.1 + github.com/opencontainers/image-spec v1.1.0 + github.com/skeema/knownhosts v1.3.1 github.com/spf13/cobra v1.9.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 github.com/tidwall/gjson v1.18.0 go.uber.org/zap v1.27.0 - golang.org/x/net v0.37.0 + golang.org/x/exp v0.0.0-20250215185904-eff6e970281f + golang.org/x/net v0.39.0 golang.org/x/oauth2 v0.26.0 + k8s.io/api v0.32.2 + k8s.io/apimachinery v0.32.2 + k8s.io/client-go v0.32.2 + oras.land/oras-go/v2 v2.5.0 + sigs.k8s.io/controller-runtime v0.20.2 + sigs.k8s.io/yaml v1.4.0 ) require ( - cloud.google.com/go/compute/metadata v0.6.0 // indirect dario.cat/mergo v1.0.1 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/BurntSushi/toml v1.4.0 // indirect - github.com/MakeNowJust/heredoc v1.0.0 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect - github.com/Masterminds/sprig/v3 v3.3.0 // indirect - github.com/Masterminds/squirrel v1.5.4 // indirect - github.com/Masterminds/vcs v1.13.3 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect - github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect - github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd // indirect - github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect - github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect github.com/bytedance/sonic v1.12.8 // indirect github.com/bytedance/sonic/loader v0.2.3 // indirect github.com/casbin/govaluate v1.3.0 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/cloudflare/circl v1.6.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect - github.com/containerd/containerd v1.7.24 // indirect - github.com/containerd/errdefs v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect - github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v27.5.0+incompatible // indirect - github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.5.0+incompatible // indirect - github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect - github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch v5.9.0+incompatible // indirect - github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect - github.com/fatih/color v1.15.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/emicklei/go-restful/v3 v3.11.1 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fluxcd/pkg/apis/acl v0.6.0 // indirect + github.com/fluxcd/pkg/apis/kustomize v1.9.0 // indirect github.com/fluxcd/pkg/apis/meta v1.10.0 // indirect - github.com/fluxcd/source-controller/api v1.5.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gin-contrib/sse v1.0.0 // indirect - github.com/go-errors/errors v1.4.2 // indirect - github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.25.0 // indirect - github.com/gobwas/glob v0.2.3 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/gomodule/redigo v1.9.2 // indirect - github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-containerregistry v0.20.3 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/context v1.1.2 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.4.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/gosuri/uitable v0.0.4 // indirect - github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/huandu/xstrings v1.5.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jmoiron/sqlx v1.4.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.11 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect - github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect - github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lib/pq v1.10.9 // indirect - github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/magiconair/properties v1.8.9 // indirect github.com/mailru/easyjson v0.9.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/locker v1.0.1 // indirect - github.com/moby/spdystream v0.5.0 // indirect - github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect - github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 // indirect github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect - github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/rubenv/sql-migrate v1.7.1 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/shopspring/decimal v1.4.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect @@ -179,55 +118,25 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect - github.com/vbatts/tar-split v0.11.6 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.2.0 // indirect - github.com/xlab/treeprint v1.2.0 // indirect - github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect - github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect - github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect - go.opentelemetry.io/otel v1.33.0 // indirect - go.opentelemetry.io/otel/metric v1.33.0 // indirect - go.opentelemetry.io/otel/trace v1.33.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.14.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/sync v0.13.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/term v0.31.0 // indirect + golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.8.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect - google.golang.org/grpc v1.67.3 // indirect google.golang.org/protobuf v1.36.5 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - helm.sh/helm/v3 v3.17.2 // indirect - k8s.io/api v0.32.2 // indirect k8s.io/apiextensions-apiserver v0.32.2 // indirect - k8s.io/apimachinery v0.32.2 // indirect - k8s.io/apiserver v0.32.2 // indirect - k8s.io/cli-runtime v0.32.2 // indirect - k8s.io/client-go v0.32.2 // indirect - k8s.io/component-base v0.32.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - k8s.io/kubectl v0.32.2 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - oras.land/oras-go v1.2.5 // indirect - oras.land/oras-go/v2 v2.5.0 // indirect - sigs.k8s.io/controller-runtime v0.20.1 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/kustomize/api v0.18.0 // indirect - sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 6bc2662..438f198 100644 --- a/go.sum +++ b/go.sum @@ -1,57 +1,23 @@ -cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= -github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= -github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= -github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Masterminds/vcs v1.13.3 h1:IIA2aBdXvfbIM+yl/eTnL4hb1XwdpvuQLglAix1gweE= -github.com/Masterminds/vcs v1.13.3/go.mod h1:TiE7xuEjl1N4j016moRd6vezp6e6Lz23gypeXfzXeW8= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs= github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -61,68 +27,34 @@ github.com/casbin/casbin/v2 v2.103.0 h1:dHElatNXNrr8XcseUov0ZSiWjauwmZZE6YMV3eU1 github.com/casbin/casbin/v2 v2.103.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco= github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= +github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= -github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= -github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= -github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= -github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= -github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= -github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= -github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= -github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U= -github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= -github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= -github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= -github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= +github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= +github.com/emicklei/go-restful/v3 v3.11.1 h1:S+9bSbua1z3FgCnV0KKOSSZ3mDthb5NyEPL5gEpCvyk= +github.com/emicklei/go-restful/v3 v3.11.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= +github.com/fluxcd/kustomize-controller/api v1.5.1 h1:SLVMIk/3E/GkK610S85zDBfX/TQhpE2ym+516ONXtU4= +github.com/fluxcd/kustomize-controller/api v1.5.1/go.mod h1:SnQ5blin2e25GOCvd9JqYezYhqcM7beyK1aLq9Iw0So= github.com/fluxcd/pkg/apis/acl v0.6.0 h1:rllf5uQLzTow81ZCslkQ6LPpDNqVQr6/fWaNksdUEtc= github.com/fluxcd/pkg/apis/acl v0.6.0/go.mod h1:IVDZx3MAoDWjlLrJHMF9Z27huFuXAEQlnbWw0M6EcTs= +github.com/fluxcd/pkg/apis/kustomize v1.9.0 h1:SJpT1CK58AnTvCpDKeGfMNA0Xud/4VReZNvPe8XkTxo= +github.com/fluxcd/pkg/apis/kustomize v1.9.0/go.mod h1:AZl2GU03oPVue6SUivdiIYd/3mvF94j7t1G2JO26d4s= github.com/fluxcd/pkg/apis/meta v1.10.0 h1:rqbAuyl5ug7A5jjRf/rNwBXmNl6tJ9wG2iIsriwnQUk= github.com/fluxcd/pkg/apis/meta v1.10.0/go.mod h1:n7NstXHDaleAUMajcXTVkhz0MYkvEXy1C/eLI/t1xoI= github.com/fluxcd/source-controller/api v1.5.0 h1:caSR+u/r2Vh0jq/0pNR0r1zLxyvgatWuGSV2mxgTB/I= @@ -147,26 +79,26 @@ github.com/gin-contrib/zap v1.1.4 h1:xvxTybg6XBdNtcQLH3Tf0lFr4vhDkwzgLLrIGlNTqIo github.com/gin-contrib/zap v1.1.4/go.mod h1:7lgEpe91kLbeJkwBTPgtVBy4zMa6oSBEcvj662diqKQ= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= -github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ= +github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -177,168 +109,95 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= -github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= -github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= -github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo= -github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s= -github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= -github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= -github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= -github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= -github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= -github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= -github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= -github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/kubocd/kubocd v0.2.1 h1:2IVRs85zqznXz9pEe9yiwuIdjcrVpWlzzLdRqvzyZxk= +github.com/kubocd/kubocd v0.2.1/go.mod h1:ICIRAAcJaK2tIXObQH6LSAUFmgKYzZZU9XqKWaEjnhM= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= -github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 h1:9djga8U4+/TQzv5iMlZHZ/qbGQB9V2nlnk2bmiG+uBs= github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8= github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672 h1:+273wgr7to5QhwOOBE5LwjdNDFAI+8cbJVfB0Zj75aI= github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= +github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -347,50 +206,25 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= -github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4= -github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= -github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= @@ -405,13 +239,12 @@ github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -432,37 +265,12 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= -github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -471,62 +279,51 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg= golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -534,19 +331,16 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= -google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8= -google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= @@ -555,49 +349,34 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -helm.sh/helm/v3 v3.17.2 h1:agYQ5ew2jq5vdx2K7q5W44KyKQrnSubUMCQsjkiv3/o= -helm.sh/helm/v3 v3.17.2/go.mod h1:+uJKMH/UiMzZQOALR3XUf3BLIoczI2RKKD6bMhPh4G8= k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.2 h1:WzyxAu4mvLkQxwD9hGa4ZfExo3yZZaYzoYvvVDlM6vw= -k8s.io/apiserver v0.32.2/go.mod h1:PEwREHiHNU2oFdte7BjzA1ZyjWjuckORLIK/wLV5goM= -k8s.io/cli-runtime v0.32.2 h1:aKQR4foh9qeyckKRkNXUccP9moxzffyndZAvr+IXMks= -k8s.io/cli-runtime v0.32.2/go.mod h1:a/JpeMztz3xDa7GCyyShcwe55p8pbcCVQxvqZnIwXN8= k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= -k8s.io/component-base v0.32.2 h1:1aUL5Vdmu7qNo4ZsE+569PV5zFatM9hl+lb3dEea2zU= -k8s.io/component-base v0.32.2/go.mod h1:PXJ61Vx9Lg+P5mS8TLd7bCIr+eMJRQTyXe8KvkrvJq0= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us= -k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= -oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= -sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= -sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= +sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= -sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= -sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= -sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/internal/config/config.go b/internal/config/config.go index 47f156c..4ef93b9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -33,6 +33,7 @@ type ApplicationConfig struct { Logging Logging `mapstructure:"logging"` Swagger Swagger `mapstructure:"swagger"` Catalogs []*model.Catalog `mapstructure:"catalog"` + Clusters []*model.Cluster `yaml:"clusters"` } // Server configuration diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 75ec670..182c1b8 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -196,6 +196,31 @@ func Test_LoadConfig_Catalog(t *testing.T) { assert.False(t, catalog.IsAuthenticated(), fmt.Sprintf("The catalog '%s' should not be authenticated", catalog.ID)) } +func Test_LoadConfig_Clusters(t *testing.T) { + // Given + viper.Set("config", "testdata/application.yaml") + // When + clusters := GetAppConfig().Clusters + // Then + require.NotEmpty(t, clusters, "K8S clusters should not be empty") + cluster := clusters[0] + assert.Equal(t, "kubo03dev", cluster.ID, "ID") + assert.Equal(t, "dev", cluster.Env, "Env") + assert.Equal(t, "/path/to/kubeconfig", cluster.Auth.Kubeconfig.Path, "cluster.Auth.Kubeconfig") + assert.Equal(t, "dev-context", cluster.Auth.Kubeconfig.Context, "cluster.Auth.Context") + assert.Equal(t, "https://host.docker.internal:56660", cluster.Auth.Kubeconfig.APIServer, "cluster.Auth.Kubeconfig.APIServer") + assert.True(t, cluster.Auth.Kubeconfig.InsecureSkipTlsVerify, "cluster.Auth.Kubeconfig.InsecureSkipTlsVerify") + + assert.Equal(t, "https://k8s-api-server-url:6443", cluster.Auth.Certificate.APIServer, "cluster.Auth.Certificate.ApiServer") + assert.Equal(t, "/path/to/client-key.pem", cluster.Auth.Certificate.ClientKey, "cluster.Auth.Certificate.ClientKey") + assert.Equal(t, "/path/to/client-cert.pem", cluster.Auth.Certificate.ClientCert, "cluster.Auth.Certificate.ClientCert") + assert.Equal(t, "/path/to/ca-cert.pem", cluster.Auth.Certificate.CACert, "cluster.Auth.Certificate.CaCert") + + assert.Equal(t, "https://k8s-api-server-url:6443", cluster.Auth.Bearer.APIServer, "cluster.Auth.Bearer.ApiServer") + assert.Equal(t, "$(BEARER_TOKEN)", cluster.Auth.Bearer.BearerToken, "cluster.Auth.Bearer.BearerToken") + +} + func Test_LoadConfig_ConfigFileNotFound(t *testing.T) { defer func() { if r := recover(); r != nil { diff --git a/internal/config/testdata/application.yaml b/internal/config/testdata/application.yaml index 80b4bd8..a966b49 100644 --- a/internal/config/testdata/application.yaml +++ b/internal/config/testdata/application.yaml @@ -93,3 +93,24 @@ catalog: repoUrl: quay.io/okdp/applications packages: - name: minio + +clusters: + - id: kubo03dev + env: dev + auth: + kubeconfig: + apiServer: https://host.docker.internal:56660 + path: /path/to/kubeconfig + context: dev-context + insecureSkipTlsVerify: True + certificate: + apiServer: https://k8s-api-server-url:6443 + clientKey: /path/to/client-key.pem + clientCert: /path/to/client-cert.pem + caCert: /path/to/ca-cert.pem + bearer: + apiServer: https://k8s-api-server-url:6443 + bearerToken: $(BEARER_TOKEN) + + + diff --git a/internal/controllers/cluster_controller.go b/internal/controllers/cluster_controller.go new file mode 100644 index 0000000..aa50183 --- /dev/null +++ b/internal/controllers/cluster_controller.go @@ -0,0 +1,70 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" + log "github.com/okdp/okdp-server/internal/common/logging" + "github.com/okdp/okdp-server/internal/services" +) + +type IClusterController struct { + clusterService *services.ClusterService +} + +func ClusterController() *IClusterController { + return &IClusterController{ + clusterService: services.NewClusterService(), + } +} + +func (r IClusterController) ListClusters(c *gin.Context) { + clusters := r.clusterService.ListClusters() + c.JSON(http.StatusOK, clusters) +} + +func (r IClusterController) GetCluster(c *gin.Context, clusterID string) { + cluster, err := r.clusterService.GetCluster(clusterID) + if err != nil { + log.Error("%+v", clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, cluster) +} + +func (r IClusterController) ListNamespaces(c *gin.Context, clusterID string) { + namespaces, err := r.clusterService.ListNamespaces(clusterID) + if err != nil { + log.Error("%+v", clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, namespaces) +} + +func (r IClusterController) GetNamespace(c *gin.Context, clusterID string, namespace string) { + namespace, err := r.clusterService.GetNamespaceByName(clusterID, namespace) + if err != nil { + log.Error("%+v", clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, namespace) +} diff --git a/internal/controllers/register.go b/internal/controllers/register.go index 496c176..e2387d1 100644 --- a/internal/controllers/register.go +++ b/internal/controllers/register.go @@ -19,9 +19,12 @@ package controllers import ( "github.com/gin-gonic/gin" _catalog "github.com/okdp/okdp-server/api/openapi/v3/_api/catalogs" + _cluster "github.com/okdp/okdp-server/api/openapi/v3/_api/clusters" + _k8s "github.com/okdp/okdp-server/api/openapi/v3/_api/k8s" + _repositories "github.com/okdp/okdp-server/api/openapi/v3/_api/repositories" _user "github.com/okdp/okdp-server/api/openapi/v3/_api/users" + "github.com/okdp/okdp-server/internal/common/constants" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" ) type Router struct { @@ -34,7 +37,10 @@ type Group struct { func (g *Group) RegisterControllers() { _user.RegisterHandlers(g, UserProfileController()) + _cluster.RegisterHandlers(g, ClusterController()) _catalog.RegisterHandlers(g, CatalogController()) + _repositories.RegisterHandlers(g, GitRepoController()) + _k8s.RegisterHandlers(g, KuboCDController()) } func (r *Router) RegisterSwaggerAPIDoc(swaggerConf config.Swagger) { diff --git a/internal/controllers/user_profile.go b/internal/controllers/user_profile.go index 32b2247..538e606 100644 --- a/internal/controllers/user_profile.go +++ b/internal/controllers/user_profile.go @@ -20,8 +20,9 @@ import ( "net/http" "github.com/gin-gonic/gin" - "github.com/okdp/okdp-server/internal/constants" - "github.com/okdp/okdp-server/internal/security/authc/model" + "github.com/okdp/okdp-server/internal/common/constants" + "github.com/okdp/okdp-server/internal/model" + authc "github.com/okdp/okdp-server/internal/security/authc/model" ) type IUserProfileController struct { @@ -34,7 +35,24 @@ func UserProfileController() *IUserProfileController { func (r IUserProfileController) GetMyProfile(c *gin.Context) { if maybeUserInfo, found := c.Get(constants.OAuth2UserInfo); found { - c.JSON(http.StatusOK, maybeUserInfo.(*model.UserInfo)) + c.JSON(http.StatusOK, maybeUserInfo.(*authc.UserInfo)) } } + +func GetUserInfo(c *gin.Context) (*authc.UserInfo, *model.ServerResponse) { + maybeUserInfo, found := c.Get(constants.OAuth2UserInfo) + err := model. + NewServerResponse(model.OkdpServerResponse). + Unauthorized("Unauthorized") + if !found { + return nil, err + } + + userInfo, ok := maybeUserInfo.(*authc.UserInfo) + if !ok { + return nil, err + } + + return userInfo, nil +} diff --git a/internal/integrations/registry/client/error.go b/internal/integrations/registry/client/error.go deleted file mode 100644 index 9d78ba1..0000000 --- a/internal/integrations/registry/client/error.go +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2025 okdp.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package client - -import ( - "github.com/okdp/okdp-server/internal/servererrors" -) - -func CatalogNotFoundError(provided string) *servererrors.ServerError { - return servererrors.OfType(servererrors.OkdpServer). - NotFoundError("The catalog with id %s not found.", provided) -} - -func CatalogPackageNotFoundError(catalogID string, packageName string) *servererrors.ServerError { - return servererrors.OfType(servererrors.OkdpServer). - NotFoundError("The package %s not found in the catalog ID %s.", packageName, catalogID) -} diff --git a/internal/model/git_commit.go b/internal/model/cluster.go similarity index 77% rename from internal/model/git_commit.go rename to internal/model/cluster.go index 4aea671..872e02e 100644 --- a/internal/model/git_commit.go +++ b/internal/model/cluster.go @@ -20,4 +20,9 @@ import ( "github.com/okdp/okdp-server/api/openapi/v3/_api" ) -type GitCommit _api.GitCommit +type Cluster _api.Cluster + +func ClusterNotFoundError(clusterID string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("The cluster with id %s not found.", clusterID) +} diff --git a/internal/server/server.go b/internal/server/server.go index c6d5f1c..a9fff08 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -22,10 +22,10 @@ import ( "github.com/gin-gonic/gin" + "github.com/okdp/okdp-server/internal/common/constants" + log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" - "github.com/okdp/okdp-server/internal/constants" "github.com/okdp/okdp-server/internal/controllers" - log "github.com/okdp/okdp-server/internal/logging" "github.com/okdp/okdp-server/internal/security" "github.com/okdp/okdp-server/internal/security/authc" "github.com/okdp/okdp-server/internal/security/authz" diff --git a/internal/services/cluster.go b/internal/services/cluster.go new file mode 100644 index 0000000..ce24233 --- /dev/null +++ b/internal/services/cluster.go @@ -0,0 +1,48 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package services + +import ( + "github.com/okdp/okdp-server/internal/integrations/k8s" + "github.com/okdp/okdp-server/internal/model" +) + +type ClusterService struct { + cluster *k8s.K8S +} + +func NewClusterService() *ClusterService { + return &ClusterService{ + cluster: k8s.NewK8S(), + } +} + +func (s ClusterService) ListClusters() []*model.Cluster { + return s.cluster.ListClusters() +} + +func (s ClusterService) GetCluster(clusterID string) (*model.Cluster, *model.ServerResponse) { + return s.cluster.GetCluster(clusterID) +} + +func (s ClusterService) ListNamespaces(clusterID string) ([]string, *model.ServerResponse) { + return []string{"Not Implemented: " + clusterID}, nil +} + +func (s ClusterService) GetNamespaceByName(clusterID string, namespace string) (string, *model.ServerResponse) { + return "Not Implemented: " + clusterID + "/" + namespace, nil +} From f77cf1c5bd2e1f08ff11c693066e76183524cb79 Mon Sep 17 00:00:00 2001 From: iizitounene Date: Wed, 14 May 2025 17:37:39 +0200 Subject: [PATCH 06/14] feat: implement k8s api server interactions --- api/openapi/v3/_api/k8s/k8s-server.go | 865 ++++++++++++++++++ api/openapi/v3/definition/ReleaseStatus.yaml | 87 ++ api/openapi/v3/paths/k8s/release-by-name.yaml | 82 ++ api/openapi/v3/paths/k8s/release-status.yaml | 41 + api/openapi/v3/paths/k8s/releases.yaml | 136 +++ internal/controllers/kubocd_controller.go | 86 ++ internal/integrations/k8s/client/client.go | 100 ++ internal/integrations/k8s/client/fluxcd.go | 109 +++ internal/integrations/k8s/client/git.go | 70 ++ internal/integrations/k8s/client/kubocd.go | 142 +++ internal/integrations/k8s/client/secret.go | 120 +++ internal/integrations/k8s/cluster.go | 42 + internal/integrations/k8s/k8s.go | 31 + internal/integrations/k8s/kubocd.go | 71 ++ internal/model/kubocd.go | 74 ++ internal/services/kubocd.go | 57 ++ 16 files changed, 2113 insertions(+) create mode 100644 api/openapi/v3/_api/k8s/k8s-server.go create mode 100644 api/openapi/v3/definition/ReleaseStatus.yaml create mode 100644 api/openapi/v3/paths/k8s/release-by-name.yaml create mode 100644 api/openapi/v3/paths/k8s/release-status.yaml create mode 100644 api/openapi/v3/paths/k8s/releases.yaml create mode 100644 internal/controllers/kubocd_controller.go create mode 100644 internal/integrations/k8s/client/client.go create mode 100644 internal/integrations/k8s/client/fluxcd.go create mode 100644 internal/integrations/k8s/client/git.go create mode 100644 internal/integrations/k8s/client/kubocd.go create mode 100644 internal/integrations/k8s/client/secret.go create mode 100644 internal/integrations/k8s/cluster.go create mode 100644 internal/integrations/k8s/k8s.go create mode 100644 internal/integrations/k8s/kubocd.go create mode 100644 internal/model/kubocd.go create mode 100644 internal/services/kubocd.go diff --git a/api/openapi/v3/_api/k8s/k8s-server.go b/api/openapi/v3/_api/k8s/k8s-server.go new file mode 100644 index 0000000..4144a18 --- /dev/null +++ b/api/openapi/v3/_api/k8s/k8s-server.go @@ -0,0 +1,865 @@ +// Package _k8s provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. +package _k8s + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/oapi-codegen/runtime" +) + +// Defines values for CreateK8sReleaseJSONBodySpecPackageProvider. +const ( + CreateK8sReleaseJSONBodySpecPackageProviderAws CreateK8sReleaseJSONBodySpecPackageProvider = "aws" + CreateK8sReleaseJSONBodySpecPackageProviderAzure CreateK8sReleaseJSONBodySpecPackageProvider = "azure" + CreateK8sReleaseJSONBodySpecPackageProviderGcp CreateK8sReleaseJSONBodySpecPackageProvider = "gcp" + CreateK8sReleaseJSONBodySpecPackageProviderGeneric CreateK8sReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for CreateK8sReleaseJSONBodySpecPackageVerifyProvider. +const ( + CreateK8sReleaseJSONBodySpecPackageVerifyProviderCosign CreateK8sReleaseJSONBodySpecPackageVerifyProvider = "cosign" + CreateK8sReleaseJSONBodySpecPackageVerifyProviderNotation CreateK8sReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// Defines values for UpdateK8sReleaseJSONBodySpecPackageProvider. +const ( + UpdateK8sReleaseJSONBodySpecPackageProviderAws UpdateK8sReleaseJSONBodySpecPackageProvider = "aws" + UpdateK8sReleaseJSONBodySpecPackageProviderAzure UpdateK8sReleaseJSONBodySpecPackageProvider = "azure" + UpdateK8sReleaseJSONBodySpecPackageProviderGcp UpdateK8sReleaseJSONBodySpecPackageProvider = "gcp" + UpdateK8sReleaseJSONBodySpecPackageProviderGeneric UpdateK8sReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for UpdateK8sReleaseJSONBodySpecPackageVerifyProvider. +const ( + UpdateK8sReleaseJSONBodySpecPackageVerifyProviderCosign UpdateK8sReleaseJSONBodySpecPackageVerifyProvider = "cosign" + UpdateK8sReleaseJSONBodySpecPackageVerifyProviderNotation UpdateK8sReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// CreateK8sReleaseJSONBody defines parameters for CreateK8sRelease. +type CreateK8sReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *CreateK8sReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider CreateK8sReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// CreateK8sReleaseParams defines parameters for CreateK8sRelease. +type CreateK8sReleaseParams struct { + // DryRun If true, performs a server-side dry run without persisting the resource + DryRun *bool `form:"dryRun,omitempty" json:"dryRun,omitempty"` +} + +// CreateK8sReleaseJSONBodySpecPackageProvider defines parameters for CreateK8sRelease. +type CreateK8sReleaseJSONBodySpecPackageProvider string + +// CreateK8sReleaseJSONBodySpecPackageVerifyProvider defines parameters for CreateK8sRelease. +type CreateK8sReleaseJSONBodySpecPackageVerifyProvider string + +// UpdateK8sReleaseJSONBody defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *UpdateK8sReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider UpdateK8sReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// UpdateK8sReleaseParams defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseParams struct { + // DryRun If true, performs a server-side dry run without persisting the resource + DryRun *bool `form:"dryRun,omitempty" json:"dryRun,omitempty"` +} + +// UpdateK8sReleaseJSONBodySpecPackageProvider defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseJSONBodySpecPackageProvider string + +// UpdateK8sReleaseJSONBodySpecPackageVerifyProvider defines parameters for UpdateK8sRelease. +type UpdateK8sReleaseJSONBodySpecPackageVerifyProvider string + +// CreateK8sReleaseJSONRequestBody defines body for CreateK8sRelease for application/json ContentType. +type CreateK8sReleaseJSONRequestBody CreateK8sReleaseJSONBody + +// UpdateK8sReleaseJSONRequestBody defines body for UpdateK8sRelease for application/json ContentType. +type UpdateK8sReleaseJSONRequestBody UpdateK8sReleaseJSONBody + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // Get the list of the deployed releases + // (GET /clusters/{clusterId}/namespaces/{namespace}/releases) + ListK8sReleases(c *gin.Context, clusterId string, namespace string) + // Create KuboCD release in Kubernetes + // (POST /clusters/{clusterId}/namespaces/{namespace}/releases) + CreateK8sRelease(c *gin.Context, clusterId string, namespace string, params CreateK8sReleaseParams) + // Update KuboCD release in Kubernetes + // (PUT /clusters/{clusterId}/namespaces/{namespace}/releases) + UpdateK8sRelease(c *gin.Context, clusterId string, namespace string, params UpdateK8sReleaseParams) + // Delete the KuboCD release in kubernetes + // (DELETE /clusters/{clusterId}/namespaces/{namespace}/releases/{releaseName}) + DeleteK8sRelease(c *gin.Context, clusterId string, namespace string, releaseName string) + // Get the deployed release by name + // (GET /clusters/{clusterId}/namespaces/{namespace}/releases/{releaseName}) + GetK8sRelease(c *gin.Context, clusterId string, namespace string, releaseName string) + // Get the release status + // (GET /clusters/{clusterId}/namespaces/{namespace}/releases/{releaseName}/status) + GetK8sReleaseStatus(c *gin.Context, clusterId string, namespace string, releaseName string) +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +type MiddlewareFunc func(c *gin.Context) + +// ListK8sReleases operation middleware +func (siw *ServerInterfaceWrapper) ListK8sReleases(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.ListK8sReleases(c, clusterId, namespace) +} + +// CreateK8sRelease operation middleware +func (siw *ServerInterfaceWrapper) CreateK8sRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // Parameter object where we will unmarshal all parameters from the context + var params CreateK8sReleaseParams + + // ------------- Optional query parameter "dryRun" ------------- + + err = runtime.BindQueryParameter("form", true, false, "dryRun", c.Request.URL.Query(), ¶ms.DryRun) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter dryRun: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.CreateK8sRelease(c, clusterId, namespace, params) +} + +// UpdateK8sRelease operation middleware +func (siw *ServerInterfaceWrapper) UpdateK8sRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // Parameter object where we will unmarshal all parameters from the context + var params UpdateK8sReleaseParams + + // ------------- Optional query parameter "dryRun" ------------- + + err = runtime.BindQueryParameter("form", true, false, "dryRun", c.Request.URL.Query(), ¶ms.DryRun) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter dryRun: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.UpdateK8sRelease(c, clusterId, namespace, params) +} + +// DeleteK8sRelease operation middleware +func (siw *ServerInterfaceWrapper) DeleteK8sRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "releaseName" ------------- + var releaseName string + + err = runtime.BindStyledParameterWithOptions("simple", "releaseName", c.Param("releaseName"), &releaseName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter releaseName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.DeleteK8sRelease(c, clusterId, namespace, releaseName) +} + +// GetK8sRelease operation middleware +func (siw *ServerInterfaceWrapper) GetK8sRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "releaseName" ------------- + var releaseName string + + err = runtime.BindStyledParameterWithOptions("simple", "releaseName", c.Param("releaseName"), &releaseName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter releaseName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetK8sRelease(c, clusterId, namespace, releaseName) +} + +// GetK8sReleaseStatus operation middleware +func (siw *ServerInterfaceWrapper) GetK8sReleaseStatus(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "releaseName" ------------- + var releaseName string + + err = runtime.BindStyledParameterWithOptions("simple", "releaseName", c.Param("releaseName"), &releaseName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter releaseName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetK8sReleaseStatus(c, clusterId, namespace, releaseName) +} + +// GinServerOptions provides options for the Gin server. +type GinServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router gin.IRouter, si ServerInterface) { + RegisterHandlersWithOptions(router, si, GinServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { + errorHandler := options.ErrorHandler + if errorHandler == nil { + errorHandler = func(c *gin.Context, err error, statusCode int) { + c.JSON(statusCode, gin.H{"msg": err.Error()}) + } + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + HandlerMiddlewares: options.Middlewares, + ErrorHandler: errorHandler, + } + + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/releases", wrapper.ListK8sReleases) + router.POST(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/releases", wrapper.CreateK8sRelease) + router.PUT(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/releases", wrapper.UpdateK8sRelease) + router.DELETE(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/releases/:releaseName", wrapper.DeleteK8sRelease) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/releases/:releaseName", wrapper.GetK8sRelease) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/releases/:releaseName/status", wrapper.GetK8sReleaseStatus) +} diff --git a/api/openapi/v3/definition/ReleaseStatus.yaml b/api/openapi/v3/definition/ReleaseStatus.yaml new file mode 100644 index 0000000..dd53ee4 --- /dev/null +++ b/api/openapi/v3/definition/ReleaseStatus.yaml @@ -0,0 +1,87 @@ +# controller-gen crd paths=./api/v1alpha1 output:crd:dir=./api/schema +description: Release is the Schema for the releases API. +properties: + status: + description: |- + ReleaseStatus defines the observed state of Release. + As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + (Except for 'context', as controlled by a debug flag) + properties: + context: + description: Context is the resulting context, if requested in debug + options + x-kubernetes-preserve-unknown-fields: true + dependencies: + description: The result of the package template and release value + items: + type: string + type: array + helmReleaseStates: + additionalProperties: + description: HelmReleaseState describe the observed state of a child + HelmRelease + properties: + ready: + type: string + status: + type: string + required: + - ready + type: object + description: HelmReleaseState describe the observed state of child + HelmReleases by name + type: object + missingDependency: + type: string + parameters: + description: Parameters is the resulting parameters set, if requested + in debug options + x-kubernetes-preserve-unknown-fields: true + phase: + type: string + printContexts: + description: |- + PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + as printcolumn + type: string + printDescription: + description: |- + PrintDescription + Copy of the release description, or, if empty the (templated) package one + type: string + printProtected: + description: PrintProtected is a copy of Protected, with a Y/n flag. + To be used in display + type: string + protected: + description: |- + Protected result of Release.spec.protected defaulted to package.spec.protected + It is the value checked by the webhook + type: boolean + readyReleases: + description: |- + ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + as printcolumn + type: string + roles: + description: The result of the package template and release value + items: + type: string + type: array + usage: + additionalProperties: + type: string + description: |- + Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + Key could 'html', 'text', some language id, etc... + type: object + required: + - dependencies + - missingDependency + - phase + - printProtected + - protected + - readyReleases + - roles + type: object +type: object diff --git a/api/openapi/v3/paths/k8s/release-by-name.yaml b/api/openapi/v3/paths/k8s/release-by-name.yaml new file mode 100644 index 0000000..c8ccca6 --- /dev/null +++ b/api/openapi/v3/paths/k8s/release-by-name.yaml @@ -0,0 +1,82 @@ +get: + summary: Get the deployed release by name + description: | + Get the deployed release by name + tags: + - k8s + operationId: GetK8sRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + - in: path + name: releaseName + schema: + type: string + required: true + description: KuboCD release name + responses: + '200': + description: KuboCD Release info + content: + application/json: + schema: + $ref: '../../definition/Release.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + +delete: + summary: Delete the KuboCD release in kubernetes + description: | + Delete the KuboCD release in kubernetes + tags: + - k8s + operationId: DeleteK8sRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + - in: path + name: releaseName + schema: + type: string + required: true + description: KuboCD release name + responses: + '200': + description: KuboCD Release deleted successfully + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/paths/k8s/release-status.yaml b/api/openapi/v3/paths/k8s/release-status.yaml new file mode 100644 index 0000000..a021c6f --- /dev/null +++ b/api/openapi/v3/paths/k8s/release-status.yaml @@ -0,0 +1,41 @@ +get: + summary: Get the release status + description: | + Get the release status + tags: + - k8s + operationId: GetK8sReleaseStatus + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + - in: path + name: releaseName + schema: + type: string + required: true + description: KuboCD release name + responses: + '200': + description: KuboCD Release info + content: + application/json: + schema: + $ref: '../../definition/ReleaseStatus.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/paths/k8s/releases.yaml b/api/openapi/v3/paths/k8s/releases.yaml new file mode 100644 index 0000000..e5b3eea --- /dev/null +++ b/api/openapi/v3/paths/k8s/releases.yaml @@ -0,0 +1,136 @@ +get: + summary: Get the list of the deployed releases + description: | + Get the list of the deployed releases + tags: + - k8s + operationId: ListK8sReleases + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + responses: + '200': + description: Release list + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/ReleaseInfo.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + +post: + summary: Create KuboCD release in Kubernetes + description: | + Create KuboCD release in Kubernetes + tags: + - k8s + operationId: CreateK8sRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + - in: query + name: dryRun + schema: + type: boolean + required: false + description: If true, performs a server-side dry run without persisting the resource + requestBody: + description: Release object to be created + required: true + content: + application/json: + schema: + $ref: '../../definition/Release.yaml' + responses: + '201': + description: Release created successfully + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/ServerResponse.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + +put: + summary: Update KuboCD release in Kubernetes + description: | + Update KuboCD release in Kubernetes + tags: + - k8s + operationId: UpdateK8sRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes namespace + - in: query + name: dryRun + schema: + type: boolean + required: false + description: If true, performs a server-side dry run without persisting the resource + requestBody: + description: Release object to be updated + required: true + content: + application/json: + schema: + $ref: '../../definition/Release.yaml' + responses: + '200': + description: Release updated successfully + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/ServerResponse.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' \ No newline at end of file diff --git a/internal/controllers/kubocd_controller.go b/internal/controllers/kubocd_controller.go new file mode 100644 index 0000000..bd80b16 --- /dev/null +++ b/internal/controllers/kubocd_controller.go @@ -0,0 +1,86 @@ +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" + + _api "github.com/okdp/okdp-server/api/openapi/v3/_api/k8s" + log "github.com/okdp/okdp-server/internal/common/logging" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/services" + "github.com/okdp/okdp-server/internal/utils" +) + +type IKuboCDController struct { + k8sService *services.KuboCDService +} + +func KuboCDController() *IKuboCDController { + return &IKuboCDController{ + k8sService: services.NewKuboCDService(), + } +} + +func (r IKuboCDController) ListK8sReleases(c *gin.Context, clusterID string, namespace string) { + releasesInfo, err := r.k8sService.ListReleases(clusterID, namespace) + if err != nil { + log.Error("Unable to get releases from Kubernetes cluster '%s' on namespace '%s', details: %+v", clusterID, namespace, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, releasesInfo) +} + +func (r IKuboCDController) GetK8sRelease(c *gin.Context, clusterID string, namespace string, releaseName string) { + release, err := r.k8sService.GetRelease(clusterID, namespace, releaseName) + if err != nil { + log.Error("Unable to get release from Kubernetes cluster '%s' on namespace '%s', details: %+v", clusterID, namespace, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, release) +} + +func (r IKuboCDController) GetK8sReleaseStatus(c *gin.Context, clusterID string, namespace string, releaseName string) { + release, err := r.k8sService.GetReleaseStatus(clusterID, namespace, releaseName) + if err != nil { + log.Error("Unable to get release status from Kubernetes cluster '%s' on namespace '%s', details: %+v", clusterID, namespace, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, release) +} + +func (r IKuboCDController) CreateK8sRelease(c *gin.Context, clusterID string, namespace string, params _api.CreateK8sReleaseParams) { + var release model.Release + + if err := c.ShouldBindJSON(&release); err != nil { + resp := model.NewServerResponse(model.OkdpServerResponse).BadRequest("%+v", err.Error()) + c.JSON(resp.Status, resp) + return + } + + response := r.k8sService.CreateRelease(clusterID, namespace, &release, utils.OrFalse(params.DryRun)) + + c.JSON(response.Status, response) + +} + +func (r IKuboCDController) UpdateK8sRelease(c *gin.Context, clusterID string, namespace string, params _api.UpdateK8sReleaseParams) { + var release model.Release + + if err := c.ShouldBindJSON(&release); err != nil { + resp := model.NewServerResponse(model.OkdpServerResponse).BadRequest("%+v", err.Error()) + c.JSON(resp.Status, resp) + return + } + + response := r.k8sService.UpdateRelease(clusterID, namespace, &release, utils.OrFalse(params.DryRun)) + c.JSON(response.Status, response) +} + +func (r IKuboCDController) DeleteK8sRelease(c *gin.Context, clusterID string, namespace string, releaseName string) { + response := r.k8sService.DeleteRelease(clusterID, namespace, releaseName) + c.JSON(response.Status, response) +} diff --git a/internal/integrations/k8s/client/client.go b/internal/integrations/k8s/client/client.go new file mode 100644 index 0000000..e614e72 --- /dev/null +++ b/internal/integrations/k8s/client/client.go @@ -0,0 +1,100 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "sync" + + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + corev1 "k8s.io/api/core/v1" + apiruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/clientcmd" + k8s "sigs.k8s.io/controller-runtime/pkg/client" + + kubocdv1alpha1 "kubocd/api/v1alpha1" + + log "github.com/okdp/okdp-server/internal/common/logging" + "github.com/okdp/okdp-server/internal/config" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/utils" +) + +var ( + instance *KubeClients + once sync.Once +) + +type KubeClients struct { + clients map[string]*KubeClient +} + +type KubeClient struct { + k8s.Client + clusterID string +} + +func GetClients() *KubeClients { + once.Do(func() { + clients := make(map[string]*KubeClient) + clusters := config.GetAppConfig().Clusters + for _, cluster := range clusters { + log.Info("K8S Cluster configuration: %+v", cluster) + config, err := clientcmd.BuildConfigFromFlags(cluster.Auth.Kubeconfig.APIServer, cluster.Auth.Kubeconfig.Path) + if cluster.Auth.Kubeconfig.InsecureSkipTlsVerify { + log.Warn("TLS verification is disabled for cluster ID: %s (%s).", cluster.ID, cluster.Env) + config.Insecure = true + config.CAFile = "" + config.CAData = nil + } + + if err != nil { + log.Fatal("Error building kubeconfig for cluster ID '%s (%s)': %s", cluster.ID, cluster.Env, err.Error()) + } + + kubeClient, err := k8s.New(config, k8s.Options{ + Scheme: newScheme(), + }) + + if err != nil { + log.Fatal("Error creating new k8s client for cluster ID '%s (%s)': %s", cluster.ID, cluster.Env, err.Error()) + } + + clients[utils.MapKey(cluster.ID)] = &KubeClient{kubeClient, cluster.ID} + } + instance = &KubeClients{clients: clients} + }) + return instance +} + +func (c KubeClients) GetClient(clusterID string) (*KubeClient, *model.ServerResponse) { + client, found := c.clients[clusterID] + if !found { + return nil, model.ClusterNotFoundError(clusterID) + } + + return client, nil +} + +func newScheme() *apiruntime.Scheme { + scheme := apiruntime.NewScheme() + _ = sourcev1.AddToScheme(scheme) + _ = kustomizev1.AddToScheme(scheme) + _ = corev1.AddToScheme(scheme) + _ = kubocdv1alpha1.AddToScheme(scheme) + return scheme +} diff --git a/internal/integrations/k8s/client/fluxcd.go b/internal/integrations/k8s/client/fluxcd.go new file mode 100644 index 0000000..ae660b7 --- /dev/null +++ b/internal/integrations/k8s/client/fluxcd.go @@ -0,0 +1,109 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "context" + + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" + k8s "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/utils" +) + +func (c KubeClient) ListKutomizations(ctx context.Context, namespaces ...string) ([]*kustomizev1.Kustomization, *model.ServerResponse) { + var kustomizationList kustomizev1.KustomizationList + if err := c.List(ctx, &kustomizationList); err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to list Kustomizations '%s' ", err.Error()) + } + + filtered := utils.Filter(kustomizationList.Items, func(k kustomizev1.Kustomization) bool { + return len(namespaces) == 0 || utils.Contains(namespaces, k.Namespace) + }) + + return filtered, nil + +} + +func (c KubeClient) ListGitRepositories(ctx context.Context, namespaces ...string) ([]*sourcev1.GitRepository, *model.ServerResponse) { + + var repos sourcev1.GitRepositoryList + if err := c.List(ctx, &repos); err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to list Git Repositories '%s'", err.Error()) + } + + filtered := utils.Filter(repos.Items, func(k sourcev1.GitRepository) bool { + return utils.Contains(namespaces, k.Namespace) + }) + + return filtered, nil +} + +func (c KubeClient) GetGitRepository(ctx context.Context, name string, namespace string) (*sourcev1.GitRepository, *model.ServerResponse) { + repoKey := k8s.ObjectKey{ + Namespace: namespace, + Name: name, + } + var repo sourcev1.GitRepository + err := c.Get(ctx, repoKey, &repo) + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to get fluxcd Git Repository '%s' in namespace '%s', details: '%s'", name, namespace, err.Error()) + } + + return &repo, nil +} + +func (c KubeClient) ListOCIRepositories(ctx context.Context, namespaces ...string) ([]*sourcev1b2.OCIRepository, *model.ServerResponse) { + + var repos sourcev1b2.OCIRepositoryList + if err := c.List(ctx, &repos); err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to list OCI Repositories '%s'", err.Error()) + } + + filtered := utils.Filter(repos.Items, func(k sourcev1b2.OCIRepository) bool { + return utils.Contains(namespaces, k.Namespace) + }) + + return filtered, nil +} + +func (c KubeClient) GetOCIRepository(ctx context.Context, name string, namespace string) (*sourcev1b2.OCIRepository, *model.ServerResponse) { + repoKey := k8s.ObjectKey{ + Namespace: namespace, + Name: name, + } + var repo sourcev1b2.OCIRepository + err := c.Get(ctx, repoKey, &repo) + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to get fluxcd OCI Repository '%s' in namespace '%s', details: '%s'", name, namespace, err.Error()) + } + + return &repo, nil +} diff --git a/internal/integrations/k8s/client/git.go b/internal/integrations/k8s/client/git.go new file mode 100644 index 0000000..92a5d43 --- /dev/null +++ b/internal/integrations/k8s/client/git.go @@ -0,0 +1,70 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "context" + + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" + + "github.com/okdp/okdp-server/internal/common/constants" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/utils" +) + +func (c KubeClient) ListGitRepos(namespaces ...string) ([]*model.GitRepository, *model.ServerResponse) { + + ctx := context.Background() + + var kustomizations []*kustomizev1.Kustomization + kustomizations, err := c.ListKutomizations(ctx, namespaces...) + if err != nil { + return nil, err + } + + kustomizations = utils.Filter2(kustomizations, func(k kustomizev1.Kustomization) bool { + return k.Spec.SourceRef.Kind == constants.GitRepository + }) + + gitRepos := make([]*model.GitRepository, 0, len(kustomizations)) + + for _, k := range kustomizations { + namespace := utils.DefaultIfEmpty(k.Spec.SourceRef.Namespace, k.Namespace) + fluxRepo, err := c.GetGitRepository(ctx, k.Spec.SourceRef.Name, namespace) + if err != nil { + return nil, err + } + gitRepo := &model.GitRepository{ + RepoURL: fluxRepo.Spec.URL, + Ref: BranchOrTag(fluxRepo.Spec.Reference.Branch, fluxRepo.Spec.Reference.Tag), + Name: k.Name, + Namespace: k.Namespace, + Path: k.Spec.Path, + } + gitRepo.Credentials.SecretRef = fluxRepo.Spec.SecretRef.Name + gitRepos = append(gitRepos, gitRepo) + } + + return gitRepos, nil +} + +func BranchOrTag(branch, tag string) string { + if branch != "" { + return "refs/heads/" + branch + } + return "refs/tags/" + tag +} diff --git a/internal/integrations/k8s/client/kubocd.go b/internal/integrations/k8s/client/kubocd.go new file mode 100644 index 0000000..0ad2be8 --- /dev/null +++ b/internal/integrations/k8s/client/kubocd.go @@ -0,0 +1,142 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8s "sigs.k8s.io/controller-runtime/pkg/client" + + kubocdv1alpha1 "kubocd/api/v1alpha1" + + "github.com/okdp/okdp-server/internal/common/constants" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/utils" +) + +func (c KubeClient) ListReleases(ctx context.Context, namespaces ...string) ([]*model.Release, *model.ServerResponse) { + + var releaseList kubocdv1alpha1.ReleaseList + if err := c.List(ctx, &releaseList); err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to list KuboCD Releases '%s'", err.Error()) + } + + converted := model.ReleaseList(releaseList) + + filtered := utils.Filter2(converted.ToReleases(), func(k model.Release) bool { + return utils.Contains(namespaces, k.Namespace) + }) + + return filtered, nil +} + +func (c KubeClient) GetRelease(ctx context.Context, namespace string, releaseName string) (*model.Release, *model.ServerResponse) { + releaseKey := k8s.ObjectKey{ + Namespace: namespace, + Name: releaseName, + } + + var release kubocdv1alpha1.Release + if err := c.Get(ctx, releaseKey, &release); err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to get KuboCD Release '%s'", err.Error()) + } + + converted := model.Release(release) + converted.SanitizeMetadata() + + return &converted, nil +} + +func (c KubeClient) GetReleaseStatus(ctx context.Context, namespace string, releaseName string) (*model.ReleaseStatus, *model.ServerResponse) { + releaseKey := k8s.ObjectKey{ + Namespace: namespace, + Name: releaseName, + } + + var release kubocdv1alpha1.Release + if err := c.Get(ctx, releaseKey, &release); err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to get KuboCD Release Status '%s'", err.Error()) + } + + converted := model.ReleaseStatus(release.Status) + + return &converted, nil +} + +func (c KubeClient) CreateRelease(ctx context.Context, namespace string, release *model.Release, dryRun bool) *model.ServerResponse { + rel := kubocdv1alpha1.Release(*release) + rel.Namespace = namespace + var err error + + if dryRun { + err = c.Create(ctx, &rel, &k8s.CreateOptions{DryRun: []string{constants.All}}) + } else { + err = c.Create(ctx, &rel) + } + if err != nil { + return model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to create KuboCD Release '%s/%s (%s)', details: '%s'", release.Namespace, release.Name, dryRun, err.Error()) + } + + return model.NewServerResponse(model.K8sClusterResponse).Created("Successfuly created release %s/%s", release.Namespace, release.Name) +} + +func (c KubeClient) UpdateRelease(ctx context.Context, namespace string, release *model.Release, dryRun bool) *model.ServerResponse { + rel := kubocdv1alpha1.Release(*release) + rel.Namespace = namespace + var err error + + if dryRun { + err = c.Update(ctx, &rel, &k8s.UpdateOptions{DryRun: []string{constants.All}}) + } else { + err = c.Update(ctx, &rel) + } + if err != nil { + return model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to update KuboCD Release '%s/%s (%s)', details: '%s'", release.Namespace, release.Name, dryRun, err.Error()) + } + + return model.NewServerResponse(model.K8sClusterResponse).Updated("Successfuly updated release %s/%s", release.Namespace, release.Name) +} + +func (c KubeClient) DeleteRelease(ctx context.Context, namespace string, releaseName string) *model.ServerResponse { + rel := kubocdv1alpha1.Release{ + ObjectMeta: metav1.ObjectMeta{ + Name: releaseName, + Namespace: namespace, + }, + } + + err := c.Delete(ctx, &rel) + if err != nil { + return model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to delete KuboCD Release '%s/%s', details: '%s'", namespace, releaseName, err.Error()) + } + + return model.NewServerResponse(model.K8sClusterResponse).Deleted("Successfuly deleted release %s", releaseName) + +} diff --git a/internal/integrations/k8s/client/secret.go b/internal/integrations/k8s/client/secret.go new file mode 100644 index 0000000..4cc8688 --- /dev/null +++ b/internal/integrations/k8s/client/secret.go @@ -0,0 +1,120 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "context" + "os" + + "github.com/go-git/go-git/v5/plumbing/transport" + "github.com/go-git/go-git/v5/plumbing/transport/http" + "github.com/go-git/go-git/v5/plumbing/transport/ssh" + "github.com/okdp/okdp-server/internal/model" + "github.com/skeema/knownhosts" + corev1 "k8s.io/api/core/v1" + k8s "sigs.k8s.io/controller-runtime/pkg/client" + + log "github.com/okdp/okdp-server/internal/common/logging" +) + +type K8SSecret struct { + corev1.Secret +} + +func (c KubeClient) GetSecret(ctx context.Context, name string, namespace string) (*K8SSecret, *model.ServerResponse) { + secretKey := k8s.ObjectKey{ + Namespace: namespace, + Name: name, + } + var secret corev1.Secret + err := c.Get(ctx, secretKey, &secret) + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to get Kubernetes secret '%s' in namespace '%s', details: '%s'", name, namespace, err.Error()) + } + + return &K8SSecret{secret}, nil + +} + +func (c KubeClient) GetAuthMethod(secretName string, namespace string) (transport.AuthMethod, *model.ServerResponse) { + secret, err := c.GetSecret(context.Background(), secretName, namespace) + if err != nil { + return nil, err + } + auth, err := secret.ToAuthMethod() + if err != nil { + return nil, err + } + return auth, nil +} + +func (s K8SSecret) ToAuthMethod() (transport.AuthMethod, *model.ServerResponse) { + switch { + case s.Data != nil && s.Data["password"] != nil: + log.Fatal("GIT repository access will use git token") + return &http.BasicAuth{ + Username: string(s.Data["username"]), + Password: string(s.Data["password"]), + }, nil + + case s.Data != nil && s.Data["identity"] != nil: + return BuildKey(s.Secret) + + default: + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Invalid secret %s=%s", s.Name, s.Namespace) + } +} + +func BuildKey(secret corev1.Secret) (*ssh.PublicKeys, *model.ServerResponse) { + key, err := ssh.NewPublicKeys("git", secret.Data["identity"], "") + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to create new public key from secret %s=%s, details: %s", secret.Name, secret.Namespace, err.Error()) + } + file, err := os.CreateTemp(os.TempDir(), "git_known_hosts") + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to create new tmp dir for git_known_hosts from secret %s=%s, details: %s", secret.Name, secret.Namespace, err.Error()) + } + defer func() { + if err := file.Close(); err != nil { + log.Error("Error closing file: %v", err) + } + _ = os.Remove(file.Name()) + }() + + _, err = file.Write(secret.Data["known_hosts"]) + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to write known_hosts from secret %s=%s, details: %s", secret.Name, secret.Namespace, err.Error()) + } + db, err := knownhosts.NewDB(file.Name()) + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to create a new known hosts database from secret %s=%s, details: %s", secret.Name, secret.Namespace, err.Error()) + } + key.HostKeyCallback = db.HostKeyCallback() + return key, nil +} diff --git a/internal/integrations/k8s/cluster.go b/internal/integrations/k8s/cluster.go new file mode 100644 index 0000000..a79d23d --- /dev/null +++ b/internal/integrations/k8s/cluster.go @@ -0,0 +1,42 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package k8s + +import ( + "strings" + + "github.com/okdp/okdp-server/internal/config" + "github.com/okdp/okdp-server/internal/model" +) + +func (r K8S) ListClusters() []*model.Cluster { + clusters := config.GetAppConfig().Clusters + if clusters == nil { + return []*model.Cluster{} + } + return clusters +} + +func (r K8S) GetCluster(clusterID string) (*model.Cluster, *model.ServerResponse) { + clusters := config.GetAppConfig().Clusters + for _, cluster := range clusters { + if strings.EqualFold(cluster.ID, clusterID) { + return cluster, nil + } + } + return nil, model.ClusterNotFoundError(clusterID) +} diff --git a/internal/integrations/k8s/k8s.go b/internal/integrations/k8s/k8s.go new file mode 100644 index 0000000..5761261 --- /dev/null +++ b/internal/integrations/k8s/k8s.go @@ -0,0 +1,31 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package k8s + +import ( + "github.com/okdp/okdp-server/internal/integrations/k8s/client" +) + +type K8S struct { + *client.KubeClients +} + +func NewK8S() *K8S { + return &K8S{ + client.GetClients(), + } +} diff --git a/internal/integrations/k8s/kubocd.go b/internal/integrations/k8s/kubocd.go new file mode 100644 index 0000000..604935d --- /dev/null +++ b/internal/integrations/k8s/kubocd.go @@ -0,0 +1,71 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package k8s + +import ( + "context" + + "github.com/okdp/okdp-server/internal/model" +) + +func (r K8S) ListReleases(clusterID string, namespace string) ([]*model.Release, *model.ServerResponse) { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return nil, err + } + return kubeClient.ListReleases(context.Background(), namespace) +} + +func (r K8S) GetRelease(clusterID string, namespace string, releaseName string) (*model.Release, *model.ServerResponse) { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return nil, err + } + return kubeClient.GetRelease(context.Background(), namespace, releaseName) +} + +func (r K8S) GetReleaseStatus(clusterID string, namespace string, releaseName string) (*model.ReleaseStatus, *model.ServerResponse) { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return nil, err + } + return kubeClient.GetReleaseStatus(context.Background(), namespace, releaseName) +} + +func (r K8S) CreateRelease(clusterID string, namespace string, release *model.Release, dryRun bool) *model.ServerResponse { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return err + } + return kubeClient.CreateRelease(context.Background(), namespace, release, dryRun) +} + +func (r K8S) UpdateRelease(clusterID string, namespace string, release *model.Release, dryRun bool) *model.ServerResponse { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return err + } + return kubeClient.UpdateRelease(context.Background(), namespace, release, dryRun) +} + +func (r K8S) DeleteRelease(clusterID string, namespace string, releaseName string) *model.ServerResponse { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return err + } + return kubeClient.DeleteRelease(context.Background(), namespace, releaseName) +} diff --git a/internal/model/kubocd.go b/internal/model/kubocd.go new file mode 100644 index 0000000..8daec5d --- /dev/null +++ b/internal/model/kubocd.go @@ -0,0 +1,74 @@ +/* + * Copyright 2024 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package model + +import ( + "sigs.k8s.io/yaml" + + kubocdv1alpha1 "kubocd/api/v1alpha1" + + "github.com/okdp/okdp-server/api/openapi/v3/_api" +) + +type Release kubocdv1alpha1.Release +type ReleaseList kubocdv1alpha1.ReleaseList +type ReleaseStatus kubocdv1alpha1.ReleaseStatus + +type ReleaseInfo _api.ReleaseInfo + +func (r *ReleaseList) ToReleases() []*Release { + converted := make([]*Release, len(r.Items)) + for i, release := range r.Items { + c := Release(release) + c.SanitizeMetadata() + converted[i] = &c + } + return converted +} + +func (r *Release) SanitizeMetadata() *Release { + r.ObjectMeta.ManagedFields = nil + r.ObjectMeta.Finalizers = nil + r.ObjectMeta.UID = "" + r.ObjectMeta.Generation = 0 + // r.ObjectMeta.CreationTimestamp = metav1.Time{} + return r +} + +func (r *Release) SanitizeStatus() *Release { + r.ObjectMeta.ResourceVersion = "" + // r.Status = kubocdv1alpha1.ReleaseStatus{} + return r +} + +func (r *Release) ToYAML() (string, error) { + data, err := yaml.Marshal(r) + if err != nil { + return "", err + } + return string(data), nil +} + +func KuboCDReleaseNotFoundError(clusterID string, namespace string, releaseName string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("Unable to find KuboCD release '%s' in the kubernetes cluster '%s' on the namespace '%s'.", releaseName, clusterID, namespace) +} + +func KuboCDReleaseCreated(clusterID string, namespace string, releaseName string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("Unable to find KuboCD release '%s' in the kubernetes cluster '%s' on the namespace '%s'.", releaseName, clusterID, namespace) +} diff --git a/internal/services/kubocd.go b/internal/services/kubocd.go new file mode 100644 index 0000000..2e8c866 --- /dev/null +++ b/internal/services/kubocd.go @@ -0,0 +1,57 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package services + +import ( + "github.com/okdp/okdp-server/internal/integrations/k8s" + "github.com/okdp/okdp-server/internal/model" +) + +type KuboCDService struct { + kubocd *k8s.K8S +} + +func NewKuboCDService() *KuboCDService { + return &KuboCDService{ + kubocd: k8s.NewK8S(), + } +} + +func (s KuboCDService) ListReleases(clusterID string, namespace string) ([]*model.Release, *model.ServerResponse) { + return s.kubocd.ListReleases(clusterID, namespace) + +} + +func (s KuboCDService) GetRelease(clusterID string, namespace string, releaseName string) (*model.Release, *model.ServerResponse) { + return s.kubocd.GetRelease(clusterID, namespace, releaseName) +} + +func (s KuboCDService) GetReleaseStatus(clusterID string, namespace string, releaseName string) (*model.ReleaseStatus, *model.ServerResponse) { + return s.kubocd.GetReleaseStatus(clusterID, namespace, releaseName) +} + +func (s KuboCDService) CreateRelease(clusterID string, namespace string, release *model.Release, dryRun bool) *model.ServerResponse { + return s.kubocd.CreateRelease(clusterID, namespace, release, dryRun) +} + +func (s KuboCDService) UpdateRelease(clusterID string, namespace string, release *model.Release, dryRun bool) *model.ServerResponse { + return s.kubocd.UpdateRelease(clusterID, namespace, release, dryRun) +} + +func (s KuboCDService) DeleteRelease(clusterID string, namespace string, releaseName string) *model.ServerResponse { + return s.kubocd.DeleteRelease(clusterID, namespace, releaseName) +} From 34bf936e89cbb63e6712e81c1efaee81dc57d151 Mon Sep 17 00:00:00 2001 From: iizitounene Date: Wed, 14 May 2025 17:34:43 +0200 Subject: [PATCH 07/14] feat: implement git repo interactions --- .../_api/repositories/repositories-server.go | 913 ++++++++++++++++++ api/openapi/v3/definition/GitRepository.yaml | 30 + api/openapi/v3/definition/Package.yaml | 2 +- api/openapi/v3/definition/Release.yaml | 281 ++++++ api/openapi/v3/definition/ReleaseInfo.yaml | 35 + api/openapi/v3/definition/ServerResponse.yaml | 32 + .../paths/repositories/release-by-name.yaml | 99 ++ .../v3/paths/repositories/releases.yaml | 153 +++ .../v3/paths/repositories/repo-by-name.yaml | 42 + .../v3/paths/repositories/repo-list.yaml | 37 + internal/controllers/git_controller.go | 150 +++ internal/integrations/git/client/client.go | 129 ++- internal/integrations/git/client/common.go | 149 +++ internal/integrations/git/git_repo.go | 89 ++ internal/model/git.go | 78 ++ internal/services/git.go | 157 +++ 16 files changed, 2374 insertions(+), 2 deletions(-) create mode 100644 api/openapi/v3/_api/repositories/repositories-server.go create mode 100644 api/openapi/v3/definition/GitRepository.yaml create mode 100644 api/openapi/v3/definition/Release.yaml create mode 100644 api/openapi/v3/definition/ReleaseInfo.yaml create mode 100644 api/openapi/v3/definition/ServerResponse.yaml create mode 100644 api/openapi/v3/paths/repositories/release-by-name.yaml create mode 100644 api/openapi/v3/paths/repositories/releases.yaml create mode 100644 api/openapi/v3/paths/repositories/repo-by-name.yaml create mode 100644 api/openapi/v3/paths/repositories/repo-list.yaml create mode 100644 internal/controllers/git_controller.go create mode 100644 internal/integrations/git/client/common.go create mode 100644 internal/model/git.go create mode 100644 internal/services/git.go diff --git a/api/openapi/v3/_api/repositories/repositories-server.go b/api/openapi/v3/_api/repositories/repositories-server.go new file mode 100644 index 0000000..efa48a6 --- /dev/null +++ b/api/openapi/v3/_api/repositories/repositories-server.go @@ -0,0 +1,913 @@ +// Package _repositories provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. +package _repositories + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/oapi-codegen/runtime" +) + +// Defines values for CreateGitReleaseJSONBodySpecPackageProvider. +const ( + CreateGitReleaseJSONBodySpecPackageProviderAws CreateGitReleaseJSONBodySpecPackageProvider = "aws" + CreateGitReleaseJSONBodySpecPackageProviderAzure CreateGitReleaseJSONBodySpecPackageProvider = "azure" + CreateGitReleaseJSONBodySpecPackageProviderGcp CreateGitReleaseJSONBodySpecPackageProvider = "gcp" + CreateGitReleaseJSONBodySpecPackageProviderGeneric CreateGitReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for CreateGitReleaseJSONBodySpecPackageVerifyProvider. +const ( + CreateGitReleaseJSONBodySpecPackageVerifyProviderCosign CreateGitReleaseJSONBodySpecPackageVerifyProvider = "cosign" + CreateGitReleaseJSONBodySpecPackageVerifyProviderNotation CreateGitReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// Defines values for UpdateGitReleaseJSONBodySpecPackageProvider. +const ( + UpdateGitReleaseJSONBodySpecPackageProviderAws UpdateGitReleaseJSONBodySpecPackageProvider = "aws" + UpdateGitReleaseJSONBodySpecPackageProviderAzure UpdateGitReleaseJSONBodySpecPackageProvider = "azure" + UpdateGitReleaseJSONBodySpecPackageProviderGcp UpdateGitReleaseJSONBodySpecPackageProvider = "gcp" + UpdateGitReleaseJSONBodySpecPackageProviderGeneric UpdateGitReleaseJSONBodySpecPackageProvider = "generic" +) + +// Defines values for UpdateGitReleaseJSONBodySpecPackageVerifyProvider. +const ( + UpdateGitReleaseJSONBodySpecPackageVerifyProviderCosign UpdateGitReleaseJSONBodySpecPackageVerifyProvider = "cosign" + UpdateGitReleaseJSONBodySpecPackageVerifyProviderNotation UpdateGitReleaseJSONBodySpecPackageVerifyProvider = "notation" +) + +// CreateGitReleaseJSONBody defines parameters for CreateGitRelease. +type CreateGitReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *CreateGitReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider CreateGitReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// CreateGitReleaseJSONBodySpecPackageProvider defines parameters for CreateGitRelease. +type CreateGitReleaseJSONBodySpecPackageProvider string + +// CreateGitReleaseJSONBodySpecPackageVerifyProvider defines parameters for CreateGitRelease. +type CreateGitReleaseJSONBodySpecPackageVerifyProvider string + +// UpdateGitReleaseJSONBody defines parameters for UpdateGitRelease. +type UpdateGitReleaseJSONBody struct { + // ApiVersion APIVersion defines the versioned schema of this representation of an object. + // Servers should convert recognized schemas to the latest internal value, and + // may reject unrecognized values. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + ApiVersion *string `json:"apiVersion,omitempty"` + + // Kind Kind is a string value representing the REST resource this object represents. + // Servers may infer this from the endpoint the client submits requests to. + // Cannot be updated. + // In CamelCase. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind *string `json:"kind,omitempty"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + + // Spec ReleaseSpec defines the desired state of Release. + Spec *struct { + // Contexts To provide contextual variables + // Refer to Context resource description for some explanation + // Contexts are merged in the following order: + // - The global default one (defined in Config) + // - The namespace context (A context with a specific name, defined in config, present in the release namespace) + // - This ordered list + // Default: [] + Contexts *[]struct { + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + } `json:"contexts,omitempty"` + + // CreateNamespace If true, add { install: { createNamespace: true } } to config map. + // Must be set, as used in module.Render() + // Default: false + CreateNamespace *bool `json:"createNamespace,omitempty"` + + // Debug Group a set of parameters useful for debugging Release and Package + Debug *struct { + // DumpContext DumpContext instruct to save a representation of the context + // in the Status. This for user debugging? + DumpContext *bool `json:"dumpContext,omitempty"` + + // DumpParameters DumpParameters instruct to save a representation of the parameters + // in the Status. This for user debugging? + DumpParameters *bool `json:"dumpParameters,omitempty"` + } `json:"debug,omitempty"` + + // Dependencies The roles we depend on. (appended to the one of the underlying package) + // Default: [] + Dependencies *[]string `json:"dependencies,omitempty"` + + // Description Short description of this release. Single line only + Description *string `json:"description,omitempty"` + + // Package The package to deploy + Package struct { + // CertSecretRef CertSecretRef can be given the name of a Secret containing + // either or both of + // + // - a PEM-encoded client certificate (`tls.crt`) and private + // key (`tls.key`); + // - a PEM-encoded CA certificate (`ca.crt`) + // + // and whichever are supplied, will be used for connecting to the + // registry. The client cert and key are useful if you are + // authenticating with a certificate; the CA cert is useful if + // you are using a self-signed server certificate. The Secret must + // be of type `Opaque` or `kubernetes.io/tls`. + // + // Note: Support for the `caFile`, `certFile` and `keyFile` keys have + // been deprecated. + CertSecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"certSecretRef,omitempty"` + + // Ignore Ignore overrides the set of excluded patterns in the .sourceignore format + // (which is the same as .gitignore). If not provided, a default will be used, + // consult the documentation for your version to find out what those are. + Ignore *string `json:"ignore,omitempty"` + + // Insecure Insecure allows connecting to a non-TLS HTTP container registry. + Insecure *bool `json:"insecure,omitempty"` + + // Interval Interval at which the OCIRepository URL is checked for updates. + // This interval is approximate and may be subject to jitter to ensure + // efficient use of resources. + Interval string `json:"interval"` + + // Provider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + // All following fields will be replicated in this object + // The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + // When not specified, defaults to 'generic'. + // -kubebuilder:default:=generic + Provider *UpdateGitReleaseJSONBodySpecPackageProvider `json:"provider,omitempty"` + + // ProxySecretRef ProxySecretRef specifies the Secret containing the proxy configuration + // to use while communicating with the container registry. + ProxySecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"proxySecretRef,omitempty"` + + // Repository Part of OCI url oci://: + Repository string `json:"repository"` + + // SecretRef SecretRef contains the secret name containing the registry login + // credentials to resolve image metadata. + // The secret must be of type kubernetes.io/dockerconfigjson. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + + // ServiceAccountName ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + // the image pull if the service account has attached pull secrets. For more information: + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + + // Suspend This flag tells the controller to suspend the reconciliation of this source. + Suspend *bool `json:"suspend,omitempty"` + + // Tag Part of OCI url oci://: + Tag string `json:"tag"` + + // Timeout The timeout for remote OCI Repository operations like pulling, defaults to 60s. + Timeout *string `json:"timeout,omitempty"` + + // Verify Verify contains the secret name containing the trusted public keys + // used to verify the signature and specifies which provider to use to check + // whether OCI image is authentic. + Verify *struct { + // MatchOIDCIdentity MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + MatchOIDCIdentity *[]struct { + // Issuer Issuer specifies the regex pattern to match against to verify + // the OIDC issuer in the Fulcio certificate. The pattern must be a + // valid Go regular expression. + Issuer string `json:"issuer"` + + // Subject Subject specifies the regex pattern to match against to verify + // the identity subject in the Fulcio certificate. The pattern must + // be a valid Go regular expression. + Subject string `json:"subject"` + } `json:"matchOIDCIdentity,omitempty"` + + // Provider Provider specifies the technology used to sign the OCI Artifact. + Provider UpdateGitReleaseJSONBodySpecPackageVerifyProvider `json:"provider"` + + // SecretRef SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + SecretRef *struct { + // Name Name of the referent. + Name string `json:"name"` + } `json:"secretRef,omitempty"` + } `json:"verify,omitempty"` + } `json:"package"` + + // Parameters The Release configuration variables + Parameters *interface{} `json:"parameters,omitempty"` + + // Protected If true, the webhook will prevent deletion + // Default: false + Protected *bool `json:"protected,omitempty"` + + // Roles List of roles fulfilled by this release. (appended to the one of the underlying package) + // Default: [] + Roles *[]string `json:"roles,omitempty"` + + // SkipDefaultContext If yes, the default context(s) of the configs are not taken in account + // ,Default: false + SkipDefaultContext *bool `json:"skipDefaultContext,omitempty"` + + // SpecPatchByModule Allow to patch the HelmRelease.spec for each module + SpecPatchByModule *map[string]interface{} `json:"specPatchByModule,omitempty"` + + // Suspended If true, HelmRelease update is suspended at KuboCD level + // (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + // Default: false + Suspended *bool `json:"suspended,omitempty"` + + // TargetNamespace The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + // Not required, as it can be setup another way, depending on the package + // (i.e. the package has a fixed namespace, or several ones). + // Default: Release.metadata.namespace + TargetNamespace *string `json:"targetNamespace,omitempty"` + } `json:"spec,omitempty"` + + // Status Release is the Schema for the releases API. + Status *struct { + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) + Status *struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies []string `json:"dependencies"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency string `json:"missingDependency"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase string `json:"phase"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected string `json:"printProtected"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected bool `json:"protected"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases string `json:"readyReleases"` + + // Roles The result of the package template and release value + Roles []string `json:"roles"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` + } `json:"status,omitempty"` + } `json:"status,omitempty"` +} + +// UpdateGitReleaseJSONBodySpecPackageProvider defines parameters for UpdateGitRelease. +type UpdateGitReleaseJSONBodySpecPackageProvider string + +// UpdateGitReleaseJSONBodySpecPackageVerifyProvider defines parameters for UpdateGitRelease. +type UpdateGitReleaseJSONBodySpecPackageVerifyProvider string + +// CreateGitReleaseJSONRequestBody defines body for CreateGitRelease for application/json ContentType. +type CreateGitReleaseJSONRequestBody CreateGitReleaseJSONBody + +// UpdateGitReleaseJSONRequestBody defines body for UpdateGitRelease for application/json ContentType. +type UpdateGitReleaseJSONRequestBody UpdateGitReleaseJSONBody + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // List all configured git repositories + // (GET /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations) + ListGitRepos(c *gin.Context, clusterId string, namespace string) + // Return a git repo details + // (GET /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}) + GetGitRepo(c *gin.Context, clusterId string, namespace string, kustomizationName string) + // Return list of releases in the git repo + // (GET /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases) + ListGitReleases(c *gin.Context, clusterId string, namespace string, kustomizationName string) + // Create a new KuboCD release in the git repo + // (POST /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases) + CreateGitRelease(c *gin.Context, clusterId string, namespace string, kustomizationName string) + // Update an existing KuboCD release in the git repo + // (PUT /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases) + UpdateGitRelease(c *gin.Context, clusterId string, namespace string, kustomizationName string) + // Delete KuboCD release by name in the git repo + // (DELETE /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases/{releaseName}) + DeleteGitRelease(c *gin.Context, clusterId string, namespace string, kustomizationName string, releaseName string) + // Return KuboCD release by name in the git repo + // (GET /clusters/{clusterId}/namespaces/{namespace}/gitkustomizations/{kustomizationName}/releases/{releaseName}) + GetGitRelease(c *gin.Context, clusterId string, namespace string, kustomizationName string, releaseName string) +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +type MiddlewareFunc func(c *gin.Context) + +// ListGitRepos operation middleware +func (siw *ServerInterfaceWrapper) ListGitRepos(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.ListGitRepos(c, clusterId, namespace) +} + +// GetGitRepo operation middleware +func (siw *ServerInterfaceWrapper) GetGitRepo(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "kustomizationName" ------------- + var kustomizationName string + + err = runtime.BindStyledParameterWithOptions("simple", "kustomizationName", c.Param("kustomizationName"), &kustomizationName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kustomizationName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetGitRepo(c, clusterId, namespace, kustomizationName) +} + +// ListGitReleases operation middleware +func (siw *ServerInterfaceWrapper) ListGitReleases(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "kustomizationName" ------------- + var kustomizationName string + + err = runtime.BindStyledParameterWithOptions("simple", "kustomizationName", c.Param("kustomizationName"), &kustomizationName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kustomizationName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.ListGitReleases(c, clusterId, namespace, kustomizationName) +} + +// CreateGitRelease operation middleware +func (siw *ServerInterfaceWrapper) CreateGitRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "kustomizationName" ------------- + var kustomizationName string + + err = runtime.BindStyledParameterWithOptions("simple", "kustomizationName", c.Param("kustomizationName"), &kustomizationName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kustomizationName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.CreateGitRelease(c, clusterId, namespace, kustomizationName) +} + +// UpdateGitRelease operation middleware +func (siw *ServerInterfaceWrapper) UpdateGitRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "kustomizationName" ------------- + var kustomizationName string + + err = runtime.BindStyledParameterWithOptions("simple", "kustomizationName", c.Param("kustomizationName"), &kustomizationName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kustomizationName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.UpdateGitRelease(c, clusterId, namespace, kustomizationName) +} + +// DeleteGitRelease operation middleware +func (siw *ServerInterfaceWrapper) DeleteGitRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "kustomizationName" ------------- + var kustomizationName string + + err = runtime.BindStyledParameterWithOptions("simple", "kustomizationName", c.Param("kustomizationName"), &kustomizationName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kustomizationName: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "releaseName" ------------- + var releaseName string + + err = runtime.BindStyledParameterWithOptions("simple", "releaseName", c.Param("releaseName"), &releaseName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter releaseName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.DeleteGitRelease(c, clusterId, namespace, kustomizationName, releaseName) +} + +// GetGitRelease operation middleware +func (siw *ServerInterfaceWrapper) GetGitRelease(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "namespace" ------------- + var namespace string + + err = runtime.BindStyledParameterWithOptions("simple", "namespace", c.Param("namespace"), &namespace, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter namespace: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "kustomizationName" ------------- + var kustomizationName string + + err = runtime.BindStyledParameterWithOptions("simple", "kustomizationName", c.Param("kustomizationName"), &kustomizationName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter kustomizationName: %w", err), http.StatusBadRequest) + return + } + + // ------------- Path parameter "releaseName" ------------- + var releaseName string + + err = runtime.BindStyledParameterWithOptions("simple", "releaseName", c.Param("releaseName"), &releaseName, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter releaseName: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.GetGitRelease(c, clusterId, namespace, kustomizationName, releaseName) +} + +// GinServerOptions provides options for the Gin server. +type GinServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router gin.IRouter, si ServerInterface) { + RegisterHandlersWithOptions(router, si, GinServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { + errorHandler := options.ErrorHandler + if errorHandler == nil { + errorHandler = func(c *gin.Context, err error, statusCode int) { + c.JSON(statusCode, gin.H{"msg": err.Error()}) + } + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + HandlerMiddlewares: options.Middlewares, + ErrorHandler: errorHandler, + } + + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations", wrapper.ListGitRepos) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations/:kustomizationName", wrapper.GetGitRepo) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations/:kustomizationName/releases", wrapper.ListGitReleases) + router.POST(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations/:kustomizationName/releases", wrapper.CreateGitRelease) + router.PUT(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations/:kustomizationName/releases", wrapper.UpdateGitRelease) + router.DELETE(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations/:kustomizationName/releases/:releaseName", wrapper.DeleteGitRelease) + router.GET(options.BaseURL+"/clusters/:clusterId/namespaces/:namespace/gitkustomizations/:kustomizationName/releases/:releaseName", wrapper.GetGitRelease) +} diff --git a/api/openapi/v3/definition/GitRepository.yaml b/api/openapi/v3/definition/GitRepository.yaml new file mode 100644 index 0000000..de3bb1c --- /dev/null +++ b/api/openapi/v3/definition/GitRepository.yaml @@ -0,0 +1,30 @@ +type: object +xml: + name: GitRepository +required: +- "repoUrl" +- "ref" +- "name" +- "namespace" +- "path" +- "credentials" +properties: + repoUrl: + type: string + format: uri + x-go-name: repoURL + ref: + type: string + name: + type: string + namespace: + type: string + path: + type: string + credentials: + type: object + required: + - "secretRef" + properties: + secretRef: + type: string diff --git a/api/openapi/v3/definition/Package.yaml b/api/openapi/v3/definition/Package.yaml index 58cd8a5..7132cdb 100644 --- a/api/openapi/v3/definition/Package.yaml +++ b/api/openapi/v3/definition/Package.yaml @@ -1,6 +1,6 @@ type: object xml: - name: package + name: Package required: - "name" - "versions" diff --git a/api/openapi/v3/definition/Release.yaml b/api/openapi/v3/definition/Release.yaml new file mode 100644 index 0000000..c6b3b4e --- /dev/null +++ b/api/openapi/v3/definition/Release.yaml @@ -0,0 +1,281 @@ +# controller-gen crd paths=./api/v1alpha1 output:crd:dir=./api/schema +description: Release is the Schema for the releases API. +properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ReleaseSpec defines the desired state of Release. + properties: + contexts: + description: |- + To provide contextual variables + Refer to Context resource description for some explanation + Contexts are merged in the following order: + - The global default one (defined in Config) + - The namespace context (A context with a specific name, defined in config, present in the release namespace) + - This ordered list + Default: [] + items: + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + type: array + createNamespace: + description: |- + If true, add { install: { createNamespace: true } } to config map. + Must be set, as used in module.Render() + Default: false + type: boolean + debug: + description: Group a set of parameters useful for debugging Release + and Package + properties: + dumpContext: + description: |- + DumpContext instruct to save a representation of the context + in the Status. This for user debugging? + type: boolean + dumpParameters: + description: |- + DumpParameters instruct to save a representation of the parameters + in the Status. This for user debugging? + type: boolean + type: object + dependencies: + description: |- + The roles we depend on. (appended to the one of the underlying package) + Default: [] + items: + type: string + type: array + description: + description: Short description of this release. Single line only + type: string + package: + description: The package to deploy + properties: + certSecretRef: + description: |- + CertSecretRef can be given the name of a Secret containing + either or both of + + - a PEM-encoded client certificate (`tls.crt`) and private + key (`tls.key`); + - a PEM-encoded CA certificate (`ca.crt`) + + and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are + authenticating with a certificate; the CA cert is useful if + you are using a self-signed server certificate. The Secret must + be of type `Opaque` or `kubernetes.io/tls`. + + Note: Support for the `caFile`, `certFile` and `keyFile` keys have + been deprecated. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + ignore: + description: |- + Ignore overrides the set of excluded patterns in the .sourceignore format + (which is the same as .gitignore). If not provided, a default will be used, + consult the documentation for your version to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS HTTP container + registry. + type: boolean + interval: + default: 5m + description: |- + Interval at which the OCIRepository URL is checked for updates. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + provider: + description: |- + The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator + All following fields will be replicated in this object + The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + When not specified, defaults to 'generic'. + -kubebuilder:default:=generic + enum: + - generic + - aws + - azure + - gcp + type: string + proxySecretRef: + description: |- + ProxySecretRef specifies the Secret containing the proxy configuration + to use while communicating with the container registry. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + repository: + description: Part of OCI url oci://: + type: string + secretRef: + description: |- + SecretRef contains the secret name containing the registry login + credentials to resolve image metadata. + The secret must be of type kubernetes.io/dockerconfigjson. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + the image pull if the service account has attached pull secrets. For more information: + https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + type: string + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + tag: + description: Part of OCI url oci://: + type: string + timeout: + default: 60s + description: The timeout for remote OCI Repository operations + like pulling, defaults to 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + verify: + description: |- + Verify contains the secret name containing the trusted public keys + used to verify the signature and specifies which provider to use to check + whether OCI image is authentic. + properties: + matchOIDCIdentity: + description: |- + MatchOIDCIdentity specifies the identity matching criteria to use + while verifying an OCI artifact which was signed using Cosign keyless + signing. The artifact's identity is deemed to be verified if any of the + specified matchers match against the identity. + items: + description: |- + OIDCIdentityMatch specifies options for verifying the certificate identity, + i.e. the issuer and the subject of the certificate. + properties: + issuer: + description: |- + Issuer specifies the regex pattern to match against to verify + the OIDC issuer in the Fulcio certificate. The pattern must be a + valid Go regular expression. + type: string + subject: + description: |- + Subject specifies the regex pattern to match against to verify + the identity subject in the Fulcio certificate. The pattern must + be a valid Go regular expression. + type: string + required: + - issuer + - subject + type: object + type: array + provider: + default: cosign + description: Provider specifies the technology used to sign + the OCI Artifact. + enum: + - cosign + - notation + type: string + secretRef: + description: |- + SecretRef specifies the Kubernetes Secret containing the + trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + required: + - interval + - repository + - tag + type: object + parameters: + description: The Release configuration variables + x-kubernetes-preserve-unknown-fields: true + protected: + description: |- + If true, the webhook will prevent deletion + Default: false + type: boolean + roles: + description: |- + List of roles fulfilled by this release. (appended to the one of the underlying package) + Default: [] + items: + type: string + type: array + skipDefaultContext: + description: |- + If yes, the default context(s) of the configs are not taken in account + ,Default: false + type: boolean + specPatchByModule: + additionalProperties: + x-kubernetes-preserve-unknown-fields: true + description: Allow to patch the HelmRelease.spec for each module + type: object + suspended: + description: |- + If true, HelmRelease update is suspended at KuboCD level + (This is NOT the helmRelease.spec.suspend flag, which may be set by Config part) + Default: false + type: boolean + targetNamespace: + description: |- + The namespace to deploy in. (May also be a partial name for a multi-namespaces package) + Not required, as it can be setup another way, depending on the package + (i.e. the package has a fixed namespace, or several ones). + Default: Release.metadata.namespace + type: string + required: + - package + type: object + status: + $ref: './ReleaseStatus.yaml' +type: object diff --git a/api/openapi/v3/definition/ReleaseInfo.yaml b/api/openapi/v3/definition/ReleaseInfo.yaml new file mode 100644 index 0000000..4443caf --- /dev/null +++ b/api/openapi/v3/definition/ReleaseInfo.yaml @@ -0,0 +1,35 @@ +type: object +xml: + name: ReleaseInfo +required: +- "name" +- "package" +- "git" +properties: + name: + type: string + namespace: + type: string + description: + type: string + package: + type: object + required: + - "repository" + - "tag" + properties: + repository: + type: string + tag: + type: string + git: + type: object + required: + - "path" + - "url" + properties: + path: + type: string + url: + type: string + x-go-name: URL diff --git a/api/openapi/v3/definition/ServerResponse.yaml b/api/openapi/v3/definition/ServerResponse.yaml new file mode 100644 index 0000000..e6e126f --- /dev/null +++ b/api/openapi/v3/definition/ServerResponse.yaml @@ -0,0 +1,32 @@ +type: object +xml: + name: ServerResponse +required: + - message + - status + - type +properties: + message: + type: string + description: The response message from the server + status: + type: integer + description: The HTTP status code + type: + type: string + enum: + - okdp_server + - registry + - git_repo + - k8s_cluster + description: The type of the server response +ServerResponseType: + type: string + enum: + - okdp_server + - registry + - git_repo + - k8s_cluster + description: An enum representing different server response types + + diff --git a/api/openapi/v3/paths/repositories/release-by-name.yaml b/api/openapi/v3/paths/repositories/release-by-name.yaml new file mode 100644 index 0000000..3eeb936 --- /dev/null +++ b/api/openapi/v3/paths/repositories/release-by-name.yaml @@ -0,0 +1,99 @@ +get: + summary: Return KuboCD release by name in the git repo + description: | + Return KuboCD release by name in the git repo + tags: + - repositories + operationId: GetGitRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + - in: path + name: kustomizationName + schema: + type: string + required: true + description: Kubernetes fluxcd git repo name + example: releases-system + - in: path + name: releaseName + schema: + type: string + required: true + description: KuboCD release name + example: podinfo + responses: + '200': + description: KuboCD Release info + content: + application/json: + schema: + $ref: '../../definition/Release.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + +delete: + summary: Delete KuboCD release by name in the git repo + description: | + Delete KuboCD release by name in the git repo + tags: + - repositories + operationId: DeleteGitRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + - in: path + name: kustomizationName + schema: + type: string + required: true + description: Kubernetes fluxcd git repo name + example: releases-system + - in: path + name: releaseName + schema: + type: string + required: true + description: KuboCD release name + example: podinfo + responses: + '200': + description: KuboCD Release deleted successfully + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' \ No newline at end of file diff --git a/api/openapi/v3/paths/repositories/releases.yaml b/api/openapi/v3/paths/repositories/releases.yaml new file mode 100644 index 0000000..2e700a3 --- /dev/null +++ b/api/openapi/v3/paths/repositories/releases.yaml @@ -0,0 +1,153 @@ +get: + summary: Return list of releases in the git repo + description: | + Return list of releases in the git repo + tags: + - repositories + operationId: ListGitReleases + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + - in: path + name: kustomizationName + schema: + type: string + required: true + description: Kubernetes fluxcd git repo name + example: releases-system + responses: + '200': + description: Release list + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/ReleaseInfo.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + + +post: + summary: Create a new KuboCD release in the git repo + description: | + Create a new KuboCD release in the git repo + tags: + - repositories + operationId: CreateGitRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + - in: path + name: kustomizationName + schema: + type: string + required: true + description: Kubernetes fluxcd git repo name + example: releases-system + requestBody: + description: Release object to be created + required: true + content: + application/json: + schema: + $ref: '../../definition/Release.yaml' + responses: + '201': + description: Release created successfully + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/ServerResponse.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + +put: + summary: Update an existing KuboCD release in the git repo + description: | + Update an existing KuboCD release in the git repo + tags: + - repositories + operationId: UpdateGitRelease + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + - in: path + name: kustomizationName + schema: + type: string + required: true + description: Kubernetes fluxcd git repo name + example: releases-system + requestBody: + description: Release object to be updated + required: true + content: + application/json: + schema: + $ref: '../../definition/Release.yaml' + responses: + '200': + description: Release updated successfully + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/ServerResponse.yaml' + + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + + + + \ No newline at end of file diff --git a/api/openapi/v3/paths/repositories/repo-by-name.yaml b/api/openapi/v3/paths/repositories/repo-by-name.yaml new file mode 100644 index 0000000..fb8b144 --- /dev/null +++ b/api/openapi/v3/paths/repositories/repo-by-name.yaml @@ -0,0 +1,42 @@ +get: + summary: Return a git repo details + description: | + Return a git repo details + tags: + - repositories + operationId: GetGitRepo + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + - in: path + name: kustomizationName + schema: + type: string + required: true + description: Kubernetes fluxcd git repo name + example: podinfo + responses: + '200': + description: Git repo information + content: + application/json: + schema: + $ref: '../../definition/GitRepository.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/api/openapi/v3/paths/repositories/repo-list.yaml b/api/openapi/v3/paths/repositories/repo-list.yaml new file mode 100644 index 0000000..430891e --- /dev/null +++ b/api/openapi/v3/paths/repositories/repo-list.yaml @@ -0,0 +1,37 @@ +get: + summary: List all configured git repositories + description: | + List all configured git repositories + tags: + - repositories + operationId: ListGitRepos + parameters: + - in: path + name: clusterId + schema: + type: string + required: true + description: Kubernetes cluster ID + - in: path + name: namespace + schema: + type: string + required: true + description: Kubernetes fluxcd git repo namespace + example: flux-system + responses: + '200': + description: List of the git repositories + content: + application/json: + schema: + type: array + items: + $ref: '../../definition/GitRepository.yaml' + default: + description: Server error + content: + application/json: + schema: + $ref: '../../definition/ServerResponse.yaml' + diff --git a/internal/controllers/git_controller.go b/internal/controllers/git_controller.go new file mode 100644 index 0000000..5ec4c1c --- /dev/null +++ b/internal/controllers/git_controller.go @@ -0,0 +1,150 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package controllers + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + log "github.com/okdp/okdp-server/internal/common/logging" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/services" +) + +type IGitRepoController struct { + gitRepoService *services.GitRepoService +} + +func GitRepoController() *IGitRepoController { + return &IGitRepoController{ + gitRepoService: services.NewGitRepoService(), + } +} + +func (r IGitRepoController) ListGitRepos(c *gin.Context, clusterID string, namespace string) { + gitRepos, err := r.gitRepoService.ListGitRepos(clusterID, namespace) + if err != nil { + log.Error("Unable to list Git repos on namespace '%s' with cluster ID '%s', details: %+v", namespace, clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, gitRepos) +} + +func (r IGitRepoController) GetGitRepo(c *gin.Context, clusterID string, namespace string, kustomizationName string) { + gitRepo, err := r.gitRepoService.GetGitRepo(clusterID, namespace, kustomizationName) + if err != nil { + log.Error("Unable to find Git repo '%s' on namespace '%s' with cluster id '%s', details: %+v", kustomizationName, namespace, clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, gitRepo) +} + +func (r IGitRepoController) ListGitReleases(c *gin.Context, clusterID string, namespace string, kustomizationName string) { + releasesInfo, err := r.gitRepoService.ListReleases(clusterID, namespace, kustomizationName) + if err != nil { + log.Error("Unable to get releases from Git repo '%s/%s' on cluster ID '%s', details: %+v", namespace, kustomizationName, clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, releasesInfo) +} + +func (r IGitRepoController) GetGitRelease(c *gin.Context, clusterID string, namespace string, kustomizationName string, releaseName string) { + release, err := r.gitRepoService.GetRelease(clusterID, namespace, kustomizationName, releaseName) + if err != nil { + log.Error("Unable to get release from Git repo '%s/%s' on cluster ID '%s', details: %+v", namespace, kustomizationName, clusterID, err) + c.JSON(err.Status, err) + return + } + c.JSON(http.StatusOK, release) +} + +func (r IGitRepoController) CreateGitRelease(c *gin.Context, clusterID string, namespace string, kustomizationName string) { + var release model.Release + userInfo, err := GetUserInfo(c) + if err != nil { + c.JSON(err.Status, err) + } + + if err := c.ShouldBindJSON(&release); err != nil { + resp := model.NewServerResponse(model.OkdpServerResponse).BadRequest("%+v", err.Error()) + c.JSON(resp.Status, resp) + return + } + + msg := fmt.Sprintf("Create new KuboCD release %s/%s on cluster id %s", namespace, release.Name, clusterID) + commitOpts := model.NewGitCommitOptions(msg). + Author(userInfo.Name). + Email(userInfo.Email) + resp, err := r.gitRepoService.CreateGitRelease(clusterID, namespace, kustomizationName, &release, commitOpts) + + if err != nil { + c.JSON(err.Status, err) + return + } + + c.JSON(http.StatusCreated, resp) + +} + +func (r IGitRepoController) UpdateGitRelease(c *gin.Context, clusterID string, namespace string, kustomizationName string) { + var release model.Release + userInfo, err := GetUserInfo(c) + if err != nil { + c.JSON(err.Status, err) + } + + if err := c.ShouldBindJSON(&release); err != nil { + resp := model.NewServerResponse(model.OkdpServerResponse).BadRequest("%+v", err.Error()) + c.JSON(resp.Status, resp) + return + } + + msg := fmt.Sprintf("Update KuboCD release %s/%s on cluster id %s", namespace, release.Name, clusterID) + commitOpts := model.NewGitCommitOptions(msg). + Author(userInfo.Name). + Email(userInfo.Email) + resp, err := r.gitRepoService.UpdateGitRelease(clusterID, namespace, kustomizationName, &release, commitOpts) + + if err != nil { + c.JSON(err.Status, err) + return + } + + c.JSON(http.StatusOK, resp) +} + +func (r IGitRepoController) DeleteGitRelease(c *gin.Context, clusterID string, namespace string, kustomizationName string, releaseName string) { + + userInfo, err := GetUserInfo(c) + if err != nil { + c.JSON(err.Status, err) + } + + msg := fmt.Sprintf("Delete KuboCD release %s/%s on cluster id %s", namespace, releaseName, clusterID) + commitOpts := model.NewGitCommitOptions(msg). + Author(userInfo.Name). + Email(userInfo.Email) + + resp := r.gitRepoService.DeleteGitRelease(clusterID, namespace, kustomizationName, releaseName, commitOpts) + + c.JSON(http.StatusOK, resp) + +} diff --git a/internal/integrations/git/client/client.go b/internal/integrations/git/client/client.go index 24d20b3..c3526ff 100644 --- a/internal/integrations/git/client/client.go +++ b/internal/integrations/git/client/client.go @@ -14,4 +14,131 @@ * limitations under the License. */ -package git +package client + +import ( + "github.com/go-git/go-billy/v5/memfs" + git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/transport" + "github.com/go-git/go-git/v5/storage/memory" + + log "github.com/okdp/okdp-server/internal/common/logging" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/utils" +) + +type LocalRepo struct { + *git.Repository + *git.Worktree +} + +func NewLocalRepo(url string, ref string, auth transport.AuthMethod) (*LocalRepo, *model.ServerResponse) { + + fs := memfs.New() + repo, er := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{ + URL: url, + Auth: auth, + Depth: 1, + Progress: nil, + SingleBranch: true, + ReferenceName: plumbing.ReferenceName(ref), + }) + + if er != nil { + return nil, model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity(er.Error()) + } + worktree, err := repo.Worktree() + if err != nil { + return nil, model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Unable to access local git repo filesystem %s, %s, details: %s", url, ref, err.Error()) + } + + return &LocalRepo{ + repo, worktree, + }, nil +} + +func DoReadContent(repo *model.GitRepository, auth transport.AuthMethod) ([]*model.GitContent, *model.ServerResponse) { + contents := []*model.GitContent{} + + localrepo, err := NewLocalRepo(repo.RepoURL, repo.Ref, auth) + if err != nil { + return nil, err + } + + fs := localrepo.Filesystem + + filePaths, err := ListFiles(fs, repo.Path) + if err != nil { + return nil, err + } + for _, filePath := range filePaths { + if !utils.IsYaml(filePath) { + log.Warn("Ignoring file '%s' in folder '%s': not a YAML file", filePath, repo.Path) + continue + } + content, err := ReadContent(fs, filePath) + if err != nil { + return nil, err + } + content.URL = repo.RepoURL + contents = append(contents, content) + } + + return contents, nil + +} + +func DoPushContent(repo *model.GitRepository, auth transport.AuthMethod, content string, commitOpts *model.GitCommit, path string) *model.ServerResponse { + localrepo, er := NewLocalRepo(repo.RepoURL, repo.Ref, auth) + if er != nil { + return er + } + + err := localrepo.CommitFile(content, path, commitOpts) + + if err != nil { + return model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Unable to commit file %s (%s/%s) => %s (%s), details: %s", path, repo.Namespace, repo.Name, repo.RepoURL, repo.Ref, err.Error()) + } + + err = localrepo.SafePush(auth) + + if err != nil && err != git.NoErrAlreadyUpToDate { + return model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Unable to push %s (%s/%s) => %s (%s), details: %s", path, repo.Namespace, repo.Name, repo.RepoURL, repo.Ref, err.Error()) + } + + return nil +} + +func DoDeleteFile(repo *model.GitRepository, auth transport.AuthMethod, commitOpts *model.GitCommit, path string) *model.ServerResponse { + localrepo, er := NewLocalRepo(repo.RepoURL, repo.Ref, auth) + if er != nil { + return er + } + + err := localrepo.DeleteFile(path, commitOpts) + + if err != nil { + return model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Unable to delete file %s (%s/%s) => %s (%s), details: %s", path, repo.Namespace, repo.Name, repo.RepoURL, repo.Ref, err.Error()) + } + + err = localrepo.SafePush(auth) + + if err != nil && err != git.NoErrAlreadyUpToDate { + return model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Unable to push %s (%s/%s) => %s (%s), details: %s", path, repo.Namespace, repo.Name, repo.RepoURL, repo.Ref, err.Error()) + } + + return model.NewServerResponse(model.OkdpServerResponse).Deleted("Release name %s successfully deleted", path) +} diff --git a/internal/integrations/git/client/common.go b/internal/integrations/git/client/common.go new file mode 100644 index 0000000..4570450 --- /dev/null +++ b/internal/integrations/git/client/common.go @@ -0,0 +1,149 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "io" + "path/filepath" + + "github.com/go-git/go-billy/v5" + git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/transport" + + "github.com/okdp/okdp-server/internal/model" +) + +func (r LocalRepo) SafePush(auth transport.AuthMethod) error { + + // err := r.Worktree.Pull(&git.PullOptions{ + // RemoteName: "origin", + // Auth: auth, + // }) + // if err != nil && err != git.NoErrAlreadyUpToDate { + // return err + // } + + err := r.Push(&git.PushOptions{ + Auth: auth, + }) + + if err != nil && err != git.NoErrAlreadyUpToDate { + return err + } + + return nil + +} + +func (r LocalRepo) CommitFile(content string, path string, commitOpts *model.GitCommit) error { + + fs := r.Worktree.Filesystem + + f, err := fs.Create(path) + if err != nil { + return err + } + defer f.Close() + + if _, err := f.Write([]byte(content)); err != nil { + return err + } + + _, err = r.Worktree.Add(path) + if err != nil { + return err + } + _, err = r.Worktree.Commit(commitOpts.Message, &commitOpts.CommitOptions) + + return err +} + +func (r LocalRepo) DeleteFile(path string, commitOpts *model.GitCommit) error { + + fs := r.Worktree.Filesystem + + if err := fs.Remove(path); err != nil { + return err + } + _, err := r.Worktree.Remove(path) + if err != nil { + return err + } + + _, err = r.Worktree.Commit(commitOpts.Message, &commitOpts.CommitOptions) + + return err +} + +func ListFiles(fs billy.Filesystem, folder string) ([]string, *model.ServerResponse) { + var fileNames []string + + var walk func(string) *model.ServerResponse + walk = func(currentPath string) *model.ServerResponse { + stat, err := fs.Stat(currentPath) + if err != nil || !stat.IsDir() { + return nil // Skip if not a directory or doesn't exist + } + + dirEntries, err := fs.ReadDir(currentPath) + if err != nil { + return model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Failed to read git folder %s: %s", currentPath, err.Error()) + } + + for _, entry := range dirEntries { + fullPath := filepath.Join(currentPath, entry.Name()) + if entry.IsDir() { + if walkErr := walk(fullPath); walkErr != nil { + return walkErr + } + } else { + fileNames = append(fileNames, fullPath) + } + } + return nil + } + + if err := walk(folder); err != nil { + return nil, err + } + + return fileNames, nil +} + +func ReadContent(fs billy.Filesystem, filePath string) (*model.GitContent, *model.ServerResponse) { + file, err := fs.Open(filePath) + if err != nil { + return nil, model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Failed to open file path %s", filePath, err.Error()) + } + + content, err := io.ReadAll(file) + + if err != nil { + return nil, model. + NewServerResponse(model.GitRepoResponse). + UnprocessableEntity("Failed to read file %s", filePath, err.Error()) + } + + return &model.GitContent{ + Content: &content, + Path: filePath, + }, nil +} diff --git a/internal/integrations/git/git_repo.go b/internal/integrations/git/git_repo.go index 24d20b3..5744295 100644 --- a/internal/integrations/git/git_repo.go +++ b/internal/integrations/git/git_repo.go @@ -15,3 +15,92 @@ */ package git + +import ( + "path/filepath" + + "github.com/okdp/okdp-server/internal/integrations/git/client" + k8sclient "github.com/okdp/okdp-server/internal/integrations/k8s/client" + "github.com/okdp/okdp-server/internal/model" + "github.com/okdp/okdp-server/internal/utils" +) + +type Repository struct { + *k8sclient.KubeClients +} + +func NewRepository() *Repository { + return &Repository{ + k8sclient.GetClients(), + } +} + +func (r Repository) ListGitRepos(clusterID string, namespace string) ([]*model.GitRepository, *model.ServerResponse) { + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return nil, err + } + return kubeClient.ListGitRepos(namespace) +} + +func (r Repository) GetGitRepo(clusterID string, namespace string, kustomizationName string) (*model.GitRepository, *model.ServerResponse) { + gitRepos, err := r.ListGitRepos(clusterID, namespace) + if err != nil { + return nil, err + } + + for _, repo := range gitRepos { + if repo.Name == kustomizationName { + return repo, nil + } + } + return nil, model.RepoNotFoundError(clusterID, namespace, kustomizationName) +} + +func (r Repository) GetContents(clusterID string, namespace string, kustomizationName string) ([]*model.GitContent, *model.ServerResponse) { + repo, err := r.GetGitRepo(clusterID, namespace, kustomizationName) + if err != nil { + return nil, err + } + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return nil, err + } + auth, err := kubeClient.GetAuthMethod(repo.Credentials.SecretRef, namespace) + if err != nil { + return nil, err + } + return client.DoReadContent(repo, auth) +} + +func (r Repository) Write(clusterID string, namespace string, kustomizationName string, content string, commitOpts *model.GitCommit, path string) *model.ServerResponse { + repo, err := r.GetGitRepo(clusterID, namespace, kustomizationName) + if err != nil { + return err + } + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return err + } + auth, err := kubeClient.GetAuthMethod(repo.Credentials.SecretRef, namespace) + if err != nil { + return err + } + return client.DoPushContent(repo, auth, content, commitOpts, utils.PathOrFallback(path, filepath.Join(repo.Path, path))) +} + +func (r Repository) DeleteFile(clusterID string, namespace string, kustomizationName string, commitOpts *model.GitCommit, path string) *model.ServerResponse { + repo, err := r.GetGitRepo(clusterID, namespace, kustomizationName) + if err != nil { + return err + } + kubeClient, err := r.GetClient(clusterID) + if err != nil { + return err + } + auth, err := kubeClient.GetAuthMethod(repo.Credentials.SecretRef, namespace) + if err != nil { + return err + } + return client.DoDeleteFile(repo, auth, commitOpts, path) +} diff --git a/internal/model/git.go b/internal/model/git.go new file mode 100644 index 0000000..e36529b --- /dev/null +++ b/internal/model/git.go @@ -0,0 +1,78 @@ +/* + * Copyright 2024 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package model + +import ( + "time" + + git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" + + "github.com/okdp/okdp-server/api/openapi/v3/_api" + "sigs.k8s.io/yaml" +) + +type GitRepository _api.GitRepository +type GitCommit struct { + Message string + git.CommitOptions +} +type GitContent struct { + Content *[]byte + Path string + URL string +} + +func (c GitContent) ToRelease() (*Release, *ServerResponse) { + var release Release + if err := yaml.Unmarshal(*c.Content, &release); err != nil { + return nil, NewServerResponse(GitRepoResponse). + UnprocessableEntity("Failed to convert yaml file content '%s' into KuboCD Release: %v", c.Path, err) + } + return &release, nil +} + +func RepoNotFoundError(clusterID string, namespace string, fluxrepo string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("The git repo %s not found on namespace %s with cluster id %s.", fluxrepo, namespace, clusterID) +} + +func KuboCDGitReleaseNotFoundError(clusterID string, namespace string, fluxrepo string, releaseName string) *ServerResponse { + return NewServerResponse(OkdpServerResponse). + NotFoundError("Unable to find KuboCD release '%s' in the git repo referenced by fluxcd repo %s/%s (clusterID: %s).", releaseName, namespace, fluxrepo, clusterID) +} + +func NewGitCommitOptions(message string) *GitCommit { + commit := &GitCommit{ + Message: "[okdp-server] " + message, + CommitOptions: git.CommitOptions{ + Author: &object.Signature{}, + }, + } + commit.CommitOptions.Author.When = time.Now() + return commit +} + +func (c *GitCommit) Author(name string) *GitCommit { + c.CommitOptions.Author.Name = name + return c +} + +func (c *GitCommit) Email(email string) *GitCommit { + c.CommitOptions.Author.Email = email + return c +} diff --git a/internal/services/git.go b/internal/services/git.go new file mode 100644 index 0000000..e5c0068 --- /dev/null +++ b/internal/services/git.go @@ -0,0 +1,157 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package services + +import ( + "github.com/okdp/okdp-server/internal/integrations/git" + "github.com/okdp/okdp-server/internal/model" +) + +type GitRepoService struct { + git *git.Repository +} + +func NewGitRepoService() *GitRepoService { + return &GitRepoService{ + git: git.NewRepository(), + } +} + +func (s GitRepoService) ListGitRepos(clusterID string, namespace string) ([]*model.GitRepository, *model.ServerResponse) { + return s.git.ListGitRepos(clusterID, namespace) +} + +func (s GitRepoService) GetGitRepo(clusterID string, namespace string, kustomizationName string) (*model.GitRepository, *model.ServerResponse) { + return s.git.GetGitRepo(clusterID, namespace, kustomizationName) +} + +func (s GitRepoService) ListReleases(clusterID string, namespace string, kustomizationName string) ([]*model.ReleaseInfo, *model.ServerResponse) { + contents, err := s.git.GetContents(clusterID, namespace, kustomizationName) + if err != nil { + return nil, err + } + return s.toReleaseInfo(contents) +} + +func (s GitRepoService) GetRelease(clusterID string, namespace string, kustomizationName string, releaseName string) (*model.Release, *model.ServerResponse) { + contents, err := s.git.GetContents(clusterID, namespace, kustomizationName) + if err != nil { + return nil, err + } + + for _, content := range contents { + release, err := content.ToRelease() + if err != nil { + return nil, err + } + + if release.ObjectMeta.Name == releaseName { + return release, nil + } + } + + return nil, model.KuboCDGitReleaseNotFoundError(clusterID, namespace, kustomizationName, releaseName) +} + +func (s GitRepoService) CreateGitRelease(clusterID string, namespace string, kustomizationName string, release *model.Release, commitOpts *model.GitCommit) (*model.Release, *model.ServerResponse) { + releaseInfo, er := s.getReleaseInfo(clusterID, namespace, kustomizationName, release.Namespace, release.Name) + if er != nil { + return nil, er + } + if releaseInfo == nil { + content, err := release.SanitizeMetadata().SanitizeStatus().ToYAML() + if err != nil { + return nil, model. + NewServerResponse(model.OkdpServerResponse). + UnprocessableEntity("Unable to convert KuboCD release %s/%s into yaml", release.Namespace, release.Name) + } + return release, s.git.Write(clusterID, namespace, kustomizationName, content, commitOpts, release.Name+".yaml") + } + + return nil, model.NewServerResponse(model.OkdpServerResponse).ConflictError("Release '%s' already exists in the git repo %s (%s)", release.Name, releaseInfo.Git.Path, releaseInfo.Git.URL) +} + +func (s GitRepoService) UpdateGitRelease(clusterID string, namespace string, kustomizationName string, release *model.Release, commitOpts *model.GitCommit) (*model.Release, *model.ServerResponse) { + releaseInfo, er := s.getReleaseInfo(clusterID, namespace, kustomizationName, release.Namespace, release.Name) + if er != nil { + return nil, er + } + if releaseInfo == nil { + return nil, model.NewServerResponse(model.OkdpServerResponse).NotFoundError("Release '%s' does not exist in the git repo", release.Name) + } + + content, err := release.SanitizeMetadata().SanitizeStatus().ToYAML() + if err != nil { + return nil, model. + NewServerResponse(model.OkdpServerResponse). + UnprocessableEntity("Unable to convert KuboCD release %s/%s into yaml", release.Namespace, release.Name) + } + + return release, s.git.Write(clusterID, namespace, kustomizationName, content, commitOpts, releaseInfo.Git.Path) +} + +func (s GitRepoService) DeleteGitRelease(clusterID string, namespace string, kustomizationName string, releaseName string, commitOpts *model.GitCommit) *model.ServerResponse { + releaseInfo, er := s.getReleaseInfo(clusterID, namespace, kustomizationName, "default", releaseName) + if er != nil { + return er + } + if *releaseInfo == (model.ReleaseInfo{}) { + return model.NewServerResponse(model.OkdpServerResponse).NotFoundError("Release '%s' does not exist in the git repo", releaseName) + } + + return s.git.DeleteFile(clusterID, namespace, kustomizationName, commitOpts, releaseInfo.Git.Path) +} + +func (s GitRepoService) toReleaseInfo(contents []*model.GitContent) ([]*model.ReleaseInfo, *model.ServerResponse) { + releasesInfo := []*model.ReleaseInfo{} + for _, content := range contents { + release, err := content.ToRelease() + if err != nil { + return nil, err + } + + name := release.ObjectMeta.Name + namespace := release.ObjectMeta.Namespace + releaseInfo := &model.ReleaseInfo{ + Name: name, + Namespace: &namespace, + Description: &release.Spec.Description, + } + releaseInfo.Package.Repository = release.Spec.Package.Repository + releaseInfo.Package.Tag = release.Spec.Package.Tag + releaseInfo.Git.Path = content.Path + releaseInfo.Git.URL = content.URL + + releasesInfo = append(releasesInfo, releaseInfo) + } + return releasesInfo, nil +} + +func (s GitRepoService) getReleaseInfo(clusterID, namespace, kustomizationName, releaseNamespace, releaseName string) (*model.ReleaseInfo, *model.ServerResponse) { + releases, err := s.ListReleases(clusterID, namespace, kustomizationName) + if err != nil { + return nil, err + } + + for _, rel := range releases { + if rel.Name == releaseName && rel.Namespace != nil && *rel.Namespace == releaseNamespace { + return rel, nil + } + } + + return nil, nil +} From 0a3b2a2aa1a54c13ad181452d86f6394b227ea9e Mon Sep 17 00:00:00 2001 From: iizitounene Date: Wed, 14 May 2025 18:34:48 +0200 Subject: [PATCH 08/14] chore: upgrade Go module dependencies to latest --- Dockerfile | 4 +- Makefile | 6 +- go.mod | 125 +++++++++++++-------------- go.sum | 244 ++++++++++++++++++++++++++--------------------------- 4 files changed, 182 insertions(+), 197 deletions(-) diff --git a/Dockerfile b/Dockerfile index 670f224..9719b05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG GO_VERSION=1.23 +ARG GO_VERSION=1.24 FROM golang:${GO_VERSION} AS go-build @@ -24,7 +24,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ LDFLAGS=${LDFLAGS##-X localbuild=true} GIT_COMMIT=$GIT_COMMIT \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -a -o okdp-server main.go -FROM alpine:3.20.3 +FROM alpine:3.21.3 RUN apk --no-cache add ca-certificates && update-ca-certificates diff --git a/Makefile b/Makefile index e558c13..5193316 100644 --- a/Makefile +++ b/Makefile @@ -17,13 +17,13 @@ test: compile gotest build: test gobuild run: test gorun rundev: generate gocompile gotest gobuild gorun -update: build goupdate +update: build goupdate build .PHONY: tools tools: go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.4.1 go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2 - go install golang.org/x/tools/cmd/goimports@v0.28.0 + go install golang.org/x/tools/cmd/goimports@v0.33.0 .PHONY: gogenerate gogenerate: @@ -81,6 +81,6 @@ gorun: .PHONY: goupdate goupdate: - go get -u all + go get -u ./... go mod tidy diff --git a/go.mod b/go.mod index a60d686..c1f6a24 100644 --- a/go.mod +++ b/go.mod @@ -1,117 +1,109 @@ module github.com/okdp/okdp-server -go 1.23.0 - -toolchain go1.23.6 +go 1.24.0 require kubocd v0.2.1 replace kubocd => github.com/kubocd/kubocd v0.2.1 require ( - github.com/Masterminds/semver/v3 v3.3.0 - github.com/casbin/casbin/v2 v2.103.0 - github.com/coreos/go-oidc/v3 v3.12.0 + github.com/Masterminds/semver/v3 v3.3.1 + github.com/casbin/casbin/v2 v2.105.0 + github.com/coreos/go-oidc/v3 v3.14.1 github.com/fluxcd/kustomize-controller/api v1.5.1 github.com/fluxcd/source-controller/api v1.5.0 - github.com/fsnotify/fsnotify v1.8.0 - github.com/getkin/kin-openapi v0.129.0 - github.com/gin-contrib/cors v1.7.3 - github.com/gin-contrib/sessions v1.0.2 - github.com/gin-contrib/zap v1.1.4 + github.com/fsnotify/fsnotify v1.9.0 + github.com/getkin/kin-openapi v0.132.0 + github.com/gin-contrib/cors v1.7.5 + github.com/gin-contrib/sessions v1.0.3 + github.com/gin-contrib/zap v1.1.5 github.com/gin-gonic/gin v1.10.0 github.com/go-git/go-billy/v5 v5.6.2 github.com/go-git/go-git/v5 v5.16.0 github.com/oapi-codegen/runtime v1.1.1 - github.com/opencontainers/image-spec v1.1.0 + github.com/opencontainers/image-spec v1.1.1 github.com/skeema/knownhosts v1.3.1 github.com/spf13/cobra v1.9.1 - github.com/spf13/viper v1.19.0 + github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.10.0 github.com/tidwall/gjson v1.18.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20250215185904-eff6e970281f - golang.org/x/net v0.39.0 - golang.org/x/oauth2 v0.26.0 - k8s.io/api v0.32.2 - k8s.io/apimachinery v0.32.2 - k8s.io/client-go v0.32.2 - oras.land/oras-go/v2 v2.5.0 - sigs.k8s.io/controller-runtime v0.20.2 + golang.org/x/net v0.40.0 + golang.org/x/oauth2 v0.30.0 + k8s.io/api v0.33.0 + k8s.io/apimachinery v0.33.0 + k8s.io/client-go v0.33.0 + oras.land/oras-go/v2 v2.6.0 + sigs.k8s.io/controller-runtime v0.20.4 sigs.k8s.io/yaml v1.4.0 ) require ( - dario.cat/mergo v1.0.1 // indirect + dario.cat/mergo v1.0.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.1.6 // indirect + github.com/ProtonMail/go-crypto v1.2.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect - github.com/bytedance/sonic v1.12.8 // indirect - github.com/bytedance/sonic/loader v0.2.3 // indirect - github.com/casbin/govaluate v1.3.0 // indirect + github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/casbin/govaluate v1.4.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.1 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect - github.com/fluxcd/pkg/apis/acl v0.6.0 // indirect - github.com/fluxcd/pkg/apis/kustomize v1.9.0 // indirect - github.com/fluxcd/pkg/apis/meta v1.10.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/gin-contrib/sse v1.0.0 // indirect + github.com/fluxcd/pkg/apis/acl v0.7.0 // indirect + github.com/fluxcd/pkg/apis/kustomize v1.10.0 // indirect + github.com/fluxcd/pkg/apis/meta v1.11.0 // indirect + github.com/fxamacker/cbor/v2 v2.8.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.9 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/go-jose/go-jose/v4 v4.1.0 // indirect github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.20.4 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/jsonpointer v0.21.1 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.25.0 // indirect + github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/context v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.4.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/magiconair/properties v1.8.9 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 // indirect - github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/sagikazarmark/locafero v0.7.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sagikazarmark/locafero v0.9.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.12.0 // indirect - github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/afero v1.14.0 // indirect + github.com/spf13/cast v1.8.0 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -121,22 +113,23 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/arch v0.14.0 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect - golang.org/x/time v0.8.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + golang.org/x/arch v0.17.0 // indirect + golang.org/x/crypto v0.38.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect + golang.org/x/time v0.11.0 // indirect + golang.org/x/tools v0.33.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.32.2 // indirect + k8s.io/apiextensions-apiserver v0.33.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect ) diff --git a/go.sum b/go.sum index 438f198..da24bc4 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,12 @@ -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= -github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.2.0 h1:+PhXXn4SPGd+qk76TlEePBfOfivE0zkWFenhGhFLzWs= +github.com/ProtonMail/go-crypto v1.2.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= @@ -18,22 +18,23 @@ github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvF github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= -github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs= -github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0= -github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= -github.com/casbin/casbin/v2 v2.103.0 h1:dHElatNXNrr8XcseUov0ZSiWjauwmZZE6YMV3eU1yic= -github.com/casbin/casbin/v2 v2.103.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco= -github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/casbin/casbin/v2 v2.105.0 h1:dLj5P6pLApBRat9SADGiLxLZjiDPvA1bsPkyV4PGx6I= +github.com/casbin/casbin/v2 v2.105.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco= github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= +github.com/casbin/govaluate v1.4.0 h1:/pjx3ssi/U1qXAomngy8aNErQXDazBChu02QEbQgIj4= +github.com/casbin/govaluate v1.4.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= -github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= +github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk= +github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= @@ -43,40 +44,40 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emicklei/go-restful/v3 v3.11.1 h1:S+9bSbua1z3FgCnV0KKOSSZ3mDthb5NyEPL5gEpCvyk= -github.com/emicklei/go-restful/v3 v3.11.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/fluxcd/kustomize-controller/api v1.5.1 h1:SLVMIk/3E/GkK610S85zDBfX/TQhpE2ym+516ONXtU4= github.com/fluxcd/kustomize-controller/api v1.5.1/go.mod h1:SnQ5blin2e25GOCvd9JqYezYhqcM7beyK1aLq9Iw0So= -github.com/fluxcd/pkg/apis/acl v0.6.0 h1:rllf5uQLzTow81ZCslkQ6LPpDNqVQr6/fWaNksdUEtc= -github.com/fluxcd/pkg/apis/acl v0.6.0/go.mod h1:IVDZx3MAoDWjlLrJHMF9Z27huFuXAEQlnbWw0M6EcTs= -github.com/fluxcd/pkg/apis/kustomize v1.9.0 h1:SJpT1CK58AnTvCpDKeGfMNA0Xud/4VReZNvPe8XkTxo= -github.com/fluxcd/pkg/apis/kustomize v1.9.0/go.mod h1:AZl2GU03oPVue6SUivdiIYd/3mvF94j7t1G2JO26d4s= -github.com/fluxcd/pkg/apis/meta v1.10.0 h1:rqbAuyl5ug7A5jjRf/rNwBXmNl6tJ9wG2iIsriwnQUk= -github.com/fluxcd/pkg/apis/meta v1.10.0/go.mod h1:n7NstXHDaleAUMajcXTVkhz0MYkvEXy1C/eLI/t1xoI= +github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0= +github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ= +github.com/fluxcd/pkg/apis/kustomize v1.10.0 h1:47EeSzkQvlQZdH92vHMe2lK2iR8aOSEJq95avw5idts= +github.com/fluxcd/pkg/apis/kustomize v1.10.0/go.mod h1:UsqMV4sqNa1Yg0pmTsdkHRJr7bafBOENIJoAN+3ezaQ= +github.com/fluxcd/pkg/apis/meta v1.11.0 h1:h8q95k6ZEK1HCfsLkt8Np3i6ktb6ZzcWJ6hg++oc9w0= +github.com/fluxcd/pkg/apis/meta v1.11.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI= github.com/fluxcd/source-controller/api v1.5.0 h1:caSR+u/r2Vh0jq/0pNR0r1zLxyvgatWuGSV2mxgTB/I= github.com/fluxcd/source-controller/api v1.5.0/go.mod h1:OZPuHMlLH2E2mnj6Q5DLkWfUOmJ20zA1LIvUVfNsYl8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= -github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30= -github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI= -github.com/gin-contrib/cors v1.7.3 h1:hV+a5xp8hwJoTw7OY+a70FsL8JkVVFTXw9EcfrYUdns= -github.com/gin-contrib/cors v1.7.3/go.mod h1:M3bcKZhxzsvI+rlRSkkxHyljJt1ESd93COUvemZ79j4= -github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA= -github.com/gin-contrib/sessions v1.0.2/go.mod h1:KxKxWqWP5LJVDCInulOl4WbLzK2KSPlLesfZ66wRvMs= -github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= -github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= -github.com/gin-contrib/zap v1.1.4 h1:xvxTybg6XBdNtcQLH3Tf0lFr4vhDkwzgLLrIGlNTqIo= -github.com/gin-contrib/zap v1.1.4/go.mod h1:7lgEpe91kLbeJkwBTPgtVBy4zMa6oSBEcvj662diqKQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= +github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= +github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/gin-contrib/cors v1.7.5 h1:cXC9SmofOrRg0w9PigwGlHG3ztswH6bqq4vJVXnvYMk= +github.com/gin-contrib/cors v1.7.5/go.mod h1:4q3yi7xBEDDWKapjT2o1V7mScKDDr8k+jZ0fSquGoy0= +github.com/gin-contrib/sessions v1.0.3 h1:AZ4j0AalLsGqdrKNbbrKcXx9OJZqViirvNGsJTxcQps= +github.com/gin-contrib/sessions v1.0.3/go.mod h1:5i4XMx4KPtQihnzxEqG9u1K446lO3G19jAi2GtbfsAI= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-contrib/zap v1.1.5 h1:qKwhWb4DQgPriCl1AHLLob6hav/KUIctKXIjTmWIN3I= +github.com/gin-contrib/zap v1.1.5/go.mod h1:lAchUtGz9M2K6xDr1rwtczyDrThmSx6c9F384T45iOE= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= @@ -89,30 +90,32 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ= github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= -github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY= +github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= +github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= -github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -121,10 +124,8 @@ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8J github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -141,8 +142,6 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -157,8 +156,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= -github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -171,14 +170,10 @@ github.com/kubocd/kubocd v0.2.1 h1:2IVRs85zqznXz9pEe9yiwuIdjcrVpWlzzLdRqvzyZxk= github.com/kubocd/kubocd v0.2.1/go.mod h1:ICIRAAcJaK2tIXObQH6LSAUFmgKYzZZU9XqKWaEjnhM= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= -github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -190,20 +185,20 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= -github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 h1:9djga8U4+/TQzv5iMlZHZ/qbGQB9V2nlnk2bmiG+uBs= -github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8= -github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672 h1:+273wgr7to5QhwOOBE5LwjdNDFAI+8cbJVfB0Zj75aI= -github.com/oasdiff/yaml3 v0.0.0-20241214160948-977117996672/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= @@ -216,10 +211,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= +github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -227,20 +220,21 @@ github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnB github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= +github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= +github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= -github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -249,7 +243,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -277,16 +270,14 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= -golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= +golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= -golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg= -golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -295,15 +286,15 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -314,31 +305,31 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -347,8 +338,6 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -356,28 +345,31 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= -k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= -k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= -k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= -k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= -k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= -k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= +k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU= +k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM= +k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs= +k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc= +k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ= +k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98= +k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979 h1:jgJW5IePPXLGB8e/1wvd0Ich9QE97RvvF3a8J3fP/Lg= +k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= -oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= -sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= -sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= +oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= +sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= +sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From 013af499792d7335278fe4b1f13143ebaf0a305a Mon Sep 17 00:00:00 2001 From: iizitounene Date: Thu, 15 May 2025 12:00:58 +0200 Subject: [PATCH 09/14] feat: support multiple k8s contexts in the kubeconfig --- .local/application-local.yaml | 3 +- internal/common/constants/constants.go | 13 +++-- internal/integrations/k8s/client/client.go | 62 ++++++++++++++++++---- internal/model/cluster.go | 17 ++++++ 4 files changed, 79 insertions(+), 16 deletions(-) diff --git a/.local/application-local.yaml b/.local/application-local.yaml index 34a0a40..be9f9df 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -129,7 +129,8 @@ clusters: kubeconfig: apiServer: https://host.docker.internal:56660 path: /tmp/.kube/config - context: dev-context + # When not provided, use current context + # context: kind-kind-okdp-sandbox insecureSkipTlsVerify: true # certificate: # apiServer: https://k8s-api-server-url:6443 diff --git a/internal/common/constants/constants.go b/internal/common/constants/constants.go index 00be64e..278ca07 100644 --- a/internal/common/constants/constants.go +++ b/internal/common/constants/constants.go @@ -29,9 +29,12 @@ const ( // CasbinRolePrefix is used to prefix the roles/groups in the casbin policy (p, role:viewers, /api/v1/users/myprofile, *) CasbinRolePrefix = "role:" // SwaggerAPIDocsURI is the swagger API Docs public URI - SwaggerAPIDocsURI = OkdpServerBaseURL + "/api-docs" - HealthzURI = "/healthz" - ReadinessURI = "/readiness" - All = "All" - GitRepository = "GitRepository" + SwaggerAPIDocsURI = OkdpServerBaseURL + "/api-docs" + HealthzURI = "/healthz" + ReadinessURI = "/readiness" + All = "All" + GitRepository = "GitRepository" + K8SAuthKubeConfig = "AuthKubeconfig" + K8SAuthCertificate = "AuthCertificate" + K8SAuthBeaer = "AuthBearer" ) diff --git a/internal/integrations/k8s/client/client.go b/internal/integrations/k8s/client/client.go index e614e72..914534e 100644 --- a/internal/integrations/k8s/client/client.go +++ b/internal/integrations/k8s/client/client.go @@ -23,11 +23,14 @@ import ( sourcev1 "github.com/fluxcd/source-controller/api/v1" corev1 "k8s.io/api/core/v1" apiruntime "k8s.io/apimachinery/pkg/runtime" + restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" k8s "sigs.k8s.io/controller-runtime/pkg/client" kubocdv1alpha1 "kubocd/api/v1alpha1" + "github.com/okdp/okdp-server/internal/common/constants" log "github.com/okdp/okdp-server/internal/common/logging" "github.com/okdp/okdp-server/internal/config" "github.com/okdp/okdp-server/internal/model" @@ -54,16 +57,31 @@ func GetClients() *KubeClients { clusters := config.GetAppConfig().Clusters for _, cluster := range clusters { log.Info("K8S Cluster configuration: %+v", cluster) - config, err := clientcmd.BuildConfigFromFlags(cluster.Auth.Kubeconfig.APIServer, cluster.Auth.Kubeconfig.Path) - if cluster.Auth.Kubeconfig.InsecureSkipTlsVerify { - log.Warn("TLS verification is disabled for cluster ID: %s (%s).", cluster.ID, cluster.Env) - config.Insecure = true - config.CAFile = "" - config.CAData = nil - } - - if err != nil { - log.Fatal("Error building kubeconfig for cluster ID '%s (%s)': %s", cluster.ID, cluster.Env, err.Error()) + var config *restclient.Config + switch cluster.AuthType() { + case constants.K8SAuthKubeConfig: + var err error + config, err = buildConfig(cluster.Auth.Kubeconfig.APIServer, cluster.Auth.Kubeconfig.Context, cluster.Auth.Kubeconfig.Path) + if err != nil { + log.Fatal("Failed to build kubeconfig for cluster ID %s and kubeconfig path: %s, details: %v", + cluster.ID, cluster.Auth.Kubeconfig.Path, err) + } + if cluster.Auth.Kubeconfig.InsecureSkipTlsVerify { + log.Warn("TLS verification is disabled for cluster ID: %s (%s).", cluster.ID, cluster.Env) + config.Insecure = true + config.CAFile = "" + config.CAData = nil + } + + if err != nil { + log.Fatal("Error building kubeconfig for cluster ID '%s (%s)': %s", cluster.ID, cluster.Env, err.Error()) + } + case constants.K8SAuthCertificate: + log.Fatal("Authentication method %s not supported for cluster ID %s", constants.K8SAuthCertificate, cluster.ID) + case constants.K8SAuthBeaer: + log.Fatal("Authentication method %s not supported for cluster ID %s", constants.K8SAuthBeaer, cluster.ID) + default: + log.Fatal("Unable to find authentication credentials for cluster ID %s", cluster.ID) } kubeClient, err := k8s.New(config, k8s.Options{ @@ -98,3 +116,27 @@ func newScheme() *apiruntime.Scheme { _ = kubocdv1alpha1.AddToScheme(scheme) return scheme } + +// buildConfig builds Kubernetes client config using optional apiServer URL, +// optional context (defaults to current context if empty), +// and explicit kubeconfig path. +func buildConfig(masterURL, context, kubeconfigPath string) (*restclient.Config, error) { + loadingRules := &clientcmd.ClientConfigLoadingRules{ + ExplicitPath: kubeconfigPath, + } + + overrides := &clientcmd.ConfigOverrides{} + + if context != "" { + overrides.CurrentContext = context + } + + if masterURL != "" { + overrides.ClusterInfo = clientcmdapi.Cluster{ + Server: masterURL, + } + } + + clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides) + return clientConfig.ClientConfig() +} diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 872e02e..16e739b 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -18,6 +18,7 @@ package model import ( "github.com/okdp/okdp-server/api/openapi/v3/_api" + "github.com/okdp/okdp-server/internal/common/constants" ) type Cluster _api.Cluster @@ -26,3 +27,19 @@ func ClusterNotFoundError(clusterID string) *ServerResponse { return NewServerResponse(OkdpServerResponse). NotFoundError("The cluster with id %s not found.", clusterID) } + +func (m Cluster) AuthType() string { + if m.Auth.Kubeconfig != nil { + return constants.K8SAuthKubeConfig + } + + if m.Auth.Certificate != nil { + return constants.K8SAuthCertificate + } + + if m.Auth.Bearer != nil { + return constants.K8SAuthBeaer + } + + return "" +} From 67e751a70215a5a1b781506be588f93634dd6d7f Mon Sep 17 00:00:00 2001 From: iizitounene Date: Fri, 23 May 2025 18:38:08 +0200 Subject: [PATCH 10/14] feat: okdp ui integration --- .local/application-local.yaml | 16 +- api/openapi/v3/_api/admin/admin-server.go | 82 ++ api/openapi/v3/_api/k8s/k8s-server.go | 311 ++++--- .../_api/repositories/repositories-server.go | 311 ++++--- api/openapi/v3/_api/spec.go | 200 ++-- api/openapi/v3/_api/types.go | 853 +++++++++++------- api/openapi/v3/api.yaml | 4 + api/openapi/v3/definition/Cluster.yaml | 3 + api/openapi/v3/definition/Package.yaml | 5 + api/openapi/v3/definition/Release.yaml | 78 +- api/openapi/v3/definition/ReleaseStatus.yaml | 157 ++-- api/openapi/v3/paths/k8s/releases.yaml | 2 +- internal/config/config_test.go | 1 + internal/config/testdata/application.yaml | 1 + internal/integrations/k8s/client/k8s.go | 50 + internal/integrations/k8s/client/kubocd.go | 2 +- internal/integrations/k8s/k8s.go | 11 + internal/integrations/k8s/kubocd.go | 4 +- internal/integrations/oci/client/client.go | 7 +- internal/services/cluster.go | 2 +- internal/services/kubocd.go | 4 +- internal/utils/collection_utils.go | 10 +- package.json | 2 +- 23 files changed, 1403 insertions(+), 713 deletions(-) create mode 100644 api/openapi/v3/_api/admin/admin-server.go create mode 100644 internal/integrations/k8s/client/k8s.go diff --git a/.local/application-local.yaml b/.local/application-local.yaml index be9f9df..8b160ca 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -83,6 +83,17 @@ swagger: - oauth2: [openid, email, profile, roles] +# packages: +# - repo: quay.io/kubocd/packages +# name: redis +# versions: [""] +# - repo: quay.io/kubocd/packages +# name: minio +# versions: [""] +# - repo: quay.io/kubocd/packages +# name: cnpg +# versions: [""] + catalog: - id: storage name: Storage catalog @@ -110,7 +121,6 @@ catalog: description: My Infra packages repoUrl: quay.io/kubocd/packages packages: - - name: podinfo - name: cert-manager - name: ingress-nginx - name: metallb @@ -120,10 +130,11 @@ catalog: description: My Stack packages repoUrl: quay.io/kubocd/packages packages: - - name: stack1 + - name: podinfo clusters: - id: kubo2 + name: My k8s cluster 1 env: dev auth: kubeconfig: @@ -141,3 +152,4 @@ clusters: # apiServer: https://k8s-api-server-url:6443 # bearerToken: $(BEARER_TOKEN) + diff --git a/api/openapi/v3/_api/admin/admin-server.go b/api/openapi/v3/_api/admin/admin-server.go new file mode 100644 index 0000000..e2b0779 --- /dev/null +++ b/api/openapi/v3/_api/admin/admin-server.go @@ -0,0 +1,82 @@ +// Package _admin provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. +package _admin + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/oapi-codegen/runtime" +) + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // Get the list of the deployed releases on all namespaces + // (GET /admin/clusters/{clusterId}/releases) + AdminListK8sReleases(c *gin.Context, clusterId string) +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +type MiddlewareFunc func(c *gin.Context) + +// AdminListK8sReleases operation middleware +func (siw *ServerInterfaceWrapper) AdminListK8sReleases(c *gin.Context) { + + var err error + + // ------------- Path parameter "clusterId" ------------- + var clusterId string + + err = runtime.BindStyledParameterWithOptions("simple", "clusterId", c.Param("clusterId"), &clusterId, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter clusterId: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.AdminListK8sReleases(c, clusterId) +} + +// GinServerOptions provides options for the Gin server. +type GinServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc + ErrorHandler func(*gin.Context, error, int) +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router gin.IRouter, si ServerInterface) { + RegisterHandlersWithOptions(router, si, GinServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) { + errorHandler := options.ErrorHandler + if errorHandler == nil { + errorHandler = func(c *gin.Context, err error, statusCode int) { + c.JSON(statusCode, gin.H{"msg": err.Error()}) + } + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + HandlerMiddlewares: options.Middlewares, + ErrorHandler: errorHandler, + } + + router.GET(options.BaseURL+"/admin/clusters/:clusterId/releases", wrapper.AdminListK8sReleases) +} diff --git a/api/openapi/v3/_api/k8s/k8s-server.go b/api/openapi/v3/_api/k8s/k8s-server.go index 4144a18..b736b66 100644 --- a/api/openapi/v3/_api/k8s/k8s-server.go +++ b/api/openapi/v3/_api/k8s/k8s-server.go @@ -6,6 +6,7 @@ package _k8s import ( "fmt" "net/http" + "time" "github.com/gin-gonic/gin" "github.com/oapi-codegen/runtime" @@ -45,18 +46,70 @@ type CreateK8sReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -226,57 +279,54 @@ type CreateK8sReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } @@ -298,18 +348,70 @@ type UpdateK8sReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -479,57 +581,54 @@ type UpdateK8sReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } diff --git a/api/openapi/v3/_api/repositories/repositories-server.go b/api/openapi/v3/_api/repositories/repositories-server.go index efa48a6..2515668 100644 --- a/api/openapi/v3/_api/repositories/repositories-server.go +++ b/api/openapi/v3/_api/repositories/repositories-server.go @@ -6,6 +6,7 @@ package _repositories import ( "fmt" "net/http" + "time" "github.com/gin-gonic/gin" "github.com/oapi-codegen/runtime" @@ -45,18 +46,70 @@ type CreateGitReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -226,57 +279,54 @@ type CreateGitReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } @@ -292,18 +342,70 @@ type UpdateGitReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -473,57 +575,54 @@ type UpdateGitReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } diff --git a/api/openapi/v3/_api/spec.go b/api/openapi/v3/_api/spec.go index b094ac6..8bc8cac 100644 --- a/api/openapi/v3/_api/spec.go +++ b/api/openapi/v3/_api/spec.go @@ -18,103 +18,109 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "BJOH64f/DQAA///Dy+n9WY0AAA==", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/openapi/v3/_api/types.go b/api/openapi/v3/_api/types.go index 1093b6b..93e27b3 100644 --- a/api/openapi/v3/_api/types.go +++ b/api/openapi/v3/_api/types.go @@ -6,6 +6,7 @@ package _api import ( "encoding/json" "fmt" + "time" "github.com/oapi-codegen/runtime" ) @@ -109,6 +110,7 @@ type Cluster struct { Auth *Cluster_Auth `json:"auth,omitempty"` Env string `json:"env"` ID string `json:"id"` + Name string `json:"name"` } // ClusterAuth0 defines model for . @@ -179,6 +181,9 @@ type Package struct { // Name The name of the package Name string `json:"name"` + // RepoURL The URL of OCR registry + RepoURL string `json:"repoUrl"` + // Versions A list of versions for the package Versions []string `json:"versions"` } @@ -189,18 +194,70 @@ type Release struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -370,87 +427,8 @@ type Release struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` - - // Status Release is the Schema for the releases API. - Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` - } `json:"status,omitempty"` -} - -// ReleaseSpecPackageProvider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator -// All following fields will be replicated in this object -// The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. -// When not specified, defaults to 'generic'. -// -kubebuilder:default:=generic -type ReleaseSpecPackageProvider string - -// ReleaseSpecPackageVerifyProvider Provider specifies the technology used to sign the OCI Artifact. -type ReleaseSpecPackageVerifyProvider string - -// ReleaseInfo defines model for ReleaseInfo. -type ReleaseInfo struct { - Description *string `json:"description,omitempty"` - Git struct { - Path string `json:"path"` - URL string `json:"url"` - } `json:"git"` - Name string `json:"name"` - Namespace *string `json:"namespace,omitempty"` - Package struct { - Repository string `json:"repository"` - Tag string `json:"tag"` - } `json:"package"` -} + } `json:"spec"` -// ReleaseStatus Release is the Schema for the releases API. -type ReleaseStatus struct { // Status ReleaseStatus defines the observed state of Release. // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. // (Except for 'context', as controlled by a debug flag) @@ -459,18 +437,18 @@ type ReleaseStatus struct { Context *interface{} `json:"context,omitempty"` // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` + Dependencies *[]string `json:"dependencies,omitempty"` // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name HelmReleaseStates *map[string]struct { Ready string `json:"ready"` Status *string `json:"status,omitempty"` } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` + MissingDependency *string `json:"missingDependency,omitempty"` // Parameters Parameters is the resulting parameters set, if requested in debug options Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` + Phase *string `json:"phase,omitempty"` // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed // as printcolumn @@ -481,18 +459,18 @@ type ReleaseStatus struct { PrintDescription *string `json:"printDescription,omitempty"` // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` + PrintProtected *string `json:"printProtected,omitempty"` // Protected Protected result of Release.spec.protected defaulted to package.spec.protected // It is the value checked by the webhook - Protected bool `json:"protected"` + Protected *bool `json:"protected,omitempty"` // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed // as printcolumn - ReadyReleases string `json:"readyReleases"` + ReadyReleases *string `json:"readyReleases,omitempty"` // Roles The result of the package template and release value - Roles []string `json:"roles"` + Roles *[]string `json:"roles,omitempty"` // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. // Key could 'html', 'text', some language id, etc... @@ -500,6 +478,79 @@ type ReleaseStatus struct { } `json:"status,omitempty"` } +// ReleaseSpecPackageProvider The source will be handled by a child fluxCD OciRepository resource, which will be created by this operator +// All following fields will be replicated in this object +// The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. +// When not specified, defaults to 'generic'. +// -kubebuilder:default:=generic +type ReleaseSpecPackageProvider string + +// ReleaseSpecPackageVerifyProvider Provider specifies the technology used to sign the OCI Artifact. +type ReleaseSpecPackageVerifyProvider string + +// ReleaseInfo defines model for ReleaseInfo. +type ReleaseInfo struct { + Description *string `json:"description,omitempty"` + Git struct { + Path string `json:"path"` + URL string `json:"url"` + } `json:"git"` + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + Package struct { + Repository string `json:"repository"` + Tag string `json:"tag"` + } `json:"package"` +} + +// ReleaseStatus ReleaseStatus defines the observed state of Release. +// As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. +// (Except for 'context', as controlled by a debug flag) +type ReleaseStatus struct { + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` +} + // ServerResponse defines model for ServerResponse. type ServerResponse struct { // Message The response message from the server @@ -531,18 +582,70 @@ type CreateGitReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -712,57 +815,54 @@ type CreateGitReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } @@ -778,18 +878,70 @@ type UpdateGitReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -959,57 +1111,54 @@ type UpdateGitReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } @@ -1025,18 +1174,70 @@ type CreateK8sReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -1206,57 +1407,54 @@ type CreateK8sReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } @@ -1278,18 +1476,70 @@ type UpdateK8sReleaseJSONBody struct { // Servers should convert recognized schemas to the latest internal value, and // may reject unrecognized values. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - ApiVersion *string `json:"apiVersion,omitempty"` + ApiVersion string `json:"apiVersion"` // Kind Kind is a string value representing the REST resource this object represents. // Servers may infer this from the endpoint the client submits requests to. // Cannot be updated. // In CamelCase. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty"` - Metadata *map[string]interface{} `json:"metadata,omitempty"` + Kind string `json:"kind"` + + // Metadata Standard object metadata. + Metadata struct { + // Annotations Arbitrary metadata. + Annotations *map[string]string `json:"annotations,omitempty"` + + // CreationTimestamp Creation timestamp. + CreationTimestamp *time.Time `json:"creationTimestamp,omitempty"` + + // DeletionGracePeriodSeconds Seconds allowed for graceful termination. + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + + // DeletionTimestamp Deletion timestamp. + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + + // Finalizers List of finalizers. + Finalizers *[]string `json:"finalizers,omitempty"` + + // GenerateName Prefix for generating a unique name. + GenerateName *string `json:"generateName,omitempty"` + + // Generation Sequence number representing generation of desired state. + Generation *int64 `json:"generation,omitempty"` + + // Labels Key-value pairs to categorize resources. + Labels *map[string]string `json:"labels,omitempty"` + + // ManagedFields Managed fields tracking info (complex object). + ManagedFields *map[string]interface{} `json:"managedFields,omitempty"` + + // Name Name of the resource. + Name *string `json:"name,omitempty"` + + // Namespace Namespace of the resource. + Namespace *string `json:"namespace,omitempty"` + + // OwnerReferences References to owning resources. + OwnerReferences *[]struct { + ApiVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Uid *string `json:"uid,omitempty"` + } `json:"ownerReferences,omitempty"` + + // ResourceVersion Resource version for concurrency control. + ResourceVersion *string `json:"resourceVersion,omitempty"` + + // SelfLink Deprecated self-link URL. + SelfLink *string `json:"selfLink,omitempty"` + + // Uid Unique ID assigned by Kubernetes. + Uid *string `json:"uid,omitempty"` + } `json:"metadata"` // Spec ReleaseSpec defines the desired state of Release. - Spec *struct { + Spec struct { // Contexts To provide contextual variables // Refer to Context resource description for some explanation // Contexts are merged in the following order: @@ -1459,57 +1709,54 @@ type UpdateK8sReleaseJSONBody struct { // (i.e. the package has a fixed namespace, or several ones). // Default: Release.metadata.namespace TargetNamespace *string `json:"targetNamespace,omitempty"` - } `json:"spec,omitempty"` + } `json:"spec"` - // Status Release is the Schema for the releases API. + // Status ReleaseStatus defines the observed state of Release. + // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + // (Except for 'context', as controlled by a debug flag) Status *struct { - // Status ReleaseStatus defines the observed state of Release. - // As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - // (Except for 'context', as controlled by a debug flag) - Status *struct { - // Context Context is the resulting context, if requested in debug options - Context *interface{} `json:"context,omitempty"` - - // Dependencies The result of the package template and release value - Dependencies []string `json:"dependencies"` - - // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name - HelmReleaseStates *map[string]struct { - Ready string `json:"ready"` - Status *string `json:"status,omitempty"` - } `json:"helmReleaseStates,omitempty"` - MissingDependency string `json:"missingDependency"` - - // Parameters Parameters is the resulting parameters set, if requested in debug options - Parameters *interface{} `json:"parameters,omitempty"` - Phase string `json:"phase"` - - // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - // as printcolumn - PrintContexts *string `json:"printContexts,omitempty"` - - // PrintDescription PrintDescription - // Copy of the release description, or, if empty the (templated) package one - PrintDescription *string `json:"printDescription,omitempty"` - - // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display - PrintProtected string `json:"printProtected"` - - // Protected Protected result of Release.spec.protected defaulted to package.spec.protected - // It is the value checked by the webhook - Protected bool `json:"protected"` - - // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - // as printcolumn - ReadyReleases string `json:"readyReleases"` - - // Roles The result of the package template and release value - Roles []string `json:"roles"` - - // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - // Key could 'html', 'text', some language id, etc... - Usage *map[string]string `json:"usage,omitempty"` - } `json:"status,omitempty"` + // Context Context is the resulting context, if requested in debug options + Context *interface{} `json:"context,omitempty"` + + // Dependencies The result of the package template and release value + Dependencies *[]string `json:"dependencies,omitempty"` + + // HelmReleaseStates HelmReleaseState describe the observed state of child HelmReleases by name + HelmReleaseStates *map[string]struct { + Ready string `json:"ready"` + Status *string `json:"status,omitempty"` + } `json:"helmReleaseStates,omitempty"` + MissingDependency *string `json:"missingDependency,omitempty"` + + // Parameters Parameters is the resulting parameters set, if requested in debug options + Parameters *interface{} `json:"parameters,omitempty"` + Phase *string `json:"phase,omitempty"` + + // PrintContexts PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + // as printcolumn + PrintContexts *string `json:"printContexts,omitempty"` + + // PrintDescription PrintDescription + // Copy of the release description, or, if empty the (templated) package one + PrintDescription *string `json:"printDescription,omitempty"` + + // PrintProtected PrintProtected is a copy of Protected, with a Y/n flag. To be used in display + PrintProtected *string `json:"printProtected,omitempty"` + + // Protected Protected result of Release.spec.protected defaulted to package.spec.protected + // It is the value checked by the webhook + Protected *bool `json:"protected,omitempty"` + + // ReadyReleases ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + // as printcolumn + ReadyReleases *string `json:"readyReleases,omitempty"` + + // Roles The result of the package template and release value + Roles *[]string `json:"roles,omitempty"` + + // Usage Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + // Key could 'html', 'text', some language id, etc... + Usage *map[string]string `json:"usage,omitempty"` } `json:"status,omitempty"` } diff --git a/api/openapi/v3/api.yaml b/api/openapi/v3/api.yaml index cce9a8b..6e8af37 100644 --- a/api/openapi/v3/api.yaml +++ b/api/openapi/v3/api.yaml @@ -38,6 +38,10 @@ tags: description: KuboCD K8S Releases externalDocs: url: https://github.com/okdp/okdp-server + - name: admin + description: KuboCD K8S Releases + externalDocs: + url: https://github.com/okdp/okdp-server paths: ### Users diff --git a/api/openapi/v3/definition/Cluster.yaml b/api/openapi/v3/definition/Cluster.yaml index dca27c0..54a0ef3 100644 --- a/api/openapi/v3/definition/Cluster.yaml +++ b/api/openapi/v3/definition/Cluster.yaml @@ -3,12 +3,15 @@ xml: name: Cluster required: - id + - name - env - k8s properties: id: type: string x-go-name: ID + name: + type: string env: type: string auth: diff --git a/api/openapi/v3/definition/Package.yaml b/api/openapi/v3/definition/Package.yaml index 7132cdb..a574c72 100644 --- a/api/openapi/v3/definition/Package.yaml +++ b/api/openapi/v3/definition/Package.yaml @@ -4,6 +4,7 @@ xml: required: - "name" - "versions" +- "repoUrl" properties: name: type: string @@ -13,3 +14,7 @@ properties: items: type: string description: A list of versions for the package + repoUrl: + type: string + description: The URL of OCR registry + x-go-name: repoURL diff --git a/api/openapi/v3/definition/Release.yaml b/api/openapi/v3/definition/Release.yaml index c6b3b4e..97df61a 100644 --- a/api/openapi/v3/definition/Release.yaml +++ b/api/openapi/v3/definition/Release.yaml @@ -1,5 +1,13 @@ # controller-gen crd paths=./api/v1alpha1 output:crd:dir=./api/schema description: Release is the Schema for the releases API. +type: object +xml: + name: Release +required: +- "apiVersion" +- "kind" +- "metadata" +- "spec" properties: apiVersion: description: |- @@ -18,6 +26,74 @@ properties: type: string metadata: type: object + description: Standard object metadata. + properties: + name: + type: string + description: Name of the resource. + namespace: + type: string + description: Namespace of the resource. + labels: + type: object + additionalProperties: + type: string + description: Key-value pairs to categorize resources. + annotations: + type: object + additionalProperties: + type: string + description: Arbitrary metadata. + finalizers: + type: array + items: + type: string + description: List of finalizers. + ownerReferences: + type: array + items: + type: object + properties: + apiVersion: + type: string + kind: + type: string + name: + type: string + uid: + type: string + description: References to owning resources. + generation: + type: integer + format: int64 + description: Sequence number representing generation of desired state. + creationTimestamp: + type: string + format: date-time + description: Creation timestamp. + deletionTimestamp: + type: string + format: date-time + description: Deletion timestamp. + uid: + type: string + description: Unique ID assigned by Kubernetes. + generateName: + type: string + description: Prefix for generating a unique name. + selfLink: + type: string + description: Deprecated self-link URL. + resourceVersion: + type: string + description: Resource version for concurrency control. + deletionGracePeriodSeconds: + type: integer + format: int64 + description: Seconds allowed for graceful termination. + managedFields: + type: object + description: Managed fields tracking info (complex object). spec: description: ReleaseSpec defines the desired state of Release. properties: @@ -278,4 +354,4 @@ properties: type: object status: $ref: './ReleaseStatus.yaml' -type: object + diff --git a/api/openapi/v3/definition/ReleaseStatus.yaml b/api/openapi/v3/definition/ReleaseStatus.yaml index dd53ee4..25654cc 100644 --- a/api/openapi/v3/definition/ReleaseStatus.yaml +++ b/api/openapi/v3/definition/ReleaseStatus.yaml @@ -1,87 +1,80 @@ # controller-gen crd paths=./api/v1alpha1 output:crd:dir=./api/schema -description: Release is the Schema for the releases API. +description: |- + ReleaseStatus defines the observed state of Release. + As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. + (Except for 'context', as controlled by a debug flag) +type: object +xml: + name: ReleaseStatus properties: - status: - description: |- - ReleaseStatus defines the observed state of Release. - As we want Status to be explicit about provided information, we don't use 'omitempty' in its definition. - (Except for 'context', as controlled by a debug flag) - properties: - context: - description: Context is the resulting context, if requested in debug - options - x-kubernetes-preserve-unknown-fields: true - dependencies: - description: The result of the package template and release value - items: - type: string - type: array - helmReleaseStates: - additionalProperties: - description: HelmReleaseState describe the observed state of a child - HelmRelease - properties: - ready: - type: string - status: - type: string - required: - - ready - type: object - description: HelmReleaseState describe the observed state of child - HelmReleases by name - type: object - missingDependency: - type: string - parameters: - description: Parameters is the resulting parameters set, if requested - in debug options - x-kubernetes-preserve-unknown-fields: true - phase: - type: string - printContexts: - description: |- - PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed - as printcolumn - type: string - printDescription: - description: |- - PrintDescription - Copy of the release description, or, if empty the (templated) package one - type: string - printProtected: - description: PrintProtected is a copy of Protected, with a Y/n flag. - To be used in display - type: string - protected: - description: |- - Protected result of Release.spec.protected defaulted to package.spec.protected - It is the value checked by the webhook - type: boolean - readyReleases: - description: |- - ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed - as printcolumn - type: string - roles: - description: The result of the package template and release value - items: + context: + description: Context is the resulting context, if requested in debug + options + x-kubernetes-preserve-unknown-fields: true + dependencies: + description: The result of the package template and release value + items: + type: string + type: array + helmReleaseStates: + additionalProperties: + description: HelmReleaseState describe the observed state of a child + HelmRelease + properties: + ready: type: string - type: array - usage: - additionalProperties: + status: type: string - description: |- - Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. - Key could 'html', 'text', some language id, etc... - type: object - required: - - dependencies - - missingDependency - - phase - - printProtected - - protected - - readyReleases - - roles + required: + - ready + type: object + description: HelmReleaseState describe the observed state of child + HelmReleases by name type: object -type: object + missingDependency: + type: string + parameters: + description: Parameters is the resulting parameters set, if requested + in debug options + x-kubernetes-preserve-unknown-fields: true + phase: + type: string + printContexts: + description: |- + PrintContextsContexts is a string to list our context. Not technically used, but intended to be displayed + as printcolumn + type: string + printDescription: + description: |- + PrintDescription + Copy of the release description, or, if empty the (templated) package one + type: string + printProtected: + description: PrintProtected is a copy of Protected, with a Y/n flag. + To be used in display + type: string + protected: + description: |- + Protected result of Release.spec.protected defaulted to package.spec.protected + It is the value checked by the webhook + type: boolean + readyReleases: + description: |- + ReadyReleases is a string to display X/Y helmRelease ready. Not technically used, but intended to be displayed + as printcolumn + type: string + roles: + description: The result of the package template and release value + items: + type: string + type: array + usage: + additionalProperties: + type: string + description: |- + Usage is the rendering of the Package.spec.usage[key]. Aimed to provide user information. + Key could 'html', 'text', some language id, etc... + type: object + + + diff --git a/api/openapi/v3/paths/k8s/releases.yaml b/api/openapi/v3/paths/k8s/releases.yaml index e5b3eea..21aab7d 100644 --- a/api/openapi/v3/paths/k8s/releases.yaml +++ b/api/openapi/v3/paths/k8s/releases.yaml @@ -26,7 +26,7 @@ get: schema: type: array items: - $ref: '../../definition/ReleaseInfo.yaml' + $ref: '../../definition/Release.yaml' default: description: Server error diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 182c1b8..16e73dc 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -205,6 +205,7 @@ func Test_LoadConfig_Clusters(t *testing.T) { require.NotEmpty(t, clusters, "K8S clusters should not be empty") cluster := clusters[0] assert.Equal(t, "kubo03dev", cluster.ID, "ID") + assert.Equal(t, "k8s infra dev", cluster.Name, "Name") assert.Equal(t, "dev", cluster.Env, "Env") assert.Equal(t, "/path/to/kubeconfig", cluster.Auth.Kubeconfig.Path, "cluster.Auth.Kubeconfig") assert.Equal(t, "dev-context", cluster.Auth.Kubeconfig.Context, "cluster.Auth.Context") diff --git a/internal/config/testdata/application.yaml b/internal/config/testdata/application.yaml index a966b49..eee1b97 100644 --- a/internal/config/testdata/application.yaml +++ b/internal/config/testdata/application.yaml @@ -96,6 +96,7 @@ catalog: clusters: - id: kubo03dev + name: k8s infra dev env: dev auth: kubeconfig: diff --git a/internal/integrations/k8s/client/k8s.go b/internal/integrations/k8s/client/k8s.go new file mode 100644 index 0000000..11f717f --- /dev/null +++ b/internal/integrations/k8s/client/k8s.go @@ -0,0 +1,50 @@ +/* + * Copyright 2025 okdp.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +import ( + "context" + "strings" + + corev1 "k8s.io/api/core/v1" + + "github.com/okdp/okdp-server/internal/model" +) + +func (c KubeClient) ListNamespaces(ctx context.Context) ([]string, *model.ServerResponse) { + var namespaceList corev1.NamespaceList + err := c.List(ctx, &namespaceList) + if err != nil { + return nil, model. + NewServerResponse(model.K8sClusterResponse). + UnprocessableEntity("Failed to list Kubernetes namespaces on clusterId '%s', details: '%s'", c.clusterID, err.Error()) + } + + exclude := map[string]bool{ + "local-path-storage": true, + } + + namespaces := []string{} + for _, ns := range namespaceList.Items { + if exclude[ns.Name] || strings.HasPrefix(ns.Name, "kube-") { + continue + } + namespaces = append(namespaces, ns.Name) + } + + return namespaces, nil +} diff --git a/internal/integrations/k8s/client/kubocd.go b/internal/integrations/k8s/client/kubocd.go index 0ad2be8..88b8251 100644 --- a/internal/integrations/k8s/client/kubocd.go +++ b/internal/integrations/k8s/client/kubocd.go @@ -41,7 +41,7 @@ func (c KubeClient) ListReleases(ctx context.Context, namespaces ...string) ([]* converted := model.ReleaseList(releaseList) filtered := utils.Filter2(converted.ToReleases(), func(k model.Release) bool { - return utils.Contains(namespaces, k.Namespace) + return len(namespaces) == 0 || utils.Contains(namespaces, k.Namespace) }) return filtered, nil diff --git a/internal/integrations/k8s/k8s.go b/internal/integrations/k8s/k8s.go index 5761261..1383ec8 100644 --- a/internal/integrations/k8s/k8s.go +++ b/internal/integrations/k8s/k8s.go @@ -17,7 +17,10 @@ package k8s import ( + "context" + "github.com/okdp/okdp-server/internal/integrations/k8s/client" + "github.com/okdp/okdp-server/internal/model" ) type K8S struct { @@ -29,3 +32,11 @@ func NewK8S() *K8S { client.GetClients(), } } + +func (s K8S) ListNamespaces(clusterID string) ([]string, *model.ServerResponse) { + kubeClient, err := s.GetClient(clusterID) + if err != nil { + return nil, err + } + return kubeClient.ListNamespaces(context.Background()) +} diff --git a/internal/integrations/k8s/kubocd.go b/internal/integrations/k8s/kubocd.go index 604935d..fe06c9c 100644 --- a/internal/integrations/k8s/kubocd.go +++ b/internal/integrations/k8s/kubocd.go @@ -22,12 +22,12 @@ import ( "github.com/okdp/okdp-server/internal/model" ) -func (r K8S) ListReleases(clusterID string, namespace string) ([]*model.Release, *model.ServerResponse) { +func (r K8S) ListReleases(clusterID string, namespaces ...string) ([]*model.Release, *model.ServerResponse) { kubeClient, err := r.GetClient(clusterID) if err != nil { return nil, err } - return kubeClient.ListReleases(context.Background(), namespace) + return kubeClient.ListReleases(context.Background(), namespaces...) } func (r K8S) GetRelease(clusterID string, namespace string, releaseName string) (*model.Release, *model.ServerResponse) { diff --git a/internal/integrations/oci/client/client.go b/internal/integrations/oci/client/client.go index 4189b9b..22f9307 100644 --- a/internal/integrations/oci/client/client.go +++ b/internal/integrations/oci/client/client.go @@ -108,7 +108,7 @@ func GetPackages(catalogID string) ([]*model.Package, *model.ServerResponse) { } packages := make([]*model.Package, 0, len(catalog.Packages)) for _, p := range catalog.Packages { - result, err := getPackage(catalogID, p.Name) + result, err := getPackage(catalogID, p.Name, catalog.RepoURL) if err != nil { return nil, err } @@ -124,7 +124,7 @@ func GetPackage(catalogID string, name string) (*model.Package, *model.ServerRes } for _, p := range catalog.Packages { if strings.EqualFold(p.Name, name) { - return getPackage(catalogID, p.Name) + return getPackage(catalogID, p.Name, catalog.RepoURL) } } return nil, model.CatalogPackageNotFoundError(catalogID, name) @@ -138,7 +138,7 @@ func GetPackageDefinition(catalogID string, name string, version string) (map[st return repo.fetchDefinition(version) } -func getPackage(catalogID string, name string) (*model.Package, *model.ServerResponse) { +func getPackage(catalogID string, name string, repoURL string) (*model.Package, *model.ServerResponse) { repo, err := getRepoClient(catalogID, name) if err != nil { return nil, err @@ -150,6 +150,7 @@ func getPackage(catalogID string, name string) (*model.Package, *model.ServerRes return &model.Package{ Name: name, Versions: utils.SortVersions(versions), + RepoURL: repoURL, }, nil } diff --git a/internal/services/cluster.go b/internal/services/cluster.go index ce24233..0603797 100644 --- a/internal/services/cluster.go +++ b/internal/services/cluster.go @@ -40,7 +40,7 @@ func (s ClusterService) GetCluster(clusterID string) (*model.Cluster, *model.Ser } func (s ClusterService) ListNamespaces(clusterID string) ([]string, *model.ServerResponse) { - return []string{"Not Implemented: " + clusterID}, nil + return s.cluster.ListNamespaces(clusterID) } func (s ClusterService) GetNamespaceByName(clusterID string, namespace string) (string, *model.ServerResponse) { diff --git a/internal/services/kubocd.go b/internal/services/kubocd.go index 2e8c866..c0311f5 100644 --- a/internal/services/kubocd.go +++ b/internal/services/kubocd.go @@ -31,8 +31,8 @@ func NewKuboCDService() *KuboCDService { } } -func (s KuboCDService) ListReleases(clusterID string, namespace string) ([]*model.Release, *model.ServerResponse) { - return s.kubocd.ListReleases(clusterID, namespace) +func (s KuboCDService) ListReleases(clusterID string, namespaces ...string) ([]*model.Release, *model.ServerResponse) { + return s.kubocd.ListReleases(clusterID, namespaces...) } diff --git a/internal/utils/collection_utils.go b/internal/utils/collection_utils.go index 3526f86..20f3b62 100644 --- a/internal/utils/collection_utils.go +++ b/internal/utils/collection_utils.go @@ -42,10 +42,10 @@ func MapKey(keys ...string) string { // Filter filters a slice of objects based on a predicate function. // It returns a new slice containing only the elements that satisfy the predicate. func Filter[T any](objects []T, predicate func(T) bool) []*T { - var filtered []*T - for _, obj := range objects { - if predicate(obj) { - filtered = append(filtered, &obj) + filtered := make([]*T, 0, len(objects)) + for i := range objects { + if predicate(objects[i]) { + filtered = append(filtered, &objects[i]) } } return filtered @@ -54,7 +54,7 @@ func Filter[T any](objects []T, predicate func(T) bool) []*T { // Filter filters a slice of objects based on a predicate function. // It returns a new slice containing only the elements that satisfy the predicate. func Filter2[T any](objects []*T, predicate func(T) bool) []*T { - var filtered []*T + filtered := make([]*T, 0, len(objects)) for _, obj := range objects { if predicate(*obj) { filtered = append(filtered, obj) diff --git a/package.json b/package.json index 4fd7203..2a630ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "okdp-server", - "version": "0.1.0", + "version": "0.2.0", "description": "okdp-server docker image", "repository": { "type": "git", From c376dfd12361a5c0a62c194a0ceeea41026557fe Mon Sep 17 00:00:00 2001 From: iizitounene Date: Fri, 23 May 2025 18:42:00 +0200 Subject: [PATCH 11/14] ci: update go version to 1.24 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49cfd96..19eff4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: name: run tests uses: okdp/gh-workflows/.github/workflows/makefile-run-template.yml@v1 with: - go_version: "1.23" + go_version: "1.24" command: "make test" docker_test: From acef22461f69c7915d2291c8fa32aebaec22142e Mon Sep 17 00:00:00 2001 From: iizitounene Date: Mon, 26 May 2025 10:47:23 +0200 Subject: [PATCH 12/14] chore: allow kubernetes cluster access using in cluster config --- .local/application-local.yaml | 1 + api/openapi/v3/_api/spec.go | 202 ++++++++++----------- api/openapi/v3/_api/types.go | 44 +++++ api/openapi/v3/definition/Cluster.yaml | 3 + internal/common/constants/constants.go | 1 + internal/config/config_test.go | 2 + internal/config/testdata/application.yaml | 1 + internal/integrations/k8s/client/client.go | 85 ++++++--- internal/model/cluster.go | 4 + 9 files changed, 213 insertions(+), 130 deletions(-) diff --git a/.local/application-local.yaml b/.local/application-local.yaml index 8b160ca..0e35c2a 100644 --- a/.local/application-local.yaml +++ b/.local/application-local.yaml @@ -137,6 +137,7 @@ clusters: name: My k8s cluster 1 env: dev auth: + # inCluster: true kubeconfig: apiServer: https://host.docker.internal:56660 path: /tmp/.kube/config diff --git a/api/openapi/v3/_api/spec.go b/api/openapi/v3/_api/spec.go index 8bc8cac..bc43527 100644 --- a/api/openapi/v3/_api/spec.go +++ b/api/openapi/v3/_api/spec.go @@ -18,109 +18,109 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/openapi/v3/_api/types.go b/api/openapi/v3/_api/types.go index 93e27b3..bcdca96 100644 --- a/api/openapi/v3/_api/types.go +++ b/api/openapi/v3/_api/types.go @@ -122,6 +122,9 @@ type ClusterAuth1 = interface{} // ClusterAuth2 defines model for . type ClusterAuth2 = interface{} +// ClusterAuth3 defines model for . +type ClusterAuth3 = interface{} + // Cluster_Auth defines model for Cluster.Auth. type Cluster_Auth struct { Bearer *struct { @@ -134,6 +137,7 @@ type Cluster_Auth struct { ClientCert string `json:"clientCert"` ClientKey string `json:"clientKey"` } `json:"certificate,omitempty"` + InCluster *bool `json:"inCluster,omitempty"` Kubeconfig *struct { APIServer string `json:"apiServer"` Context string `json:"context"` @@ -1862,6 +1866,32 @@ func (t *Cluster_Auth) MergeClusterAuth2(v ClusterAuth2) error { return err } +// AsClusterAuth3 returns the union data inside the Cluster_Auth as a ClusterAuth3 +func (t Cluster_Auth) AsClusterAuth3() (ClusterAuth3, error) { + var body ClusterAuth3 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromClusterAuth3 overwrites any union data inside the Cluster_Auth as the provided ClusterAuth3 +func (t *Cluster_Auth) FromClusterAuth3(v ClusterAuth3) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeClusterAuth3 performs a merge with any union data inside the Cluster_Auth, using the provided ClusterAuth3 +func (t *Cluster_Auth) MergeClusterAuth3(v ClusterAuth3) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + func (t Cluster_Auth) MarshalJSON() ([]byte, error) { b, err := t.union.MarshalJSON() if err != nil { @@ -1889,6 +1919,13 @@ func (t Cluster_Auth) MarshalJSON() ([]byte, error) { } } + if t.InCluster != nil { + object["inCluster"], err = json.Marshal(t.InCluster) + if err != nil { + return nil, fmt.Errorf("error marshaling 'inCluster': %w", err) + } + } + if t.Kubeconfig != nil { object["kubeconfig"], err = json.Marshal(t.Kubeconfig) if err != nil { @@ -1924,6 +1961,13 @@ func (t *Cluster_Auth) UnmarshalJSON(b []byte) error { } } + if raw, found := object["inCluster"]; found { + err = json.Unmarshal(raw, &t.InCluster) + if err != nil { + return fmt.Errorf("error reading 'inCluster': %w", err) + } + } + if raw, found := object["kubeconfig"]; found { err = json.Unmarshal(raw, &t.Kubeconfig) if err != nil { diff --git a/api/openapi/v3/definition/Cluster.yaml b/api/openapi/v3/definition/Cluster.yaml index 54a0ef3..b181438 100644 --- a/api/openapi/v3/definition/Cluster.yaml +++ b/api/openapi/v3/definition/Cluster.yaml @@ -17,10 +17,13 @@ properties: auth: type: object oneOf: + - required: [inCluster] - required: [kubeconfig] - required: [certificate] - required: [bearer] properties: + inCluster: + type: boolean kubeconfig: type: object required: diff --git a/internal/common/constants/constants.go b/internal/common/constants/constants.go index 278ca07..a79c949 100644 --- a/internal/common/constants/constants.go +++ b/internal/common/constants/constants.go @@ -37,4 +37,5 @@ const ( K8SAuthKubeConfig = "AuthKubeconfig" K8SAuthCertificate = "AuthCertificate" K8SAuthBeaer = "AuthBearer" + K8SInCluster = "InCluster" ) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 16e73dc..096ae29 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -220,6 +220,8 @@ func Test_LoadConfig_Clusters(t *testing.T) { assert.Equal(t, "https://k8s-api-server-url:6443", cluster.Auth.Bearer.APIServer, "cluster.Auth.Bearer.ApiServer") assert.Equal(t, "$(BEARER_TOKEN)", cluster.Auth.Bearer.BearerToken, "cluster.Auth.Bearer.BearerToken") + assert.True(t, *cluster.Auth.InCluster, "cluster.Auth.InCluster") + } func Test_LoadConfig_ConfigFileNotFound(t *testing.T) { diff --git a/internal/config/testdata/application.yaml b/internal/config/testdata/application.yaml index eee1b97..87a74d4 100644 --- a/internal/config/testdata/application.yaml +++ b/internal/config/testdata/application.yaml @@ -99,6 +99,7 @@ clusters: name: k8s infra dev env: dev auth: + inCluster: true kubeconfig: apiServer: https://host.docker.internal:56660 path: /path/to/kubeconfig diff --git a/internal/integrations/k8s/client/client.go b/internal/integrations/k8s/client/client.go index 914534e..84df365 100644 --- a/internal/integrations/k8s/client/client.go +++ b/internal/integrations/k8s/client/client.go @@ -17,12 +17,14 @@ package client import ( + "fmt" "sync" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1" corev1 "k8s.io/api/core/v1" apiruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" @@ -55,47 +57,28 @@ func GetClients() *KubeClients { once.Do(func() { clients := make(map[string]*KubeClient) clusters := config.GetAppConfig().Clusters + for _, cluster := range clusters { log.Info("K8S Cluster configuration: %+v", cluster) - var config *restclient.Config - switch cluster.AuthType() { - case constants.K8SAuthKubeConfig: - var err error - config, err = buildConfig(cluster.Auth.Kubeconfig.APIServer, cluster.Auth.Kubeconfig.Context, cluster.Auth.Kubeconfig.Path) - if err != nil { - log.Fatal("Failed to build kubeconfig for cluster ID %s and kubeconfig path: %s, details: %v", - cluster.ID, cluster.Auth.Kubeconfig.Path, err) - } - if cluster.Auth.Kubeconfig.InsecureSkipTlsVerify { - log.Warn("TLS verification is disabled for cluster ID: %s (%s).", cluster.ID, cluster.Env) - config.Insecure = true - config.CAFile = "" - config.CAData = nil - } - - if err != nil { - log.Fatal("Error building kubeconfig for cluster ID '%s (%s)': %s", cluster.ID, cluster.Env, err.Error()) - } - case constants.K8SAuthCertificate: - log.Fatal("Authentication method %s not supported for cluster ID %s", constants.K8SAuthCertificate, cluster.ID) - case constants.K8SAuthBeaer: - log.Fatal("Authentication method %s not supported for cluster ID %s", constants.K8SAuthBeaer, cluster.ID) - default: - log.Fatal("Unable to find authentication credentials for cluster ID %s", cluster.ID) + + config, err := buildConfig(cluster) + if err != nil { + log.Fatal("Failed to get config for cluster ID '%s (%s)': %v", cluster.ID, cluster.Env, err) } kubeClient, err := k8s.New(config, k8s.Options{ Scheme: newScheme(), }) - if err != nil { - log.Fatal("Error creating new k8s client for cluster ID '%s (%s)': %s", cluster.ID, cluster.Env, err.Error()) + log.Fatal("Error creating new k8s client for cluster ID '%s (%s)': %v", cluster.ID, cluster.Env, err) } clients[utils.MapKey(cluster.ID)] = &KubeClient{kubeClient, cluster.ID} } + instance = &KubeClients{clients: clients} }) + return instance } @@ -117,10 +100,54 @@ func newScheme() *apiruntime.Scheme { return scheme } -// buildConfig builds Kubernetes client config using optional apiServer URL, +// buildConfig constructs a Kubernetes REST config based on the cluster's authentication method. +// Supported auth types: +// - K8SAuthKubeConfig: uses a kubeconfig file and context. +// - K8SInCluster: uses in-cluster service account credentials. +// Unsupported auth types will return an error. +// +// Params: +// +// cluster - pointer to the cluster configuration model. +// +// Returns: +// +// *restclient.Config - Kubernetes REST configuration. +// error - any error encountered during config building. +func buildConfig(cluster *model.Cluster) (*restclient.Config, error) { + switch cluster.AuthType() { + case constants.K8SAuthKubeConfig: + config, err := buildKubeConfig( + cluster.Auth.Kubeconfig.APIServer, + cluster.Auth.Kubeconfig.Context, + cluster.Auth.Kubeconfig.Path, + ) + if err != nil { + return nil, err + } + if cluster.Auth.Kubeconfig.InsecureSkipTlsVerify { + log.Warn("TLS verification is disabled for cluster ID: %s (%s).", cluster.ID, cluster.Env) + config.Insecure = true + config.CAFile = "" + config.CAData = nil + } + return config, nil + + case constants.K8SInCluster: + return rest.InClusterConfig() + + case constants.K8SAuthCertificate, constants.K8SAuthBeaer: + return nil, fmt.Errorf("authentication method %s not supported", cluster.AuthType()) + + default: + return nil, fmt.Errorf("no authentication credentials found") + } +} + +// buildKubeConfig builds Kubernetes client config using optional apiServer URL, // optional context (defaults to current context if empty), // and explicit kubeconfig path. -func buildConfig(masterURL, context, kubeconfigPath string) (*restclient.Config, error) { +func buildKubeConfig(masterURL, context, kubeconfigPath string) (*restclient.Config, error) { loadingRules := &clientcmd.ClientConfigLoadingRules{ ExplicitPath: kubeconfigPath, } diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 16e739b..126656d 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -41,5 +41,9 @@ func (m Cluster) AuthType() string { return constants.K8SAuthBeaer } + if *m.Auth.InCluster { + return constants.K8SInCluster + } + return "" } From c21d9a7cd635fbf891052d1504667957248033e5 Mon Sep 17 00:00:00 2001 From: iizitounene Date: Mon, 26 May 2025 14:44:59 +0200 Subject: [PATCH 13/14] chore: update helm chart --- .local/keycloak.sh | 45 ++++++++-- README.md | 7 +- helm/okdp-server/Chart.yaml | 4 +- helm/okdp-server/templates/NOTES.txt | 3 +- helm/okdp-server/templates/rbac.yaml | 43 ++++++++++ helm/okdp-server/values.keycloak.yaml | 90 ++++++++++++++++---- helm/okdp-server/values.yaml | 118 ++++++++++++++++++++------ 7 files changed, 259 insertions(+), 51 deletions(-) create mode 100644 helm/okdp-server/templates/rbac.yaml diff --git a/.local/keycloak.sh b/.local/keycloak.sh index ff3e327..5289caa 100644 --- a/.local/keycloak.sh +++ b/.local/keycloak.sh @@ -1,5 +1,28 @@ #!/bin/bash +CONFIDENTIAL_CLIENT='confidential-oidc-client' +PUBLIC_CLIENT='public-oidc-client' +WEB_ORIGINS='["*"]' +REDIRECT_URIS='[ + "http://localhost:8090/oauth2/callback", + "http://localhost:8092/oauth2-redirect.html", + "http://localhost:4200/index.html", + "http://localhost:4200/silent-refresh.html", + "http://localhost:4200/home", + "http://okdp-ui.okdp.sandbox/index.html", + "https://okdp-ui.okdp.sandbox/index.html", + "http://okdp-server.okdp.sandbox/swagger/oauth2-redirect.html", + "https://okdp-server.okdp.sandbox/swagger/oauth2-redirect.html" +]' + +get_client_id() { + local client_name=$1 + /opt/keycloak/bin/kcadm.sh get clients -r master --fields id,clientId \ + | grep -B1 "\"clientId\" : \"${client_name}\"" \ + | grep '"id"' \ + | sed -E 's/.*"id" : "([^"]+)".*/\1/' +} + echo "Creating users, roles and clients ..." # Connect to kecloak @@ -35,12 +58,22 @@ echo "Creating users, roles and clients ..." /opt/keycloak/bin/kcadm.sh add-roles -r master --uusername adm1 --rolename admins # Create OAuth2 clients -/opt/keycloak/bin/kcadm.sh create clients -r master -s clientId=public-oidc-client -s name=public-oidc-client -s publicClient=true \ - -s 'redirectUris=["http://localhost:8090/oauth2/callback", "http://localhost:8092/oauth2-redirect.html", "http://localhost:4200/index.html", "http://localhost:4200/silent-refresh.html", "http://localhost:4200/home"]' \ - -s 'webOrigins=["http://localhost:8090", "http://localhost:8092", "http://localhost:4200"]' -/opt/keycloak/bin/kcadm.sh create clients -r master -s clientId=confidential-oidc-client -s name=confidential-oidc-client -s 'secret=secret1' \ - -s 'redirectUris=["http://localhost:8090/oauth2/callback", "http://localhost:8092/oauth2-redirect.html", "http://localhost:4200/index.html", "http://localhost:4200/silent-refresh.html", "http://localhost:4200/home"]' \ - -s 'webOrigins=["http://localhost:8090", "http://localhost:8092", "http://localhost:4200"]' +/opt/keycloak/bin/kcadm.sh create clients -r master -s clientId=$PUBLIC_CLIENT -s name=$PUBLIC_CLIENT -s publicClient=true \ + -s "redirectUris=${REDIRECT_URIS}" \ + -s "webOrigins=${WEB_ORIGINS}" +/opt/keycloak/bin/kcadm.sh create clients -r master -s clientId=$CONFIDENTIAL_CLIENT -s name=$CONFIDENTIAL_CLIENT -s 'secret=secret1' \ + -s "redirectUris=${REDIRECT_URIS}" \ + -s "webOrigins=${WEB_ORIGINS}" + +CONF_CLIENT_ID=$(get_client_id "$CONFIDENTIAL_CLIENT") +/opt/keycloak/bin/kcadm.sh update clients/$CONF_CLIENT_ID -r master \ + -s "redirectUris=${REDIRECT_URIS}" \ + -s "webOrigins=${WEB_ORIGINS}" + +PUB_CLIENT_ID=$(get_client_id "$PUBLIC_CLIENT") +/opt/keycloak/bin/kcadm.sh update clients/$PUB_CLIENT_ID -r master \ + -s "redirectUris=${REDIRECT_URIS}" \ + -s "webOrigins=${WEB_ORIGINS}" # Update access token lifetime echo "Update access token lifetime to 8H" diff --git a/README.md b/README.md index ea3f648..0714060 100644 --- a/README.md +++ b/README.md @@ -41,12 +41,15 @@ docker build -t quay.io/okdp/okdp-server:0.1.0-snapshot . docker push quay.io/okdp/okdp-server:0.1.0-snapshot helm package ./helm/okdp-server -helm push okdp-server-0.1.0-snapshot.tgz oci://quay.io/okdp/charts +helm push okdp-server-0.2.0-snapshot.tgz oci://quay.io/okdp/charts -helm pull oci://quay.io/okdp/charts/swagger-ui --version 0.1.0 --destination helm/okdp-server/charts +helm pull oci://quay.io/okdp/charts/swagger-ui --version 0.2.0 --destination helm/okdp-server/charts helm upgrade --install okdp-server \ --namespace okdp-server \ --create-namespace helm/okdp-server \ --values helm/okdp-server/values.keycloak.yaml ``` + +Swagger UI: https://okdp-server.okdp.sandbox/swagger/ + diff --git a/helm/okdp-server/Chart.yaml b/helm/okdp-server/Chart.yaml index cd9bf9d..c123ff0 100644 --- a/helm/okdp-server/Chart.yaml +++ b/helm/okdp-server/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: okdp-server description: A Helm chart for okdp-server type: application -version: 0.1.0 -appVersion: "0.1.0" +version: 0.2.0-snapshot +appVersion: "0.2.0-snapshot" home: https://okdp.io maintainers: - email: idir.izitounene@kubotal.io diff --git a/helm/okdp-server/templates/NOTES.txt b/helm/okdp-server/templates/NOTES.txt index acfb453..e7caee9 100644 --- a/helm/okdp-server/templates/NOTES.txt +++ b/helm/okdp-server/templates/NOTES.txt @@ -2,7 +2,8 @@ {{- if .Values.ingress.enabled }} {{- range $host := .Values.ingress.hosts }} {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + https{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + https{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}/swagger {{- end }} {{- end }} {{- else if contains "NodePort" .Values.service.type }} diff --git a/helm/okdp-server/templates/rbac.yaml b/helm/okdp-server/templates/rbac.yaml new file mode 100644 index 0000000..0a1026a --- /dev/null +++ b/helm/okdp-server/templates/rbac.yaml @@ -0,0 +1,43 @@ +{{- if .Values.rbac.create -}} +# Refine later +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "okdp-server.fullname" . }} + {{- with .Values.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "okdp-server.labels" . | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +- nonResourceURLs: + - '*' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "okdp-server.fullname" . }} + {{- with .Values.rbac.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "okdp-server.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "okdp-server.serviceAccountName" $ }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "okdp-server.fullname" $ }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/helm/okdp-server/values.keycloak.yaml b/helm/okdp-server/values.keycloak.yaml index a48dc77..96a0f26 100644 --- a/helm/okdp-server/values.keycloak.yaml +++ b/helm/okdp-server/values.keycloak.yaml @@ -1,4 +1,74 @@ configuration: + # -- List of Kubernetes clusters this chart will interact with + clusters: + - id: kubo2 # -- Unique identifier for the cluster + name: "My k8s cluster 1" # -- Human-readable name for the cluster + env: dev # -- Environment tag (e.g., dev, staging, prod) + + auth: + # -- Use in-cluster authentication + inCluster: true + + # kubeconfig: + # apiServer: https://host.docker.internal:56660 # -- Kubernetes API server address + # path: /tmp/.kube/config # -- Path to the kubeconfig file + # # context: kind-kind-okdp-sandbox # -- Optional: specify kubeconfig context to use + # insecureSkipTlsVerify: true # -- Skip TLS verification (not recommended in production) + + # -- Optional certificate-based authentication + # certificate: + # apiServer: https://k8s-api-server-url:6443 # -- API server for certificate auth + # clientKey: /path/to/client-key.pem # -- Path to client key + # clientCert: /path/to/client-cert.pem # -- Path to client certificate + # caCert: /path/to/ca-cert.pem # -- Path to CA certificate + + # -- Optional bearer token authentication + # bearer: + # apiServer: https://k8s-api-server-url:6443 # -- API server for bearer token auth + # bearerToken: $(BEARER_TOKEN) # -- Bearer token used to authenticate + + # -- List of catalogs available to this chart + catalog: + - id: storage # -- Unique identifier for the catalog + name: "Storage catalog" # -- Human-readable name of the catalog + description: "My Storage packages" # -- Description of the catalog's purpose + repoUrl: quay.io/kubocd/packages # -- OCI registry URL to pull packages from + + # -- Credentials for private registries (optional) + #credentials: + # robotAccountName: $(OCI_USERNAME) # -- Robot account username for private registry + # robotAccountToken: $(OCI_PASSWORD) # -- Robot account token for private registry + # dockerconfigjson: $(DOCKER_CONFIG_JSON) # -- Base64-encoded Docker config JSON + + # -- List of packages under this catalog + packages: + - name: redis # -- Name of the package + - name: minio + - name: cnpg + + - id: auth + name: "Auth catalog" + description: "My Auth packages" + repoUrl: quay.io/kubocd/packages + packages: + - name: openldap + + - id: infra + name: "Infra catalog" + description: "My Infra packages" + repoUrl: quay.io/kubocd/packages + packages: + - name: cert-manager + - name: ingress-nginx + - name: metallb + + - id: stack + name: "Stack catalog" + description: "My Stack packages" + repoUrl: quay.io/kubocd/packages + packages: + - name: podinfo + server: # -- Specify the Server listen address. listenAddress: 0.0.0.0 @@ -19,9 +89,9 @@ configuration: provider: ["bearer"] bearer: # -- Specify the issuer uri. - issuerUri: "http://keycloak.okdp.sandbox/realms/master" + issuerUri: "http://keycloak:7080/realms/master" # -- Specify the jwks URL. - jwksURL: "http://keycloak.okdp.sandbox/realms/master/protocol/openid-connect/certs" + jwksURL: "http://keycloak:7080/realms/master/protocol/openid-connect/certs" # -- Specify the roles attribute path from json access token. rolesAttributePath: "realm_access.roles" # -- Specify the groups attribute path from json access token. @@ -105,8 +175,8 @@ configuration: type: oauth2 flows: authorizationCode: - authorizationUrl: http://keycloak.okdp.sandbox/realms/master/protocol/openid-connect/auth - tokenUrl: http://keycloak.okdp.sandbox/realms/master/protocol/openid-connect/token + authorizationUrl: http://keycloak:7080/realms/master/protocol/openid-connect/auth + tokenUrl: http://keycloak:7080/realms/master/protocol/openid-connect/token scopes: openid: OpenId Authentication email: User Email @@ -115,18 +185,6 @@ configuration: security: - oauth2: [openid, email, profile, roles] - kad: - # -- Specify any ID. - - id: sandbox - # -- Specify any name. - name: Poc Sandbox - # -- Specify KAD API URL. - apiUrl: "kad.okdp.sandbox" - # -- Specify KAD AUTH Bearer. - authBearer: "4Ys3brdqnD5LVjf6hLcQsSQbHWLh5asJ" - # -- Wether to skip the certificate validation. - insecureSkipVerify: true - swagger-ui: enabled: true configuration: diff --git a/helm/okdp-server/values.yaml b/helm/okdp-server/values.yaml index 82da89f..a5f764c 100644 --- a/helm/okdp-server/values.yaml +++ b/helm/okdp-server/values.yaml @@ -7,7 +7,7 @@ image: # -- Image pull policy. pullPolicy: Always # -- Image tag. - tag: "0.1.0" + tag: "0.2.0" # -- Secrets to be used for pulling images from private Docker registries. imagePullSecrets: [] @@ -17,6 +17,85 @@ nameOverride: "" fullnameOverride: "" configuration: + # -- List of Kubernetes clusters this chart will interact with + clusters: + # -- Unique identifier for the cluster + - id: kubo2 + # -- Human-readable name for the cluster + name: "My k8s cluster 1" + # -- Environment tag (e.g., dev, staging, prod) + env: dev + auth: + # -- Use in-cluster authentication + inCluster: true + # kubeconfig: + # apiServer: https://host.docker.internal:56660 # -- Kubernetes API server address + # path: /tmp/.kube/config # -- Path to the kubeconfig file + # # context: kind-kind-okdp-sandbox # -- Optional: specify kubeconfig context to use + # insecureSkipTlsVerify: true # -- Skip TLS verification (not recommended in production) + + # -- Optional certificate-based authentication + # certificate: + # apiServer: https://k8s-api-server-url:6443 # -- API server for certificate auth + # clientKey: /path/to/client-key.pem # -- Path to client key + # clientCert: /path/to/client-cert.pem # -- Path to client certificate + # caCert: /path/to/ca-cert.pem # -- Path to CA certificate + + # -- Optional bearer token authentication + # bearer: + # apiServer: https://k8s-api-server-url:6443 # -- API server for bearer token auth + # bearerToken: $(BEARER_TOKEN) # -- Bearer token used to authenticate + + # -- List of catalogs available to this chart + catalog: + # -- Unique identifier for the catalog + - id: storage + # -- Human-readable name of the catalog + name: "Storage catalog" + # -- Description of the catalog's purpose + description: "My Storage packages" + # -- OCI registry URL to pull packages from + repoUrl: quay.io/kubocd/packages + + # -- Credentials for private registries (optional) + # credentials: + # -- Robot account username for private registry + # robotAccountName: $(OCI_USERNAME) + # -- Robot account token for private registry + # robotAccountToken: $(OCI_PASSWORD) + # -- Base64-encoded Docker config JSON + # dockerconfigjson: $(DOCKER_CONFIG_JSON) + + # -- List of packages under this catalog + packages: + # -- Name of the package + - name: redis + - name: minio + - name: cnpg + + - id: auth + name: "Auth catalog" + description: "My Auth packages" + repoUrl: quay.io/kubocd/packages + packages: + - name: openldap + + - id: infra + name: "Infra catalog" + description: "My Infra packages" + repoUrl: quay.io/kubocd/packages + packages: + - name: cert-manager + - name: ingress-nginx + - name: metallb + + - id: stack + name: "Stack catalog" + description: "My Stack packages" + repoUrl: quay.io/kubocd/packages + packages: + - name: podinfo + server: # -- Specify the Server listen address. listenAddress: 0.0.0.0 @@ -69,16 +148,12 @@ configuration: inline: policy: | p, role:viewers, /api/v1/users/myprofile, * - p, role:viewers, /api/v1/kad, * - p, role:viewers, /api/v1/kad/*/services, * - p, role:viewers, /api/v1/kad/*/catalog, * - p, role:viewers, /api/v1/kad/*/catalog/*, * - p, role:viewers, /api/v1/kad/*/componentreleases, * - p, role:viewers, /api/v1/kad/*/componentreleases/*, * - p, role:viewers, /api/v1/kad/*/templatereleases, * - p, role:viewers, /api/v1/kad/*/templatereleases/*, * - p, role:viewers, /api/v1/kad/*/components, * - p, role:viewers, /api/v1/kad/*/components/*, * + p, role:viewers, /api/v1/catalogs, * + p, role:viewers, /api/v1/catalogs/*, * + + p, role:viewers, /api/v1/clusters, * + p, role:viewers, /api/v1/clusters/*/gitrepos, * + p, role:viewers, /api/v1/clusters/*/gitrepos/*, * g, role:admins, role:developers g, role:developers, role:viewers @@ -135,17 +210,6 @@ configuration: security: - oauth2: [openid, email, profile, roles] - kad: - # -- Specify any ID. - - id: sandbox - # -- Specify any name. - name: Poc Sandbox - # -- Specify KAD API URL. - apiUrl: "" - # -- Specify KAD AUTH Bearer. - authBearer: "" - # -- Wether to skip the certificate validation. - insecureSkipVerify: true swagger-ui: # — Whether to enable or disable swagger UI. enabled: true @@ -173,15 +237,21 @@ swagger-ui: serviceAccount: # -- Specify whether a service account should be created - create: false + create: true # -- Automatically mount a ServiceAccount's API credentials? - automount: false + automount: true # -- Annotations to add to the service account annotations: {} # -- The name of the service account to use. # -- If not set and create is true, a name is generated using the fullname template name: "" +rbac: + # -- Specify whether a RBAC should be created + create: true + # -- Specify annotations for the proxy. + annotations: {} + # -- Additional annotations for the okdp-server pod. podAnnotations: {} # -- Additional labels for the okdp-server pod. From 0430e73126eff0a6439c2fda085bfbb3c5064aaa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 13:35:15 +0000 Subject: [PATCH 14/14] [helm-docs] Update readme --- helm/okdp-server/README.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/helm/okdp-server/README.md b/helm/okdp-server/README.md index 75e28e8..0d74a4a 100644 --- a/helm/okdp-server/README.md +++ b/helm/okdp-server/README.md @@ -1,6 +1,6 @@ # okdp-server -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.0](https://img.shields.io/badge/AppVersion-0.1.0-informational?style=flat-square) +![Version: 0.2.0-snapshot](https://img.shields.io/badge/Version-0.2.0--snapshot-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.2.0-snapshot](https://img.shields.io/badge/AppVersion-0.2.0--snapshot-informational?style=flat-square) A Helm chart for okdp-server @@ -31,11 +31,18 @@ A Helm chart for okdp-server | autoscaling.maxReplicas | int | `100` | | | autoscaling.minReplicas | int | `1` | | | autoscaling.targetCPUUtilizationPercentage | int | `80` | | -| configuration.kad[0] | object | `{"apiUrl":"","authBearer":"","id":"sandbox","insecureSkipVerify":true,"name":"Poc Sandbox"}` | Specify any ID. | -| configuration.kad[0].apiUrl | string | `""` | Specify KAD API URL. | -| configuration.kad[0].authBearer | string | `""` | Specify KAD AUTH Bearer. | -| configuration.kad[0].insecureSkipVerify | bool | `true` | Wether to skip the certificate validation. | -| configuration.kad[0].name | string | `"Poc Sandbox"` | Specify any name. | +| configuration.catalog | list | `[{"description":"My Storage packages","id":"storage","name":"Storage catalog","packages":[{"name":"redis"},{"name":"minio"},{"name":"cnpg"}],"repoUrl":"quay.io/kubocd/packages"},{"description":"My Auth packages","id":"auth","name":"Auth catalog","packages":[{"name":"openldap"}],"repoUrl":"quay.io/kubocd/packages"},{"description":"My Infra packages","id":"infra","name":"Infra catalog","packages":[{"name":"cert-manager"},{"name":"ingress-nginx"},{"name":"metallb"}],"repoUrl":"quay.io/kubocd/packages"},{"description":"My Stack packages","id":"stack","name":"Stack catalog","packages":[{"name":"podinfo"}],"repoUrl":"quay.io/kubocd/packages"}]` | List of catalogs available to this chart | +| configuration.catalog[0] | object | `{"description":"My Storage packages","id":"storage","name":"Storage catalog","packages":[{"name":"redis"},{"name":"minio"},{"name":"cnpg"}],"repoUrl":"quay.io/kubocd/packages"}` | Unique identifier for the catalog | +| configuration.catalog[0].description | string | `"My Storage packages"` | Description of the catalog's purpose | +| configuration.catalog[0].name | string | `"Storage catalog"` | Human-readable name of the catalog | +| configuration.catalog[0].packages | list | `[{"name":"redis"},{"name":"minio"},{"name":"cnpg"}]` | List of packages under this catalog | +| configuration.catalog[0].packages[0] | object | `{"name":"redis"}` | Name of the package | +| configuration.catalog[0].repoUrl | string | `"quay.io/kubocd/packages"` | OCI registry URL to pull packages from | +| configuration.clusters | list | `[{"auth":{"inCluster":true},"env":"dev","id":"kubo2","name":"My k8s cluster 1"}]` | List of Kubernetes clusters this chart will interact with | +| configuration.clusters[0] | object | `{"auth":{"inCluster":true},"env":"dev","id":"kubo2","name":"My k8s cluster 1"}` | Unique identifier for the cluster | +| configuration.clusters[0].auth.inCluster | bool | `true` | Use in-cluster authentication | +| configuration.clusters[0].env | string | `"dev"` | Environment tag (e.g., dev, staging, prod) | +| configuration.clusters[0].name | string | `"My k8s cluster 1"` | Human-readable name for the cluster | | configuration.logging.format | string | `"console"` | Specify the logging format. One of `console` or `json`. | | configuration.logging.level | string | `"debug"` | Specify the logging level. One of `debug`, `info`, `warn`, `error`, `fatal` or `panic`. | | configuration.security.authN.bearer.groupsAttributePath | string | `"realm_access.groups"` | Specify the groups attribute path from json access token. | @@ -45,7 +52,7 @@ A Helm chart for okdp-server | configuration.security.authN.bearer.skipIssuerCheck | bool | `false` | Wether to skip issuer check. | | configuration.security.authN.bearer.skipSignatureCheck | bool | `false` | Wether to skip issuer signature check. | | configuration.security.authN.provider | list | `["bearer"]` | Specify the oidc privider. One of `openid` or `bearer`. | -| configuration.security.authZ.inline | object | `{"model":"[request_definition]\nr = sub, obj, act\n\n[policy_definition]\np = sub, obj, act\n\n[role_definition]\ng = _, _\n\n[policy_effect]\ne = some(where (p.eft == allow))\n\n[matchers]\nm = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == \"*\")\n","policy":"p, role:viewers, /api/v1/users/myprofile, *\np, role:viewers, /api/v1/kad, *\np, role:viewers, /api/v1/kad/*/services, *\np, role:viewers, /api/v1/kad/*/catalog, *\np, role:viewers, /api/v1/kad/*/catalog/*, *\np, role:viewers, /api/v1/kad/*/componentreleases, *\np, role:viewers, /api/v1/kad/*/componentreleases/*, *\np, role:viewers, /api/v1/kad/*/templatereleases, *\np, role:viewers, /api/v1/kad/*/templatereleases/*, *\np, role:viewers, /api/v1/kad/*/components, *\np, role:viewers, /api/v1/kad/*/components/*, *\n\ng, role:admins, role:developers\ng, role:developers, role:viewers\n"}` | More info: https://casbin.org/docs/how-it-works/ file: modelPath: ".local/authz-model.conf" policyPath: ".local/authz-policy.csv" | +| configuration.security.authZ.inline | object | `{"model":"[request_definition]\nr = sub, obj, act\n\n[policy_definition]\np = sub, obj, act\n\n[role_definition]\ng = _, _\n\n[policy_effect]\ne = some(where (p.eft == allow))\n\n[matchers]\nm = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == \"*\")\n","policy":"p, role:viewers, /api/v1/users/myprofile, *\np, role:viewers, /api/v1/catalogs, *\np, role:viewers, /api/v1/catalogs/*, *\n\np, role:viewers, /api/v1/clusters, *\np, role:viewers, /api/v1/clusters/*/gitrepos, *\np, role:viewers, /api/v1/clusters/*/gitrepos/*, *\n\ng, role:admins, role:developers\ng, role:developers, role:viewers\n"}` | More info: https://casbin.org/docs/how-it-works/ file: modelPath: ".local/authz-model.conf" policyPath: ".local/authz-policy.csv" | | configuration.security.authZ.inline.model | string | `"[request_definition]\nr = sub, obj, act\n\n[policy_definition]\np = sub, obj, act\n\n[role_definition]\ng = _, _\n\n[policy_effect]\ne = some(where (p.eft == allow))\n\n[matchers]\nm = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == \"*\")\n"` | More info: https://casbin.org/docs/how-it-works/ | | configuration.security.authZ.provider | string | `"inline"` | Specify the authZ storage provider. One of `inline` or `file`. | | configuration.security.cors.allowCredentials | bool | `true` | Determine whether cookies and authentication credentials should be included in cross-origin requests. | @@ -73,7 +80,7 @@ A Helm chart for okdp-server | fullnameOverride | string | `""` | Overrides the release name. | | image.pullPolicy | string | `"Always"` | Image pull policy. | | image.repository | string | `"quay.io/okdp/okdp-server"` | Docker image registry. | -| image.tag | string | `"0.1.0"` | Image tag. | +| image.tag | string | `"0.2.0"` | Image tag. | | imagePullSecrets | list | `[]` | Secrets to be used for pulling images from private Docker registries. | | ingress.annotations | object | `{}` | | | ingress.className | string | `""` | Specify the ingress class (Kubernetes >= 1.18). | @@ -88,6 +95,8 @@ A Helm chart for okdp-server | podAnnotations | object | `{}` | Additional annotations for the okdp-server pod. | | podLabels | object | `{}` | Additional labels for the okdp-server pod. | | podSecurityContext | object | `{}` | | +| rbac.annotations | object | `{}` | Specify annotations for the proxy. | +| rbac.create | bool | `true` | Specify whether a RBAC should be created | | readinessProbe | object | `{"httpGet":{"path":"/readiness","port":"http"}}` | Readiness probe for the okdp-server container. | | replicaCount | int | `1` | Desired number of okdp-server pods to run. | | resources | object | `{}` | | @@ -95,8 +104,8 @@ A Helm chart for okdp-server | service.port | int | `8090` | | | service.type | string | `"ClusterIP"` | | | serviceAccount.annotations | object | `{}` | Annotations to add to the service account | -| serviceAccount.automount | bool | `false` | Automatically mount a ServiceAccount's API credentials? | -| serviceAccount.create | bool | `false` | Specify whether a service account should be created | +| serviceAccount.automount | bool | `true` | Automatically mount a ServiceAccount's API credentials? | +| serviceAccount.create | bool | `true` | Specify whether a service account should be created | | serviceAccount.name | string | `""` | If not set and create is true, a name is generated using the fullname template | | swagger-ui.configuration.extraEnv | list | `[{"name":"BASE_URL","value":"/"},{"name":"URLS","value":null},{"name":"OAUTH_CLIENT_ID","value":null},{"name":"OAUTH_SCOPES","value":"openid profile email roles"},{"name":"OAUTH_USE_PKCE","value":true},{"name":"CORS_ENABLED","value":true}]` | Specify swagger configuration with environment variables (https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/) | | swagger-ui.configuration.extraEnv[0] | object | `{"name":"BASE_URL","value":"/"}` | Specify base url. |