Skip to content

Commit 0cc6d05

Browse files
authored
Merge pull request #9 from linuxfoundation/jme/LFXV2-321
Expose OpenAPI spec files externally and update Helm charts
2 parents a2f3d97 + c771d46 commit 0cc6d05

File tree

14 files changed

+215
-67
lines changed

14 files changed

+215
-67
lines changed

charts/lfx-v2-query-service/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ apiVersion: v2
55
name: lfx-v2-query-service
66
description: LFX Platform V2 Query Service chart
77
type: application
8-
version: 0.2.2
8+
version: 0.2.3
99
appVersion: "latest"

charts/lfx-v2-query-service/templates/httproute.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ spec:
2121
- path:
2222
type: PathPrefix
2323
value: /query/
24+
- path:
25+
type: PathPrefix
26+
value: /_query/
2427
{{- if .Values.heimdall.enabled }}
2528
filters:
2629
- type: ExtensionRef

charts/lfx-v2-query-service/templates/ruleset.yaml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,37 @@ metadata:
88
namespace: {{ .Release.Namespace }}
99
spec:
1010
rules:
11+
- id: "rule:lfx:lfx-v2-query-service:openapi:get"
12+
match:
13+
methods:
14+
- GET
15+
routes:
16+
- path: /_query/openapi.json
17+
- path: /_query/openapi.yaml
18+
- path: /_query/openapi3.json
19+
- path: /_query/openapi3.yaml
20+
execute:
21+
- authenticator: oidc
22+
- authenticator: anonymous_authenticator
23+
{{- if .Values.app.use_oidc_contextualizer }}
24+
- contextualizer: oidc_contextualizer
25+
{{- end }}
26+
- authorizer: allow_all
27+
- finalizer: create_jwt
28+
config:
29+
values:
30+
aud: lfx-v2-query-service
1131
- id: "rule:lfx:lfx-v2-query-service"
1232
match:
1333
methods:
1434
- GET
1535
routes:
1636
- path: /query/resources
1737
execute:
38+
- authenticator: oidc
1839
- authenticator: anonymous_authenticator
19-
{{- if .Values.authelia.enabled }}
20-
- authenticator: authelia
21-
- contextualizer: authelia_userinfo
40+
{{- if .Values.app.use_oidc_contextualizer }}
41+
- contextualizer: oidc_contextualizer
2242
{{- end }}
2343
- authorizer: allow_all
2444
- finalizer: create_jwt

charts/lfx-v2-query-service/values.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ image:
99
tag: ""
1010
pullPolicy: IfNotPresent
1111

12+
# app is the configuration for the application
13+
app:
14+
# use_oidc_contextualizer is a boolean to determine if the OIDC contextualizer should be used
15+
use_oidc_contextualizer: true
16+
1217
# traefik is the configuration for Traefik Gateway API routing
1318
traefik:
1419
# gateway specifies the platform Gateway to attach to

cmd/http.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"log/slog"
99
"net/http"
10+
"os"
1011
"sync"
1112
"time"
1213

@@ -44,6 +45,11 @@ func handleHTTPServer(ctx context.Context, host string, querySvcEndpoints *query
4445
}
4546
}
4647

48+
koDatapath := os.Getenv("KO_DATA_PATH")
49+
if koDatapath == "" {
50+
koDatapath = "./gen/http"
51+
}
52+
koHttpDir := http.Dir(koDatapath)
4753
// Wrap the endpoints with the transport specific layers. The generated
4854
// server packages contains code generated from the design which maps
4955
// the service input and output data structures to HTTP requests and
@@ -53,7 +59,7 @@ func handleHTTPServer(ctx context.Context, host string, querySvcEndpoints *query
5359
)
5460
{
5561
eh := errorHandler(ctx)
56-
querySvcServer = querysvcsvr.New(querySvcEndpoints, mux, dec, enc, eh, nil, nil)
62+
querySvcServer = querysvcsvr.New(querySvcEndpoints, mux, dec, enc, eh, nil, koHttpDir, koHttpDir, koHttpDir, koHttpDir)
5763
}
5864

5965
// Configure the mux.

cmd/kodata/gen/http

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../gen/http

design/query-svc.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import (
77
"goa.design/goa/v3/dsl"
88
)
99

10+
var _ = dsl.API("lfx-v2-query-service", func() {
11+
dsl.Title("LFX V2 - Query Service")
12+
dsl.Description("Query indexed resources")
13+
})
14+
1015
var JWTAuth = dsl.JWTSecurity("jwt", func() {
1116
dsl.Description("Heimdall authorization")
1217
})
@@ -113,5 +118,8 @@ var _ = dsl.Service("query-svc", func() {
113118
})
114119

115120
// Serve the file gen/http/openapi3.json for requests sent to /openapi.json.
116-
dsl.Files("/openapi.json", "gen/http/openapi3.json")
121+
dsl.Files("/_query/openapi.json", "gen/http/openapi.json")
122+
dsl.Files("/_query/openapi.yaml", "gen/http/openapi.yaml")
123+
dsl.Files("/_query/openapi3.json", "gen/http/openapi3.json")
124+
dsl.Files("/_query/openapi3.yaml", "gen/http/openapi3.yaml")
117125
})
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gen/http/openapi.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"swagger":"2.0","info":{"title":"","version":"0.0.1"},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/livez":{"get":{"tags":["query-svc"],"summary":"livez query-svc","description":"Check if the service is alive.","operationId":"query-svc#livez","produces":["text/plain"],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}}},"schemes":["http"]}},"/openapi.json":{"get":{"tags":["query-svc"],"summary":"Download gen/http/openapi3.json","operationId":"query-svc#/openapi.json","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}},"/query/resources":{"get":{"tags":["query-svc"],"summary":"query-resources query-svc","description":"Locate resources by their type or parent, or use typeahead search to query resources by a display name or similar alias.","operationId":"query-svc#query-resources","parameters":[{"name":"v","in":"query","description":"Version of the API","required":true,"type":"string","enum":["1"]},{"name":"name","in":"query","description":"Resource name or alias; supports typeahead","required":false,"type":"string","minLength":1},{"name":"parent","in":"query","description":"Parent (for navigation; varies by object type)","required":false,"type":"string","pattern":"^[a-zA-Z]+:[a-zA-Z0-9_-]+$"},{"name":"type","in":"query","description":"Resource type to search","required":false,"type":"string"},{"name":"tags","in":"query","description":"Tags to search (varies by object type)","required":false,"type":"array","items":{"type":"string"},"collectionFormat":"multi"},{"name":"sort","in":"query","description":"Sort order for results","required":false,"type":"string","default":"name_asc","enum":["name_asc","name_desc","updated_asc","updated_desc"]},{"name":"page_token","in":"query","description":"Opaque token for pagination","required":false,"type":"string"},{"name":"Authorization","in":"header","description":"JWT token issued by Heimdall","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/QuerySvcQueryResourcesResponseBody","required":["resources"]},"headers":{"Cache-Control":{"description":"Cache control header","type":"string"}}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/BadRequestError","required":["message"]}},"500":{"description":"Internal Server Error response.","schema":{"$ref":"#/definitions/InternalServerError","required":["message"]}},"503":{"description":"Service Unavailable response.","schema":{"$ref":"#/definitions/ServiceUnavailableError","required":["message"]}}},"schemes":["http"],"security":[{"jwt_header_Authorization":[]}]}},"/readyz":{"get":{"tags":["query-svc"],"summary":"readyz query-svc","description":"Check if the service is able to take inbound requests.","operationId":"query-svc#readyz","produces":["text/plain"],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}},"503":{"description":"Service Unavailable response.","schema":{"$ref":"#/definitions/QuerySvcReadyzNotReadyResponseBody"}}},"schemes":["http"]}}},"definitions":{"BadRequestError":{"title":"BadRequestError","type":"object","properties":{"message":{"type":"string","description":"Error message","example":"The request was invalid."}},"description":"Bad request","example":{"message":"The request was invalid."},"required":["message"]},"InternalServerError":{"title":"InternalServerError","type":"object","properties":{"message":{"type":"string","description":"Error message","example":"An internal server error occurred."}},"description":"Internal server error","example":{"message":"An internal server error occurred."},"required":["message"]},"QuerySvcQueryResourcesResponseBody":{"title":"QuerySvcQueryResourcesResponseBody","type":"object","properties":{"page_token":{"type":"string","description":"Opaque token if more results are available","example":"****"},"resources":{"type":"array","items":{"$ref":"#/definitions/Resource"},"description":"Resources found","example":[{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"}]}},"example":{"page_token":"****","resources":[{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"}]},"required":["resources"]},"QuerySvcReadyzNotReadyResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"Service is not ready yet (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"Resource":{"title":"Resource","type":"object","properties":{"data":{"description":"Resource data snapshot","example":{"id":"123","name":"My committee","description":"a committee"}},"id":{"type":"string","description":"Resource ID (within its resource collection)","example":"123"},"type":{"type":"string","description":"Resource type","example":"committee"}},"description":"A resource is a universal representation of an LFX API resource for indexing.","example":{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"}},"ServiceUnavailableError":{"title":"ServiceUnavailableError","type":"object","properties":{"message":{"type":"string","description":"Error message","example":"The service is unavailable."}},"description":"Service unavailable","example":{"message":"The service is unavailable."},"required":["message"]}},"securityDefinitions":{"jwt_header_Authorization":{"type":"apiKey","description":"Heimdall authorization","name":"Authorization","in":"header"}}}
1+
{"swagger":"2.0","info":{"title":"LFX V2 - Query Service","description":"Query indexed resources","version":"0.0.1"},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/_query/openapi.json":{"get":{"tags":["query-svc"],"summary":"Download gen/http/openapi.json","operationId":"query-svc#/_query/openapi.json","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}},"/_query/openapi.yaml":{"get":{"tags":["query-svc"],"summary":"Download gen/http/openapi.yaml","operationId":"query-svc#/_query/openapi.yaml","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}},"/_query/openapi3.json":{"get":{"tags":["query-svc"],"summary":"Download gen/http/openapi3.json","operationId":"query-svc#/_query/openapi3.json","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}},"/_query/openapi3.yaml":{"get":{"tags":["query-svc"],"summary":"Download gen/http/openapi3.yaml","operationId":"query-svc#/_query/openapi3.yaml","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}},"/livez":{"get":{"tags":["query-svc"],"summary":"livez query-svc","description":"Check if the service is alive.","operationId":"query-svc#livez","produces":["text/plain"],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}}},"schemes":["http"]}},"/query/resources":{"get":{"tags":["query-svc"],"summary":"query-resources query-svc","description":"Locate resources by their type or parent, or use typeahead search to query resources by a display name or similar alias.","operationId":"query-svc#query-resources","parameters":[{"name":"v","in":"query","description":"Version of the API","required":true,"type":"string","enum":["1"]},{"name":"name","in":"query","description":"Resource name or alias; supports typeahead","required":false,"type":"string","minLength":1},{"name":"parent","in":"query","description":"Parent (for navigation; varies by object type)","required":false,"type":"string","pattern":"^[a-zA-Z]+:[a-zA-Z0-9_-]+$"},{"name":"type","in":"query","description":"Resource type to search","required":false,"type":"string"},{"name":"tags","in":"query","description":"Tags to search (varies by object type)","required":false,"type":"array","items":{"type":"string"},"collectionFormat":"multi"},{"name":"sort","in":"query","description":"Sort order for results","required":false,"type":"string","default":"name_asc","enum":["name_asc","name_desc","updated_asc","updated_desc"]},{"name":"page_token","in":"query","description":"Opaque token for pagination","required":false,"type":"string"},{"name":"Authorization","in":"header","description":"JWT token issued by Heimdall","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/QuerySvcQueryResourcesResponseBody","required":["resources"]},"headers":{"Cache-Control":{"description":"Cache control header","type":"string"}}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/BadRequestError","required":["message"]}},"500":{"description":"Internal Server Error response.","schema":{"$ref":"#/definitions/InternalServerError","required":["message"]}},"503":{"description":"Service Unavailable response.","schema":{"$ref":"#/definitions/ServiceUnavailableError","required":["message"]}}},"schemes":["http"],"security":[{"jwt_header_Authorization":[]}]}},"/readyz":{"get":{"tags":["query-svc"],"summary":"readyz query-svc","description":"Check if the service is able to take inbound requests.","operationId":"query-svc#readyz","produces":["text/plain"],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}},"503":{"description":"Service Unavailable response.","schema":{"$ref":"#/definitions/QuerySvcReadyzNotReadyResponseBody"}}},"schemes":["http"]}}},"definitions":{"BadRequestError":{"title":"BadRequestError","type":"object","properties":{"message":{"type":"string","description":"Error message","example":"The request was invalid."}},"description":"Bad request","example":{"message":"The request was invalid."},"required":["message"]},"InternalServerError":{"title":"InternalServerError","type":"object","properties":{"message":{"type":"string","description":"Error message","example":"An internal server error occurred."}},"description":"Internal server error","example":{"message":"An internal server error occurred."},"required":["message"]},"QuerySvcQueryResourcesResponseBody":{"title":"QuerySvcQueryResourcesResponseBody","type":"object","properties":{"page_token":{"type":"string","description":"Opaque token if more results are available","example":"****"},"resources":{"type":"array","items":{"$ref":"#/definitions/Resource"},"description":"Resources found","example":[{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"}]}},"example":{"page_token":"****","resources":[{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"},{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"}]},"required":["resources"]},"QuerySvcReadyzNotReadyResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"Service is not ready yet (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"Resource":{"title":"Resource","type":"object","properties":{"data":{"description":"Resource data snapshot","example":{"id":"123","name":"My committee","description":"a committee"}},"id":{"type":"string","description":"Resource ID (within its resource collection)","example":"123"},"type":{"type":"string","description":"Resource type","example":"committee"}},"description":"A resource is a universal representation of an LFX API resource for indexing.","example":{"data":{"id":"123","name":"My committee","description":"a committee"},"id":"123","type":"committee"}},"ServiceUnavailableError":{"title":"ServiceUnavailableError","type":"object","properties":{"message":{"type":"string","description":"Error message","example":"The service is unavailable."}},"description":"Service unavailable","example":{"message":"The service is unavailable."},"required":["message"]}},"securityDefinitions":{"jwt_header_Authorization":{"type":"apiKey","description":"Heimdall authorization","name":"Authorization","in":"header"}}}

0 commit comments

Comments
 (0)