Skip to content

Commit 0537b59

Browse files
authored
support yaml formatted openapi schema (kubernetes-sigs#4017)
* support yaml formatted openapi schema * suggested changes
1 parent 339e33d commit 0537b59

File tree

7 files changed

+138
-10
lines changed

7 files changed

+138
-10
lines changed

api/krusty/openapicustomschema_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ func writeTestSchema(th kusttest_test.Harness, filepath string) {
1717
th.WriteF(filepath+"mycrd_schema.json", string(bytes))
1818
}
1919

20+
func writeTestSchemaYaml(th kusttest_test.Harness, filepath string) {
21+
bytes, _ := ioutil.ReadFile("testdata/customschema.yaml")
22+
th.WriteF(filepath+"mycrd_schema.yaml", string(bytes))
23+
}
24+
2025
func writeCustomResource(th kusttest_test.Harness, filepath string) {
2126
th.WriteF(filepath, `
2227
apiVersion: example.com/v1alpha1
@@ -103,6 +108,21 @@ openapi:
103108
th.AssertActualEqualsExpected(m, patchedCustomResource)
104109
}
105110

111+
func TestCustomOpenApiFieldYaml(t *testing.T) {
112+
th := kusttest_test.MakeHarness(t)
113+
th.WriteK(".", `
114+
resources:
115+
- mycrd.yaml
116+
openapi:
117+
path: mycrd_schema.yaml
118+
`+customSchemaPatch)
119+
writeCustomResource(th, "mycrd.yaml")
120+
writeTestSchemaYaml(th, "./")
121+
openapi.ResetOpenAPI()
122+
m := th.Run(".", th.MakeDefaultOptions())
123+
th.AssertActualEqualsExpected(m, patchedCustomResource)
124+
}
125+
106126
// Error if user tries to specify both builtin version
107127
// and custom schema
108128
func TestCustomOpenApiFieldBothPathAndVersion(t *testing.T) {

api/krusty/testdata/customschema.yaml

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
definitions:
2+
v1alpha1.MyCRD:
3+
properties:
4+
apiVersion:
5+
type: string
6+
kind:
7+
type: string
8+
metadata:
9+
type: object
10+
spec:
11+
properties:
12+
template:
13+
"$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
14+
type: object
15+
status:
16+
properties:
17+
success:
18+
type: boolean
19+
type: object
20+
type: object
21+
x-kubernetes-group-version-kind:
22+
- group: example.com
23+
kind: MyCRD
24+
version: v1alpha1
25+
io.k8s.api.core.v1.PodTemplateSpec:
26+
properties:
27+
metadata:
28+
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
29+
spec:
30+
"$ref": "#/definitions/io.k8s.api.core.v1.PodSpec"
31+
type: object
32+
io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta:
33+
properties:
34+
name:
35+
type: string
36+
type: object
37+
io.k8s.api.core.v1.PodSpec:
38+
properties:
39+
containers:
40+
items:
41+
"$ref": "#/definitions/io.k8s.api.core.v1.Container"
42+
type: array
43+
x-kubernetes-patch-merge-key: name
44+
x-kubernetes-patch-strategy: merge
45+
type: object
46+
io.k8s.api.core.v1.Container:
47+
properties:
48+
command:
49+
items:
50+
type: string
51+
type: array
52+
image:
53+
type: string
54+
name:
55+
type: string
56+
ports:
57+
items:
58+
"$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort"
59+
type: array
60+
x-kubernetes-list-map-keys:
61+
- containerPort
62+
- protocol
63+
x-kubernetes-list-type: map
64+
x-kubernetes-patch-merge-key: containerPort
65+
x-kubernetes-patch-strategy: merge
66+
type: object
67+
io.k8s.api.core.v1.ContainerPort:
68+
properties:
69+
containerPort:
70+
type: integer
71+
name:
72+
type: string
73+
protocol:
74+
type: string
75+
type: object

cmd/config/go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,5 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2R
248248
sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
249249
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
250250
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
251+
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
251252
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

kustomize/commands/openapi/fetch/fetch.go

+31-9
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,38 @@ import (
88
"os/exec"
99

1010
"github.com/spf13/cobra"
11+
"sigs.k8s.io/yaml"
1112
)
1213

14+
var format string
15+
1316
// NewCmdFetch makes a new fetch command.
1417
func NewCmdFetch(w io.Writer) *cobra.Command {
15-
infoCmd := cobra.Command{
18+
fetchCmd := cobra.Command{
1619
Use: "fetch",
1720
Short: `Fetches the OpenAPI specification from the current kubernetes cluster specified
1821
in the user's kubeconfig`,
1922
Example: `kustomize openapi fetch`,
20-
Run: func(cmd *cobra.Command, args []string) {
21-
printSchema(w)
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
return printSchema(w)
2225
},
2326
}
24-
return &infoCmd
27+
fetchCmd.Flags().StringVar(
28+
&format,
29+
"format",
30+
"json",
31+
"Specify format for fetched schema ('json' or 'yaml')")
32+
return &fetchCmd
2533
}
2634

27-
func printSchema(w io.Writer) {
35+
func printSchema(w io.Writer) error {
36+
if format != "json" && format != "yaml" {
37+
return fmt.Errorf("format must be either 'json' or 'yaml'")
38+
}
39+
2840
errMsg := `
2941
Error fetching schema from cluster.
30-
Please make sure kubectl is installed and its context is set correctly.
42+
Please make sure kubectl is installed, its context is set correctly, and your cluster is up.
3143
Installation and setup instructions: https://kubernetes.io/docs/tasks/tools/install-kubectl/`
3244

3345
command := exec.Command("kubectl", []string{"get", "--raw", "/openapi/v2"}...)
@@ -36,15 +48,25 @@ Installation and setup instructions: https://kubernetes.io/docs/tasks/tools/inst
3648
command.Stdout = &stdout
3749
command.Stderr = &stderr
3850
err := command.Run()
39-
if err != nil || stdout.String() == "" {
40-
fmt.Fprintln(w, err, stderr.String()+errMsg)
41-
return
51+
if err != nil {
52+
return fmt.Errorf("%w\n%s", err, stderr.String()+errMsg)
53+
} else if stdout.String() == "" {
54+
return fmt.Errorf(stderr.String() + errMsg)
4255
}
4356

4457
// format and output
4558
var jsonSchema map[string]interface{}
4659
output := stdout.Bytes()
4760
json.Unmarshal(output, &jsonSchema)
4861
output, _ = json.MarshalIndent(jsonSchema, "", " ")
62+
63+
if format == "yaml" {
64+
output, err = yaml.JSONToYAML(output)
65+
if err != nil {
66+
return err
67+
}
68+
}
69+
4970
fmt.Fprintln(w, string(output))
71+
return nil
5072
}

kyaml/go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
2020
gopkg.in/yaml.v2 v2.4.0
2121
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
22+
sigs.k8s.io/yaml v1.2.0
2223
)
2324

2425
// These can be removed after upgrading golangci-lint (Issue #3663)

kyaml/go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,5 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
225225
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
226226
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
227227
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
228+
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
228229
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

kyaml/openapi/openapi.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi"
1717
"sigs.k8s.io/kustomize/kyaml/openapi/kustomizationapi"
1818
"sigs.k8s.io/kustomize/kyaml/yaml"
19+
k8syaml "sigs.k8s.io/yaml"
1920
)
2021

2122
// globalSchema contains global state information about the openapi
@@ -536,7 +537,14 @@ func parseBuiltinSchema(version string) {
536537
// parse parses and indexes a single json schema
537538
func parse(b []byte) error {
538539
var swagger spec.Swagger
539-
540+
s := string(b)
541+
if len(s) > 0 && s[0] != '{' {
542+
var err error
543+
b, err = k8syaml.YAMLToJSON(b)
544+
if err != nil {
545+
return errors.Wrap(err)
546+
}
547+
}
540548
if err := swagger.UnmarshalJSON(b); err != nil {
541549
return errors.Wrap(err)
542550
}

0 commit comments

Comments
 (0)