From f8b5b6dbd8b41cee3fd3cc7c83be48b8f3d80135 Mon Sep 17 00:00:00 2001 From: Max Lambrecht Date: Tue, 23 May 2023 18:58:10 -0500 Subject: [PATCH] Defining Harvester admin API Signed-off-by: Max Lambrecht --- Makefile | 108 ++--- pkg/harvester/api/admin/admin.cfg.yaml | 11 + pkg/harvester/api/admin/admin.gen.go | 635 +++++++++++++++++++++++++ pkg/harvester/api/admin/admin.yaml | 96 ++++ pkg/server/db/README.md | 2 +- 5 files changed, 797 insertions(+), 55 deletions(-) create mode 100644 pkg/harvester/api/admin/admin.cfg.yaml create mode 100644 pkg/harvester/api/admin/admin.gen.go create mode 100644 pkg/harvester/api/admin/admin.yaml diff --git a/Makefile b/Makefile index 86d52fc93..7acfc17a8 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,19 @@ -include Makefile-poc.mk -DIR := ${CURDIR} +DIR := $(CURDIR) .DEFAULT_GOAL = help -E:=@ +E := @ ifeq ($(V),1) - E= + E = endif cyan := $(shell which tput > /dev/null && tput setaf 6 2>/dev/null || echo "") reset := $(shell which tput > /dev/null && tput sgr0 2>/dev/null || echo "") -bold := $(shell which tput > /dev/null && tput bold 2>/dev/null || echo "") +bold := $(shell which tput > /dev/null && tput bold 2>/dev/null || echo "") -.PHONY: default +.PHONY: default default: build @@ -22,33 +22,32 @@ all: build test ############################################################################ # OS/ARCH detection ############################################################################ -os1=$(shell uname -s) -os2= +os1 := $(shell uname -s) +os2 := ifeq ($(os1),Darwin) -os1=darwin -os2=osx +os1 := darwin +os2 := osx else ifeq ($(os1),Linux) -os1=linux -os2=linux +os1 := linux +os2 := linux else ifeq (,$(findstring MYSYS_NT-10-0-, $(os1))) -os1=windows -os2=windows +os1 := windows +os2 := windows else $(error unsupported OS: $(os1)) endif -arch1=$(shell uname -m) +arch1 := $(shell uname -m) ifeq ($(arch1),x86_64) -arch2=amd64 +arch2 := amd64 else ifeq ($(arch1),aarch64) -arch2=arm64 +arch2 := arm64 else ifeq ($(arch1),arm64) -arch2=arm64 +arch2 := arm64 else $(error unsupported ARCH: $(arch1)) endif - ############################################################################ # Vars ############################################################################ @@ -56,35 +55,35 @@ endif build_dir := $(DIR)/.build/$(os1)-$(arch1) go_version_full := $(shell cat .go-version) -go_version := $(go_version_full:.0=) +go_version := $(subst .0,,$(go_version_full)) go_dir := $(build_dir)/go/$(go_version) ifeq ($(os1),windows) - go_bin_dir = $(go_dir)/go/bin - go_url = https://storage.googleapis.com/golang/go$(go_version).$(os1)-$(arch2).zip - exe=".exe" -else - go_bin_dir = $(go_dir)/bin - go_url = https://storage.googleapis.com/golang/go$(go_version).$(os1)-$(arch2).tar.gz - exe= +go_bin_dir := $(go_dir)/go/bin +go_url := https://storage.googleapis.com/golang/go$(go_version).$(os1)-$(arch2).zip +exe := .exe +else +go_bin_dir := $(go_dir)/bin +go_url := https://storage.googleapis.com/golang/go$(go_version).$(os1)-$(arch2).tar.gz +exe := endif go_path := PATH="$(go_bin_dir):$(PATH)" -oapi_codegen_version = 1.12.4 -oapi_codegen_dir = $(build_dir)/protoc/$(protoc_version):q +oapi_codegen_version := 1.12.4 +oapi_codegen_dir := $(build_dir)/protoc/$(protoc_version) -server_sqlc_config_file = $(DIR)/pkg/server/db/sqlc.yaml +server_sqlc_config_file := $(DIR)/pkg/server/db/sqlc.yaml -sqlc_dir = $(build_dir)/sqlc/$(sqlc_version) -sqlc_bin = $(sqlc_dir)/sqlc -sqlc_version = 1.18.0 +sqlc_dir := $(build_dir)/sqlc/$(sqlc_version) +sqlc_bin := $(sqlc_dir)/sqlc +sqlc_version := 1.18.0 ifeq ($(os1),windows) - sqlc_url = https://github.com/kyleconroy/sqlc/releases/download/v${sqlc_version}/sqlc_${sqlc_version}_windows_amd64.zip +sqlc_url := https://github.com/kyleconroy/sqlc/releases/download/v$(sqlc_version)/sqlc_$(sqlc_version)_windows_amd64.zip else ifeq ($(os1),darwin) - sqlc_url = https://github.com/kyleconroy/sqlc/releases/download/v${sqlc_version}/sqlc_${sqlc_version}_darwin_$(arch2).zip +sqlc_url := https://github.com/kyleconroy/sqlc/releases/download/v$(sqlc_version)/sqlc_$(sqlc_version)_darwin_$(arch2).zip else - sqlc_url = https://github.com/kyleconroy/sqlc/releases/download/v${sqlc_version}/sqlc_${sqlc_version}_linux_amd64.zip +sqlc_url := https://github.com/kyleconroy/sqlc/releases/download/v$(sqlc_version)/sqlc_$(sqlc_version)_linux_amd64.zip endif go-check: @@ -113,8 +112,8 @@ $(sqlc_bin): # The following vars are used in rule construction comma := , -null := -space := $(null) +null := +space := $(null) .PHONY: build @@ -125,7 +124,7 @@ build: bin/galadriel-harvester bin/galadriel-server define binary_rule .PHONY: $1 $1: | go-check bin/ - @echo Building $1... + @echo "Building $1..." $(E)$(go_path) go build -o $1 $2 endef @@ -137,9 +136,8 @@ $(eval $(call binary_rule,bin/galadriel-server,cmd/server/main.go)) bin/: @mkdir -p $@ -CONTAINER_OPTIONS = docker podman -CONTAINER_EXEC := $(foreach exec,$(CONTAINER_OPTIONS),\ - $(if $(shell which $(exec)),$(exec))) +CONTAINER_OPTIONS := docker podman +CONTAINER_EXEC := $(shell command -v $(CONTAINER_OPTIONS) 2> /dev/null) server-run: build ./bin/galadriel-server run @@ -176,16 +174,17 @@ docker-build: docker-build-server docker-build-harvester #------------------------------------------------------------------------ # VARIABLES -NAME = Galadriel -VERSION = 0.1.0 -AUTHOR=HPE +NAME := Galadriel +VERSION := 0.1.0 +AUTHOR := HPE # COLORS GREEN := $(shell tput -Txterm setaf 2) RESET := $(shell tput -Txterm sgr0) -TARGET_MAX_CHAR_NUM=30 +TARGET_MAX_CHAR_NUM := 30 +## Shows help. ## Shows help. help: @echo "$(bold)Usage:$(reset) make $(cyan)$(reset)" @@ -200,20 +199,21 @@ help: @echo " $(cyan)all$(reset) - build all Galadriel binaries, and run unit tests" @echo @echo "$(bold)Code generation:$(reset)" - @echo " $(cyan)generate$(reset) - generate datastore sql and api boileplate code" - -### Code generation #### -.PHONY: generate-sqlc-server generete-spec + @echo " $(cyan)generate-sql-code$(reset) - generate SQL code using sqlc" + @echo " $(cyan)generate-api-code$(reset) - generate API code using oapi-codegen" -# Run sqlc to generate sql code -generate-sqlc-code: install-sqlc run-generate-sqlc +.PHONY: generate-sql-code generate-api-code -run-generate-sqlc: +# Run sqlc to generate SQL code for the server +generate-sql-code: install-sqlc $(server_sqlc_config_file) + @echo "Generating server SQL code..." $(sqlc_bin) generate --file $(server_sqlc_config_file) -# Run oapi-codegen to generate api code -generate-spec: +# Specify the input specification files as prerequisites for generate-api-code +generate-api-code: $(SPEC_FILES) + @echo "Generating API code..." go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v$(oapi_codegen_version) cd ./pkg/common/api; $(GOPATH)/bin/oapi-codegen -config schemas.cfg.yaml schemas.yaml cd ./pkg/server/api/admin; $(GOPATH)/bin/oapi-codegen -config admin.cfg.yaml admin.yaml cd ./pkg/server/api/harvester; $(GOPATH)/bin/oapi-codegen -config harvester.cfg.yaml harvester.yaml + cd ./pkg/harvester/api/admin; $(GOPATH)/bin/oapi-codegen -config admin.cfg.yaml admin.yaml diff --git a/pkg/harvester/api/admin/admin.cfg.yaml b/pkg/harvester/api/admin/admin.cfg.yaml new file mode 100644 index 000000000..b6775c2c4 --- /dev/null +++ b/pkg/harvester/api/admin/admin.cfg.yaml @@ -0,0 +1,11 @@ +package: admin +generate: + echo-server: true + client: true + models: true + embedded-spec: true +import-mapping: + ../../../common/api/schemas.yaml: github.com/HewlettPackard/galadriel/pkg/common/api +output: admin.gen.go +output-options: + skip-prune: true diff --git a/pkg/harvester/api/admin/admin.gen.go b/pkg/harvester/api/admin/admin.gen.go new file mode 100644 index 000000000..c9ea46e50 --- /dev/null +++ b/pkg/harvester/api/admin/admin.gen.go @@ -0,0 +1,635 @@ +// Package admin provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT. +package admin + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + + externalRef0 "github.com/HewlettPackard/galadriel/pkg/common/api" + "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" +) + +const ( + Harvester_authScopes = "harvester_auth.Scopes" +) + +// PatchRelationship defines model for PatchRelationship. +type PatchRelationship struct { + ConsentStatus externalRef0.ConsentStatus `json:"consent_status"` +} + +// Default defines model for Default. +type Default = externalRef0.ApiError + +// GetRelationshipsParams defines parameters for GetRelationships. +type GetRelationshipsParams struct { + ConsentStatus *externalRef0.ConsentStatus `form:"consentStatus,omitempty" json:"consentStatus,omitempty"` +} + +// PatchRelationshipJSONRequestBody defines body for PatchRelationship for application/json ContentType. +type PatchRelationshipJSONRequestBody = PatchRelationship + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + return &client, nil +} + +// WithHTTPClient allows overriding the default Doer, which is +// automatically created using http.Client. This is useful for tests. +func WithHTTPClient(doer HttpRequestDoer) ClientOption { + return func(c *Client) error { + c.Client = doer + return nil + } +} + +// WithRequestEditorFn allows setting up a callback function, which will be +// called right before sending the request. This can be used to mutate the request. +func WithRequestEditorFn(fn RequestEditorFn) ClientOption { + return func(c *Client) error { + c.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // GetRelationships request + GetRelationships(ctx context.Context, params *GetRelationshipsParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // PatchRelationship request with any body + PatchRelationshipWithBody(ctx context.Context, relationshipID externalRef0.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + PatchRelationship(ctx context.Context, relationshipID externalRef0.UUID, body PatchRelationshipJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) GetRelationships(ctx context.Context, params *GetRelationshipsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetRelationshipsRequest(c.Server, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) PatchRelationshipWithBody(ctx context.Context, relationshipID externalRef0.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPatchRelationshipRequestWithBody(c.Server, relationshipID, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) PatchRelationship(ctx context.Context, relationshipID externalRef0.UUID, body PatchRelationshipJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPatchRelationshipRequest(c.Server, relationshipID, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewGetRelationshipsRequest generates requests for GetRelationships +func NewGetRelationshipsRequest(server string, params *GetRelationshipsParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/relationships") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.ConsentStatus != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "consentStatus", runtime.ParamLocationQuery, *params.ConsentStatus); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPatchRelationshipRequest calls the generic PatchRelationship builder with application/json body +func NewPatchRelationshipRequest(server string, relationshipID externalRef0.UUID, body PatchRelationshipJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewPatchRelationshipRequestWithBody(server, relationshipID, "application/json", bodyReader) +} + +// NewPatchRelationshipRequestWithBody generates requests for PatchRelationship with any type of body +func NewPatchRelationshipRequestWithBody(server string, relationshipID externalRef0.UUID, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "relationshipID", runtime.ParamLocationPath, relationshipID) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/relationships/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PATCH", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses creates a new ClientWithResponses, which wraps +// Client with return type handling +func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { + client, err := NewClient(server, opts...) + if err != nil { + return nil, err + } + return &ClientWithResponses{client}, nil +} + +// WithBaseURL overrides the baseURL. +func WithBaseURL(baseURL string) ClientOption { + return func(c *Client) error { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // GetRelationships request + GetRelationshipsWithResponse(ctx context.Context, params *GetRelationshipsParams, reqEditors ...RequestEditorFn) (*GetRelationshipsResponse, error) + + // PatchRelationship request with any body + PatchRelationshipWithBodyWithResponse(ctx context.Context, relationshipID externalRef0.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PatchRelationshipResponse, error) + + PatchRelationshipWithResponse(ctx context.Context, relationshipID externalRef0.UUID, body PatchRelationshipJSONRequestBody, reqEditors ...RequestEditorFn) (*PatchRelationshipResponse, error) +} + +type GetRelationshipsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]externalRef0.Relationship + JSONDefault *externalRef0.ApiError +} + +// Status returns HTTPResponse.Status +func (r GetRelationshipsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetRelationshipsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PatchRelationshipResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *externalRef0.Relationship + JSONDefault *externalRef0.ApiError +} + +// Status returns HTTPResponse.Status +func (r PatchRelationshipResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PatchRelationshipResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// GetRelationshipsWithResponse request returning *GetRelationshipsResponse +func (c *ClientWithResponses) GetRelationshipsWithResponse(ctx context.Context, params *GetRelationshipsParams, reqEditors ...RequestEditorFn) (*GetRelationshipsResponse, error) { + rsp, err := c.GetRelationships(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetRelationshipsResponse(rsp) +} + +// PatchRelationshipWithBodyWithResponse request with arbitrary body returning *PatchRelationshipResponse +func (c *ClientWithResponses) PatchRelationshipWithBodyWithResponse(ctx context.Context, relationshipID externalRef0.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PatchRelationshipResponse, error) { + rsp, err := c.PatchRelationshipWithBody(ctx, relationshipID, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParsePatchRelationshipResponse(rsp) +} + +func (c *ClientWithResponses) PatchRelationshipWithResponse(ctx context.Context, relationshipID externalRef0.UUID, body PatchRelationshipJSONRequestBody, reqEditors ...RequestEditorFn) (*PatchRelationshipResponse, error) { + rsp, err := c.PatchRelationship(ctx, relationshipID, body, reqEditors...) + if err != nil { + return nil, err + } + return ParsePatchRelationshipResponse(rsp) +} + +// ParseGetRelationshipsResponse parses an HTTP response from a GetRelationshipsWithResponse call +func ParseGetRelationshipsResponse(rsp *http.Response) (*GetRelationshipsResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetRelationshipsResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []externalRef0.Relationship + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && true: + var dest externalRef0.ApiError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSONDefault = &dest + + } + + return response, nil +} + +// ParsePatchRelationshipResponse parses an HTTP response from a PatchRelationshipWithResponse call +func ParsePatchRelationshipResponse(rsp *http.Response) (*PatchRelationshipResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PatchRelationshipResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest externalRef0.Relationship + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && true: + var dest externalRef0.ApiError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSONDefault = &dest + + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // List the relationships. + // (GET /relationships) + GetRelationships(ctx echo.Context, params GetRelationshipsParams) error + // Accept/Denies relationship requests + // (PATCH /relationships/{relationshipID}) + PatchRelationship(ctx echo.Context, relationshipID externalRef0.UUID) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// GetRelationships converts echo context to params. +func (w *ServerInterfaceWrapper) GetRelationships(ctx echo.Context) error { + var err error + + ctx.Set(Harvester_authScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetRelationshipsParams + // ------------- Optional query parameter "consentStatus" ------------- + + err = runtime.BindQueryParameter("form", true, false, "consentStatus", ctx.QueryParams(), ¶ms.ConsentStatus) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter consentStatus: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetRelationships(ctx, params) + return err +} + +// PatchRelationship converts echo context to params. +func (w *ServerInterfaceWrapper) PatchRelationship(ctx echo.Context) error { + var err error + // ------------- Path parameter "relationshipID" ------------- + var relationshipID externalRef0.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "relationshipID", runtime.ParamLocationPath, ctx.Param("relationshipID"), &relationshipID) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter relationshipID: %s", err)) + } + + ctx.Set(Harvester_authScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PatchRelationship(ctx, relationshipID) + return err +} + +// This is a simple interface which specifies echo.Route addition functions which +// are present on both echo.Echo and echo.Group, since we want to allow using +// either of them for path registration +type EchoRouter interface { + CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router EchoRouter, si ServerInterface) { + RegisterHandlersWithBaseURL(router, si, "") +} + +// Registers handlers, and prepends BaseURL to the paths, so that the paths +// can be served under a prefix. +func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.GET(baseURL+"/relationships", wrapper.GetRelationships) + router.PATCH(baseURL+"/relationships/:relationshipID", wrapper.PatchRelationship) + +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/8xW227bOBD9FYHbR91sJ26iN2+dtAay3aBpXzbwGrQ0ktiVKIYcxTUC/ftiKN8Uuc2l", + "XWCfTIvkzJlzDsl5YHFVqkqCRMOiB6bBqEoasH+mkPK6QBrGlUSQdsiVKkTMUVQy+GoqSd9MnEPJafRG", + "Q8oi9luwjxu0syaYKHGhdaVZ0zQuS8DEWiiKwyJmJ5zJ9czZQ6BVm70UeredQCSJoJ28uNaVAo2CIKe8", + "MOAydfCJoCdAv2mlS44sYkLi+IS5rOTfRFmXLDo9P3dZKWT7bxCGLsO1gnYpZKBZ47ISjOGZjQTfeKkK", + "mp84S+A1irQuHLAVbJe5+3wGtZBZm/AKZIY5i4YHSTbzVK2Gu1poSFh02+Le553v1lfLrxAjYXpHPEm8", + "QY61rRUkVXBLGunqHhJGNEthBwpkQnnmvcQuu+YY55+gsKqaXKgXc2yBLMwOyY980IXdr7sT61jdP4NU", + "A0dIFhy7Sg7D4cALB94o/ByeRaMwCsO/DkVMOIKHooRHOg6OsCmSpxj48mU2pZWoa4OLpCq5kAu+2JT+", + "Qv56YV6dX/ISntr6mbZM7Y6PtPxxlOWvqWL52iqWr62iVsl/7IxHRhd0Kg/82IFwTNRjFH3XQ9+V5diB", + "skx2qh6l/Ow0HZ94p28Hb72T0/HQW47S2BvG5+NROh7zlI8PWahrC+aAgNHYZYojgqb7/e/b0DvnXjp/", + "OGu83fjkGePBsHnD+lzSOZNptX2ceGxla7Vn7wXm9ZIY1QWLWI6oTBQEmf3sx1UZfIBVAYjXPP6H6yTI", + "eMETLaBgvZfp/XbK+cD1PRgE7fzBJc+gBIn2yTIKYpFuHkWfuawQMUgDB4gmisc5OEM/7KCKgmC1Wvnc", + "zvqVzoLNVhNczd5dfLy58IZ+6OdYWmQo0KpzDBMB8Zw/FUgajWyie9CmrWLgh/5gQDEqBZIrQRr7oT9i", + "VqXcXo6BPrhY7ZcMLK10g9qJWULZAT91FlIIzUtA0IZFtw9MUMq7GvSauVsG4s55d5/ZMzx+K+Zut0cZ", + "huGL+hOBUD75QHXel2bnPa41Xx9rXm7qOAZjqAvYMdUaaddAHUu3KyTYdlq244G41gLXlsh8K++C13So", + "bufEgKnLkus1i9iVMOhgDk5HObIg8oy0YF2l5pShK3PwcPh3Nm0IrqKGoK98v0/oSd9lZjZ1qrQHkLmt", + "Q8h4e4N0YbDDyxJ1Dc91TPsqtEa5q8Hg71Wy/mU9bJ+BI344nHfaPsbBylmCs7nhe8U1P2nr57v5/+Te", + "SRyDwmBKLarpOMTZaGd+5GSbTt9vnde964sq5kVeGfTNimcZaF9UAVciuB8xQrGJ+tiwE+fmenZ5eeHY", + "DsFpW4S9RztfG7e/u1OEMBvrKw10i9kZOhB8m+USkg3jTsc0S8AVgHRwVXWQmD2ULh3NvPk3AAD//w4x", + "IU3MDQAA", +} + +// GetSwagger returns the content of the embedded swagger specification file +// or error if failed to decode +func decodeSpec() ([]byte, error) { + zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + if err != nil { + return nil, fmt.Errorf("error base64 decoding spec: %s", err) + } + zr, err := gzip.NewReader(bytes.NewReader(zipped)) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %s", err) + } + var buf bytes.Buffer + _, err = buf.ReadFrom(zr) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %s", err) + } + + return buf.Bytes(), nil +} + +var rawSpec = decodeSpecCached() + +// a naive cached of a decoded swagger spec +func decodeSpecCached() func() ([]byte, error) { + data, err := decodeSpec() + return func() ([]byte, error) { + return data, err + } +} + +// Constructs a synthetic filesystem for resolving external references when loading openapi specifications. +func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { + var res = make(map[string]func() ([]byte, error)) + if len(pathToFile) > 0 { + res[pathToFile] = rawSpec + } + + pathPrefix := path.Dir(pathToFile) + + for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "../../../common/api/schemas.yaml")) { + if _, ok := res[rawPath]; ok { + // it is not possible to compare functions in golang, so always overwrite the old value + } + res[rawPath] = rawFunc + } + return res +} + +// GetSwagger returns the Swagger specification corresponding to the generated code +// in this file. The external references of Swagger specification are resolved. +// The logic of resolving external references is tightly connected to "import-mapping" feature. +// Externally referenced files must be embedded in the corresponding golang packages. +// Urls can be supported but this task was out of the scope. +func GetSwagger() (swagger *openapi3.T, err error) { + var resolvePath = PathToRawSpec("") + + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = true + loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { + var pathToFile = url.String() + pathToFile = path.Clean(pathToFile) + getSpec, ok := resolvePath[pathToFile] + if !ok { + err1 := fmt.Errorf("path not found: %s", pathToFile) + return nil, err1 + } + return getSpec() + } + var specData []byte + specData, err = rawSpec() + if err != nil { + return + } + swagger, err = loader.LoadFromData(specData) + if err != nil { + return + } + return +} diff --git a/pkg/harvester/api/admin/admin.yaml b/pkg/harvester/api/admin/admin.yaml new file mode 100644 index 000000000..31ce73df2 --- /dev/null +++ b/pkg/harvester/api/admin/admin.yaml @@ -0,0 +1,96 @@ +openapi: 3.0.3 +info: + title: Galadriel Harvester API - OpenAPI 3.0 + description: |- + Galadriel Harvester Management API specification. + contact: + name: Github + url: https://github.com/HewlettPackard/galadriel + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.11 +servers: + - url: https://localhost.swagger.io/api/v3 +tags: + - name: Trust Domain + description: A SPIFFE Trust Domain + - name: Relationships + description: A relationship is the representation of a SPIFFE Federation Relationship between two Trust Domains + +paths: + /relationships: + get: + tags: + - Relationships + summary: List the relationships. + operationId: GetRelationships + parameters: + - name: consentStatus + in: query + schema: + $ref: '../../../common/api/schemas.yaml#/components/schemas/ConsentStatus' + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: array + items: + $ref: '../../../common/api/schemas.yaml#/components/schemas/Relationship' + default: + $ref: '#/components/responses/Default' + security: + - harvester_auth: [ ] + + + /relationships/{relationshipID}: + patch: + tags: + - Relationships + summary: Accept/Denies relationship requests + operationId: PatchRelationship + parameters: + - name: relationshipID + in: path + description: ID of the relationship + required: true + schema: + $ref: '../../../common/api/schemas.yaml#/components/schemas/UUID' + requestBody: + description: Relationship status to be updated + content: + application/json: + schema: + $ref: '#/components/schemas/PatchRelationship' + required: true + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '../../../common/api/schemas.yaml#/components/schemas/Relationship' + default: + $ref: '#/components/responses/Default' + security: + - harvester_auth: [ ] + +components: + responses: + Default: + description: Error API responses + content: + application/json: + schema: + $ref: '../../../common/api/schemas.yaml#/components/schemas/ApiError' + schemas: + PatchRelationship: + type: object + additionalProperties: false + required: + - consent_status + properties: + consent_status: + $ref: '../../../common/api/schemas.yaml#/components/schemas/ConsentStatus' diff --git a/pkg/server/db/README.md b/pkg/server/db/README.md index f1678ecf2..fad6dacc0 100644 --- a/pkg/server/db/README.md +++ b/pkg/server/db/README.md @@ -7,7 +7,7 @@ Type-safe code from SQL is generated using [sqlc](https://github.com/kyleconroy/ When there is a change in the schema or in the queries, the DB code should be re-generated: ``` -make generate-sqlc-code +make generate-sql-code ``` This regenerates the files `models.go`, `db.go`, `querier.go`, and files ending in `.sql.go`.