From f7e28673f910850ce1bdffea8395f0ce416c4eab Mon Sep 17 00:00:00 2001 From: Lyuben Penkovski <lyuben.penkovski@vereign.com> Date: Mon, 28 Mar 2022 08:20:23 +0300 Subject: [PATCH] Goa DSL for policy evaluation and 'main' wiring --- cmd/policy/main.go | 10 ++ design/design.go | 13 +++ design/types.go | 17 +++ gen/http/cli/policy/cli.go | 61 +++++++++++ gen/http/openapi.json | 2 +- gen/http/openapi.yaml | 65 ++++++++++++ gen/http/openapi3.json | 2 +- gen/http/openapi3.yaml | 81 ++++++++++++++- gen/http/policy/client/cli.go | 55 ++++++++++ gen/http/policy/client/client.go | 75 ++++++++++++++ gen/http/policy/client/encode_decode.go | 104 +++++++++++++++++++ gen/http/policy/client/paths.go | 17 +++ gen/http/policy/client/types.go | 55 ++++++++++ gen/http/policy/server/encode_decode.go | 66 ++++++++++++ gen/http/policy/server/paths.go | 17 +++ gen/http/policy/server/server.go | 131 ++++++++++++++++++++++++ gen/http/policy/server/types.go | 57 +++++++++++ gen/policy/client.go | 36 +++++++ gen/policy/endpoints.go | 40 ++++++++ gen/policy/service.go | 46 +++++++++ internal/service/policy/service.go | 18 ++++ 21 files changed, 965 insertions(+), 3 deletions(-) create mode 100644 design/types.go create mode 100644 gen/http/policy/client/cli.go create mode 100644 gen/http/policy/client/client.go create mode 100644 gen/http/policy/client/encode_decode.go create mode 100644 gen/http/policy/client/paths.go create mode 100644 gen/http/policy/client/types.go create mode 100644 gen/http/policy/server/encode_decode.go create mode 100644 gen/http/policy/server/paths.go create mode 100644 gen/http/policy/server/server.go create mode 100644 gen/http/policy/server/types.go create mode 100644 gen/policy/client.go create mode 100644 gen/policy/endpoints.go create mode 100644 gen/policy/service.go create mode 100644 internal/service/policy/service.go diff --git a/cmd/policy/main.go b/cmd/policy/main.go index 5a648869..05675f99 100644 --- a/cmd/policy/main.go +++ b/cmd/policy/main.go @@ -18,10 +18,13 @@ import ( goahealth "code.vereign.com/gaiax/tsa/policy/gen/health" goahealthsrv "code.vereign.com/gaiax/tsa/policy/gen/http/health/server" goaopenapisrv "code.vereign.com/gaiax/tsa/policy/gen/http/openapi/server" + goapolicysrv "code.vereign.com/gaiax/tsa/policy/gen/http/policy/server" "code.vereign.com/gaiax/tsa/policy/gen/openapi" + goapolicy "code.vereign.com/gaiax/tsa/policy/gen/policy" "code.vereign.com/gaiax/tsa/policy/internal/config" "code.vereign.com/gaiax/tsa/policy/internal/service" "code.vereign.com/gaiax/tsa/policy/internal/service/health" + "code.vereign.com/gaiax/tsa/policy/internal/service/policy" ) var Version = "0.0.0+development" @@ -42,18 +45,22 @@ func main() { // create services var ( + policySvc goapolicy.Service healthSvc goahealth.Service ) { + policySvc = policy.New() healthSvc = health.New() } // create endpoints var ( + policyEndpoints *goapolicy.Endpoints healthEndpoints *goahealth.Endpoints openapiEndpoints *openapi.Endpoints ) { + policyEndpoints = goapolicy.NewEndpoints(policySvc) healthEndpoints = goahealth.NewEndpoints(healthSvc) openapiEndpoints = openapi.NewEndpoints(nil) } @@ -76,15 +83,18 @@ func main() { // the service input and output data structures to HTTP requests and // responses. var ( + policyServer *goapolicysrv.Server healthServer *goahealthsrv.Server openapiServer *goaopenapisrv.Server ) { + policyServer = goapolicysrv.New(policyEndpoints, mux, dec, enc, nil, errFormatter) healthServer = goahealthsrv.New(healthEndpoints, mux, dec, enc, nil, errFormatter) openapiServer = goaopenapisrv.New(openapiEndpoints, mux, dec, enc, nil, errFormatter, nil, nil) } // Configure the mux. + goapolicysrv.Mount(mux, policyServer) goahealthsrv.Mount(mux, healthServer) goaopenapisrv.Mount(mux, openapiServer) diff --git a/design/design.go b/design/design.go index f73c6373..2dae4129 100644 --- a/design/design.go +++ b/design/design.go @@ -15,6 +15,19 @@ var _ = API("policy", func() { }) }) +var _ = Service("policy", func() { + Description("Policy Service provides evaluation of policies through Open Policy Agent.") + + Method("Evaluate", func() { + Payload(EvaluateRequest) + Result(EvaluateResult) + HTTP(func() { + POST("/policy/{group}/{policyName}/{version}/evaluation") + Response(StatusOK) + }) + }) +}) + var _ = Service("health", func() { Description("Health service provides health check endpoints.") diff --git a/design/types.go b/design/types.go new file mode 100644 index 00000000..c72cf1a0 --- /dev/null +++ b/design/types.go @@ -0,0 +1,17 @@ +// nolint:revive +package design + +import . "goa.design/goa/v3/dsl" + +var EvaluateRequest = Type("EvaluateRequest", func() { + Field(1, "group", String, "Policy group") + Field(2, "policyName", String, "Policy name") + Field(3, "version", String, "Policy version") + Field(4, "data", Any, "Data passed as input to the policy execution runtime") + Required("group", "policyName", "version", "data") +}) + +var EvaluateResult = Type("EvaluateResult", func() { + Field(1, "result", Any, "Arbitrary JSON response.") + Required("result") +}) diff --git a/gen/http/cli/policy/cli.go b/gen/http/cli/policy/cli.go index b27030d7..f7610a85 100644 --- a/gen/http/cli/policy/cli.go +++ b/gen/http/cli/policy/cli.go @@ -14,6 +14,7 @@ import ( "os" healthc "code.vereign.com/gaiax/tsa/policy/gen/http/health/client" + policyc "code.vereign.com/gaiax/tsa/policy/gen/http/policy/client" goahttp "goa.design/goa/v3/http" goa "goa.design/goa/v3/pkg" ) @@ -24,12 +25,16 @@ import ( // func UsageCommands() string { return `health (liveness|readiness) +policy evaluate ` } // UsageExamples produces an example of a valid invocation of the CLI tool. func UsageExamples() string { return os.Args[0] + ` health liveness` + "\n" + + os.Args[0] + ` policy evaluate --body '{ + "data": "Quasi et et laudantium non." + }' --group "Et facilis sit corporis enim." --policy-name "Saepe aut cumque." --version "Ab accusamus voluptatem et est."` + "\n" + "" } @@ -48,11 +53,22 @@ func ParseEndpoint( healthLivenessFlags = flag.NewFlagSet("liveness", flag.ExitOnError) healthReadinessFlags = flag.NewFlagSet("readiness", flag.ExitOnError) + + policyFlags = flag.NewFlagSet("policy", flag.ContinueOnError) + + policyEvaluateFlags = flag.NewFlagSet("evaluate", flag.ExitOnError) + policyEvaluateBodyFlag = policyEvaluateFlags.String("body", "REQUIRED", "") + policyEvaluateGroupFlag = policyEvaluateFlags.String("group", "REQUIRED", "Policy group") + policyEvaluatePolicyNameFlag = policyEvaluateFlags.String("policy-name", "REQUIRED", "Policy name") + policyEvaluateVersionFlag = policyEvaluateFlags.String("version", "REQUIRED", "Policy version") ) healthFlags.Usage = healthUsage healthLivenessFlags.Usage = healthLivenessUsage healthReadinessFlags.Usage = healthReadinessUsage + policyFlags.Usage = policyUsage + policyEvaluateFlags.Usage = policyEvaluateUsage + if err := flag.CommandLine.Parse(os.Args[1:]); err != nil { return nil, nil, err } @@ -70,6 +86,8 @@ func ParseEndpoint( switch svcn { case "health": svcf = healthFlags + case "policy": + svcf = policyFlags default: return nil, nil, fmt.Errorf("unknown service %q", svcn) } @@ -95,6 +113,13 @@ func ParseEndpoint( } + case "policy": + switch epn { + case "evaluate": + epf = policyEvaluateFlags + + } + } } if epf == nil { @@ -125,6 +150,13 @@ func ParseEndpoint( endpoint = c.Readiness() data = nil } + case "policy": + c := policyc.NewClient(scheme, host, doer, enc, dec, restore) + switch epn { + case "evaluate": + endpoint = c.Evaluate() + data, err = policyc.BuildEvaluatePayload(*policyEvaluateBodyFlag, *policyEvaluateGroupFlag, *policyEvaluatePolicyNameFlag, *policyEvaluateVersionFlag) + } } } if err != nil { @@ -167,3 +199,32 @@ Example: %[1]s health readiness `, os.Args[0]) } + +// policyUsage displays the usage of the policy command and its subcommands. +func policyUsage() { + fmt.Fprintf(os.Stderr, `Policy Service provides evaluation of policies through Open Policy Agent. +Usage: + %[1]s [globalflags] policy COMMAND [flags] + +COMMAND: + evaluate: Evaluate implements Evaluate. + +Additional help: + %[1]s policy COMMAND --help +`, os.Args[0]) +} +func policyEvaluateUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] policy evaluate -body JSON -group STRING -policy-name STRING -version STRING + +Evaluate implements Evaluate. + -body JSON: + -group STRING: Policy group + -policy-name STRING: Policy name + -version STRING: Policy version + +Example: + %[1]s policy evaluate --body '{ + "data": "Quasi et et laudantium non." + }' --group "Et facilis sit corporis enim." --policy-name "Saepe aut cumque." --version "Ab accusamus voluptatem et est." +`, os.Args[0]) +} diff --git a/gen/http/openapi.json b/gen/http/openapi.json index f3017019..b7773f1f 100644 --- a/gen/http/openapi.json +++ b/gen/http/openapi.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":""},"host":"localhost:8080","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}}}} \ No newline at end of file +{"swagger":"2.0","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":""},"host":"localhost:8080","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/evaluation":{"post":{"tags":["policy"],"summary":"Evaluate policy","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version","required":true,"type":"string"},{"name":"EvaluateRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/PolicyEvaluateRequestBody","required":["data"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/PolicyEvaluateResponseBody","required":["result"]}}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}}},"definitions":{"PolicyEvaluateRequestBody":{"title":"PolicyEvaluateRequestBody","type":"object","properties":{"data":{"type":"string","description":"Data passed as input to the policy execution runtime","example":"Ipsum nihil quo.","format":"binary"}},"example":{"data":"Repellat velit omnis."},"required":["data"]},"PolicyEvaluateResponseBody":{"title":"PolicyEvaluateResponseBody","type":"object","properties":{"result":{"type":"string","description":"Arbitrary JSON response.","example":"Illum ad assumenda consectetur minima voluptatibus.","format":"binary"}},"example":{"result":"Id odio aperiam voluptatem molestias corrupti sunt."},"required":["result"]}}} \ No newline at end of file diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml index d78c3dfa..214812d2 100644 --- a/gen/http/openapi.yaml +++ b/gen/http/openapi.yaml @@ -24,6 +24,44 @@ paths: description: OK response. schemes: - http + /policy/{group}/{policyName}/{version}/evaluation: + post: + tags: + - policy + summary: Evaluate policy + operationId: policy#Evaluate + parameters: + - name: group + in: path + description: Policy group + required: true + type: string + - name: policyName + in: path + description: Policy name + required: true + type: string + - name: version + in: path + description: Policy version + required: true + type: string + - name: EvaluateRequestBody + in: body + required: true + schema: + $ref: '#/definitions/PolicyEvaluateRequestBody' + required: + - data + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/PolicyEvaluateResponseBody' + required: + - result + schemes: + - http /readiness: get: tags: @@ -35,3 +73,30 @@ paths: description: OK response. schemes: - http +definitions: + PolicyEvaluateRequestBody: + title: PolicyEvaluateRequestBody + type: object + properties: + data: + type: string + description: Data passed as input to the policy execution runtime + example: Ipsum nihil quo. + format: binary + example: + data: Repellat velit omnis. + required: + - data + PolicyEvaluateResponseBody: + title: PolicyEvaluateResponseBody + type: object + properties: + result: + type: string + description: Arbitrary JSON response. + example: Illum ad assumenda consectetur minima voluptatibus. + format: binary + example: + result: Id odio aperiam voluptatem molestias corrupti sunt. + required: + - result diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json index 22d61abd..705e2078 100644 --- a/gen/http/openapi3.json +++ b/gen/http/openapi3.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":"1.0"},"servers":[{"url":"http://localhost:8080","description":"Policy Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."}]} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":"1.0"},"servers":[{"url":"http://localhost:8080","description":"Policy Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/policy/{group}/{policyName}/{version}/evaluation":{"post":{"tags":["policy"],"summary":"Evaluate policy","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group","required":true,"schema":{"type":"string","description":"Policy group","example":"Explicabo beatae quisquam officiis libero voluptatibus."},"example":"Repudiandae dolore quod."},{"name":"policyName","in":"path","description":"Policy name","required":true,"schema":{"type":"string","description":"Policy name","example":"Aut ut fuga quae eius minus."},"example":"Architecto quibusdam ab."},{"name":"version","in":"path","description":"Policy version","required":true,"schema":{"type":"string","description":"Policy version","example":"In illum est et hic."},"example":"Deleniti non nihil dolor aut sed."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateRequestBody"},"example":{"data":"Quasi et et laudantium non."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateResult"},"example":{"result":"Et voluptates."}}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}}},"components":{"schemas":{"EvaluateRequestBody":{"type":"object","properties":{"data":{"type":"string","description":"Data passed as input to the policy execution runtime","example":"Vitae qui.","format":"binary"}},"example":{"data":"Provident fugiat at cupiditate."},"required":["data"]},"EvaluateResult":{"type":"object","properties":{"result":{"type":"string","description":"Arbitrary JSON response.","example":"Commodi vitae voluptatem.","format":"binary"}},"example":{"result":"Similique quisquam optio."},"required":["result"]}}},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"policy","description":"Policy Service provides evaluation of policies through Open Policy Agent."}]} \ No newline at end of file diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml index b2d64e2a..aa3e8dd7 100644 --- a/gen/http/openapi3.yaml +++ b/gen/http/openapi3.yaml @@ -16,6 +16,57 @@ paths: responses: "200": description: OK response. + /policy/{group}/{policyName}/{version}/evaluation: + post: + tags: + - policy + summary: Evaluate policy + operationId: policy#Evaluate + parameters: + - name: group + in: path + description: Policy group + required: true + schema: + type: string + description: Policy group + example: Explicabo beatae quisquam officiis libero voluptatibus. + example: Repudiandae dolore quod. + - name: policyName + in: path + description: Policy name + required: true + schema: + type: string + description: Policy name + example: Aut ut fuga quae eius minus. + example: Architecto quibusdam ab. + - name: version + in: path + description: Policy version + required: true + schema: + type: string + description: Policy version + example: In illum est et hic. + example: Deleniti non nihil dolor aut sed. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EvaluateRequestBody' + example: + data: Quasi et et laudantium non. + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/EvaluateResult' + example: + result: Et voluptates. /readiness: get: tags: @@ -25,7 +76,35 @@ paths: responses: "200": description: OK response. -components: {} +components: + schemas: + EvaluateRequestBody: + type: object + properties: + data: + type: string + description: Data passed as input to the policy execution runtime + example: Vitae qui. + format: binary + example: + data: Provident fugiat at cupiditate. + required: + - data + EvaluateResult: + type: object + properties: + result: + type: string + description: Arbitrary JSON response. + example: Commodi vitae voluptatem. + format: binary + example: + result: Similique quisquam optio. + required: + - result tags: - name: health description: Health service provides health check endpoints. +- name: policy + description: Policy Service provides evaluation of policies through Open Policy + Agent. diff --git a/gen/http/policy/client/cli.go b/gen/http/policy/client/cli.go new file mode 100644 index 00000000..c483ac70 --- /dev/null +++ b/gen/http/policy/client/cli.go @@ -0,0 +1,55 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy HTTP client CLI support package +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package client + +import ( + "encoding/json" + "fmt" + + policy "code.vereign.com/gaiax/tsa/policy/gen/policy" + goa "goa.design/goa/v3/pkg" +) + +// BuildEvaluatePayload builds the payload for the policy Evaluate endpoint +// from CLI flags. +func BuildEvaluatePayload(policyEvaluateBody string, policyEvaluateGroup string, policyEvaluatePolicyName string, policyEvaluateVersion string) (*policy.EvaluateRequest, error) { + var err error + var body EvaluateRequestBody + { + err = json.Unmarshal([]byte(policyEvaluateBody), &body) + if err != nil { + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"data\": \"Quasi et et laudantium non.\"\n }'") + } + if body.Data == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("data", "body")) + } + if err != nil { + return nil, err + } + } + var group string + { + group = policyEvaluateGroup + } + var policyName string + { + policyName = policyEvaluatePolicyName + } + var version string + { + version = policyEvaluateVersion + } + v := &policy.EvaluateRequest{ + Data: body.Data, + } + v.Group = group + v.PolicyName = policyName + v.Version = version + + return v, nil +} diff --git a/gen/http/policy/client/client.go b/gen/http/policy/client/client.go new file mode 100644 index 00000000..837783bd --- /dev/null +++ b/gen/http/policy/client/client.go @@ -0,0 +1,75 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy client HTTP transport +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package client + +import ( + "context" + "net/http" + + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// Client lists the policy service endpoint HTTP clients. +type Client struct { + // Evaluate Doer is the HTTP client used to make requests to the Evaluate + // endpoint. + EvaluateDoer goahttp.Doer + + // RestoreResponseBody controls whether the response bodies are reset after + // decoding so they can be read again. + RestoreResponseBody bool + + scheme string + host string + encoder func(*http.Request) goahttp.Encoder + decoder func(*http.Response) goahttp.Decoder +} + +// NewClient instantiates HTTP clients for all the policy service servers. +func NewClient( + scheme string, + host string, + doer goahttp.Doer, + enc func(*http.Request) goahttp.Encoder, + dec func(*http.Response) goahttp.Decoder, + restoreBody bool, +) *Client { + return &Client{ + EvaluateDoer: doer, + RestoreResponseBody: restoreBody, + scheme: scheme, + host: host, + decoder: dec, + encoder: enc, + } +} + +// Evaluate returns an endpoint that makes HTTP requests to the policy service +// Evaluate server. +func (c *Client) Evaluate() goa.Endpoint { + var ( + encodeRequest = EncodeEvaluateRequest(c.encoder) + decodeResponse = DecodeEvaluateResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v interface{}) (interface{}, error) { + req, err := c.BuildEvaluateRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.EvaluateDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("policy", "Evaluate", err) + } + return decodeResponse(resp) + } +} diff --git a/gen/http/policy/client/encode_decode.go b/gen/http/policy/client/encode_decode.go new file mode 100644 index 00000000..49cdd5fc --- /dev/null +++ b/gen/http/policy/client/encode_decode.go @@ -0,0 +1,104 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy HTTP client encoders and decoders +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package client + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + + policy "code.vereign.com/gaiax/tsa/policy/gen/policy" + goahttp "goa.design/goa/v3/http" +) + +// BuildEvaluateRequest instantiates a HTTP request object with method and path +// set to call the "policy" service "Evaluate" endpoint +func (c *Client) BuildEvaluateRequest(ctx context.Context, v interface{}) (*http.Request, error) { + var ( + group string + policyName string + version string + ) + { + p, ok := v.(*policy.EvaluateRequest) + if !ok { + return nil, goahttp.ErrInvalidType("policy", "Evaluate", "*policy.EvaluateRequest", v) + } + group = p.Group + policyName = p.PolicyName + version = p.Version + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: EvaluatePolicyPath(group, policyName, version)} + req, err := http.NewRequest("POST", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("policy", "Evaluate", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeEvaluateRequest returns an encoder for requests sent to the policy +// Evaluate server. +func EncodeEvaluateRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, interface{}) error { + return func(req *http.Request, v interface{}) error { + p, ok := v.(*policy.EvaluateRequest) + if !ok { + return goahttp.ErrInvalidType("policy", "Evaluate", "*policy.EvaluateRequest", v) + } + body := NewEvaluateRequestBody(p) + if err := encoder(req).Encode(&body); err != nil { + return goahttp.ErrEncodingError("policy", "Evaluate", err) + } + return nil + } +} + +// DecodeEvaluateResponse returns a decoder for responses returned by the +// policy Evaluate endpoint. restoreBody controls whether the response body +// should be restored after having been read. +func DecodeEvaluateResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (interface{}, error) { + return func(resp *http.Response) (interface{}, error) { + if restoreBody { + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = ioutil.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = ioutil.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body EvaluateResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("policy", "Evaluate", err) + } + err = ValidateEvaluateResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("policy", "Evaluate", err) + } + res := NewEvaluateResultOK(&body) + return res, nil + default: + body, _ := ioutil.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("policy", "Evaluate", resp.StatusCode, string(body)) + } + } +} diff --git a/gen/http/policy/client/paths.go b/gen/http/policy/client/paths.go new file mode 100644 index 00000000..62f6160d --- /dev/null +++ b/gen/http/policy/client/paths.go @@ -0,0 +1,17 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// HTTP request path constructors for the policy service. +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package client + +import ( + "fmt" +) + +// EvaluatePolicyPath returns the URL path to the policy service Evaluate HTTP endpoint. +func EvaluatePolicyPath(group string, policyName string, version string) string { + return fmt.Sprintf("/policy/%v/%v/%v/evaluation", group, policyName, version) +} diff --git a/gen/http/policy/client/types.go b/gen/http/policy/client/types.go new file mode 100644 index 00000000..36eb2a2e --- /dev/null +++ b/gen/http/policy/client/types.go @@ -0,0 +1,55 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy HTTP client types +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package client + +import ( + policy "code.vereign.com/gaiax/tsa/policy/gen/policy" + goa "goa.design/goa/v3/pkg" +) + +// EvaluateRequestBody is the type of the "policy" service "Evaluate" endpoint +// HTTP request body. +type EvaluateRequestBody struct { + // Data passed as input to the policy execution runtime + Data interface{} `form:"data" json:"data" xml:"data"` +} + +// EvaluateResponseBody is the type of the "policy" service "Evaluate" endpoint +// HTTP response body. +type EvaluateResponseBody struct { + // Arbitrary JSON response. + Result interface{} `form:"result,omitempty" json:"result,omitempty" xml:"result,omitempty"` +} + +// NewEvaluateRequestBody builds the HTTP request body from the payload of the +// "Evaluate" endpoint of the "policy" service. +func NewEvaluateRequestBody(p *policy.EvaluateRequest) *EvaluateRequestBody { + body := &EvaluateRequestBody{ + Data: p.Data, + } + return body +} + +// NewEvaluateResultOK builds a "policy" service "Evaluate" endpoint result +// from a HTTP "OK" response. +func NewEvaluateResultOK(body *EvaluateResponseBody) *policy.EvaluateResult { + v := &policy.EvaluateResult{ + Result: body.Result, + } + + return v +} + +// ValidateEvaluateResponseBody runs the validations defined on +// EvaluateResponseBody +func ValidateEvaluateResponseBody(body *EvaluateResponseBody) (err error) { + if body.Result == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("result", "body")) + } + return +} diff --git a/gen/http/policy/server/encode_decode.go b/gen/http/policy/server/encode_decode.go new file mode 100644 index 00000000..cf8a4c3b --- /dev/null +++ b/gen/http/policy/server/encode_decode.go @@ -0,0 +1,66 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy HTTP server encoders and decoders +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package server + +import ( + "context" + "io" + "net/http" + + policy "code.vereign.com/gaiax/tsa/policy/gen/policy" + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// EncodeEvaluateResponse returns an encoder for responses returned by the +// policy Evaluate endpoint. +func EncodeEvaluateResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error { + return func(ctx context.Context, w http.ResponseWriter, v interface{}) error { + res, _ := v.(*policy.EvaluateResult) + enc := encoder(ctx, w) + body := NewEvaluateResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeEvaluateRequest returns a decoder for requests sent to the policy +// Evaluate endpoint. +func DecodeEvaluateRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) { + return func(r *http.Request) (interface{}, error) { + var ( + body EvaluateRequestBody + err error + ) + err = decoder(r).Decode(&body) + if err != nil { + if err == io.EOF { + return nil, goa.MissingPayloadError() + } + return nil, goa.DecodePayloadError(err.Error()) + } + err = ValidateEvaluateRequestBody(&body) + if err != nil { + return nil, err + } + + var ( + group string + policyName string + version string + + params = mux.Vars(r) + ) + group = params["group"] + policyName = params["policyName"] + version = params["version"] + payload := NewEvaluateRequest(&body, group, policyName, version) + + return payload, nil + } +} diff --git a/gen/http/policy/server/paths.go b/gen/http/policy/server/paths.go new file mode 100644 index 00000000..b5ca7ad8 --- /dev/null +++ b/gen/http/policy/server/paths.go @@ -0,0 +1,17 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// HTTP request path constructors for the policy service. +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package server + +import ( + "fmt" +) + +// EvaluatePolicyPath returns the URL path to the policy service Evaluate HTTP endpoint. +func EvaluatePolicyPath(group string, policyName string, version string) string { + return fmt.Sprintf("/policy/%v/%v/%v/evaluation", group, policyName, version) +} diff --git a/gen/http/policy/server/server.go b/gen/http/policy/server/server.go new file mode 100644 index 00000000..e324397d --- /dev/null +++ b/gen/http/policy/server/server.go @@ -0,0 +1,131 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy HTTP server +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package server + +import ( + "context" + "net/http" + + policy "code.vereign.com/gaiax/tsa/policy/gen/policy" + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// Server lists the policy service endpoint HTTP handlers. +type Server struct { + Mounts []*MountPoint + Evaluate http.Handler +} + +// ErrorNamer is an interface implemented by generated error structs that +// exposes the name of the error as defined in the design. +type ErrorNamer interface { + ErrorName() string +} + +// MountPoint holds information about the mounted endpoints. +type MountPoint struct { + // Method is the name of the service method served by the mounted HTTP handler. + Method string + // Verb is the HTTP method used to match requests to the mounted handler. + Verb string + // Pattern is the HTTP request path pattern used to match requests to the + // mounted handler. + Pattern string +} + +// New instantiates HTTP handlers for all the policy service endpoints using +// the provided encoder and decoder. The handlers are mounted on the given mux +// using the HTTP verb and path defined in the design. errhandler is called +// whenever a response fails to be encoded. formatter is used to format errors +// returned by the service methods prior to encoding. Both errhandler and +// formatter are optional and can be nil. +func New( + e *policy.Endpoints, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(err error) goahttp.Statuser, +) *Server { + return &Server{ + Mounts: []*MountPoint{ + {"Evaluate", "POST", "/policy/{group}/{policyName}/{version}/evaluation"}, + }, + Evaluate: NewEvaluateHandler(e.Evaluate, mux, decoder, encoder, errhandler, formatter), + } +} + +// Service returns the name of the service served. +func (s *Server) Service() string { return "policy" } + +// Use wraps the server handlers with the given middleware. +func (s *Server) Use(m func(http.Handler) http.Handler) { + s.Evaluate = m(s.Evaluate) +} + +// Mount configures the mux to serve the policy endpoints. +func Mount(mux goahttp.Muxer, h *Server) { + MountEvaluateHandler(mux, h.Evaluate) +} + +// Mount configures the mux to serve the policy endpoints. +func (s *Server) Mount(mux goahttp.Muxer) { + Mount(mux, s) +} + +// MountEvaluateHandler configures the mux to serve the "policy" service +// "Evaluate" endpoint. +func MountEvaluateHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("POST", "/policy/{group}/{policyName}/{version}/evaluation", f) +} + +// NewEvaluateHandler creates a HTTP handler which loads the HTTP request and +// calls the "policy" service "Evaluate" endpoint. +func NewEvaluateHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeEvaluateRequest(mux, decoder) + encodeResponse = EncodeEvaluateResponse(encoder) + encodeError = goahttp.ErrorEncoder(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "Evaluate") + ctx = context.WithValue(ctx, goa.ServiceKey, "policy") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + errhandler(ctx, w, err) + } + }) +} diff --git a/gen/http/policy/server/types.go b/gen/http/policy/server/types.go new file mode 100644 index 00000000..be5b1945 --- /dev/null +++ b/gen/http/policy/server/types.go @@ -0,0 +1,57 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy HTTP server types +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package server + +import ( + policy "code.vereign.com/gaiax/tsa/policy/gen/policy" + goa "goa.design/goa/v3/pkg" +) + +// EvaluateRequestBody is the type of the "policy" service "Evaluate" endpoint +// HTTP request body. +type EvaluateRequestBody struct { + // Data passed as input to the policy execution runtime + Data interface{} `form:"data,omitempty" json:"data,omitempty" xml:"data,omitempty"` +} + +// EvaluateResponseBody is the type of the "policy" service "Evaluate" endpoint +// HTTP response body. +type EvaluateResponseBody struct { + // Arbitrary JSON response. + Result interface{} `form:"result" json:"result" xml:"result"` +} + +// NewEvaluateResponseBody builds the HTTP response body from the result of the +// "Evaluate" endpoint of the "policy" service. +func NewEvaluateResponseBody(res *policy.EvaluateResult) *EvaluateResponseBody { + body := &EvaluateResponseBody{ + Result: res.Result, + } + return body +} + +// NewEvaluateRequest builds a policy service Evaluate endpoint payload. +func NewEvaluateRequest(body *EvaluateRequestBody, group string, policyName string, version string) *policy.EvaluateRequest { + v := &policy.EvaluateRequest{ + Data: body.Data, + } + v.Group = group + v.PolicyName = policyName + v.Version = version + + return v +} + +// ValidateEvaluateRequestBody runs the validations defined on +// EvaluateRequestBody +func ValidateEvaluateRequestBody(body *EvaluateRequestBody) (err error) { + if body.Data == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("data", "body")) + } + return +} diff --git a/gen/policy/client.go b/gen/policy/client.go new file mode 100644 index 00000000..5fc9b70f --- /dev/null +++ b/gen/policy/client.go @@ -0,0 +1,36 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy client +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package policy + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// Client is the "policy" service client. +type Client struct { + EvaluateEndpoint goa.Endpoint +} + +// NewClient initializes a "policy" service client given the endpoints. +func NewClient(evaluate goa.Endpoint) *Client { + return &Client{ + EvaluateEndpoint: evaluate, + } +} + +// Evaluate calls the "Evaluate" endpoint of the "policy" service. +func (c *Client) Evaluate(ctx context.Context, p *EvaluateRequest) (res *EvaluateResult, err error) { + var ires interface{} + ires, err = c.EvaluateEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*EvaluateResult), nil +} diff --git a/gen/policy/endpoints.go b/gen/policy/endpoints.go new file mode 100644 index 00000000..5b8b177f --- /dev/null +++ b/gen/policy/endpoints.go @@ -0,0 +1,40 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy endpoints +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package policy + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// Endpoints wraps the "policy" service endpoints. +type Endpoints struct { + Evaluate goa.Endpoint +} + +// NewEndpoints wraps the methods of the "policy" service with endpoints. +func NewEndpoints(s Service) *Endpoints { + return &Endpoints{ + Evaluate: NewEvaluateEndpoint(s), + } +} + +// Use applies the given middleware to all the "policy" service endpoints. +func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) { + e.Evaluate = m(e.Evaluate) +} + +// NewEvaluateEndpoint returns an endpoint function that calls the method +// "Evaluate" of service "policy". +func NewEvaluateEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req interface{}) (interface{}, error) { + p := req.(*EvaluateRequest) + return s.Evaluate(ctx, p) + } +} diff --git a/gen/policy/service.go b/gen/policy/service.go new file mode 100644 index 00000000..f2b7f991 --- /dev/null +++ b/gen/policy/service.go @@ -0,0 +1,46 @@ +// Code generated by goa v3.7.0, DO NOT EDIT. +// +// policy service +// +// Command: +// $ goa gen code.vereign.com/gaiax/tsa/policy/design + +package policy + +import ( + "context" +) + +// Policy Service provides evaluation of policies through Open Policy Agent. +type Service interface { + // Evaluate implements Evaluate. + Evaluate(context.Context, *EvaluateRequest) (res *EvaluateResult, err error) +} + +// ServiceName is the name of the service as defined in the design. This is the +// same value that is set in the endpoint request contexts under the ServiceKey +// key. +const ServiceName = "policy" + +// MethodNames lists the service method names as defined in the design. These +// are the same values that are set in the endpoint request contexts under the +// MethodKey key. +var MethodNames = [1]string{"Evaluate"} + +// EvaluateRequest is the payload type of the policy service Evaluate method. +type EvaluateRequest struct { + // Policy group + Group string + // Policy name + PolicyName string + // Policy version + Version string + // Data passed as input to the policy execution runtime + Data interface{} +} + +// EvaluateResult is the result type of the policy service Evaluate method. +type EvaluateResult struct { + // Arbitrary JSON response. + Result interface{} +} diff --git a/internal/service/policy/service.go b/internal/service/policy/service.go new file mode 100644 index 00000000..ed8edcb5 --- /dev/null +++ b/internal/service/policy/service.go @@ -0,0 +1,18 @@ +package policy + +import ( + "context" + + "code.vereign.com/gaiax/tsa/golib/errors" + "code.vereign.com/gaiax/tsa/policy/gen/policy" +) + +type Service struct{} + +func New() *Service { + return &Service{} +} + +func (s *Service) Evaluate(context.Context, *policy.EvaluateRequest) (*policy.EvaluateResult, error) { + return nil, errors.New("not implemented") +} -- GitLab