From 04ca27572ff2e3ed5458c16d6a3f8bf7e7963aea Mon Sep 17 00:00:00 2001 From: David Gageot Date: Fri, 13 Dec 2019 20:28:17 +0100 Subject: [PATCH] Add commands to list/print json schemas (#3355) Signed-off-by: David Gageot --- .gitignore | 1 + Makefile | 12 +-- cmd/skaffold/app/cmd/cmd.go | 1 + cmd/skaffold/app/cmd/schema.go | 53 ++++++++++++ cmd/skaffold/app/cmd/schema/fs.go | 28 +++++++ cmd/skaffold/app/cmd/schema/fs_dummy.go | 28 +++++++ cmd/skaffold/app/cmd/schema/list.go | 33 ++++++++ cmd/skaffold/app/cmd/schema/list_test.go | 62 ++++++++++++++ cmd/skaffold/app/cmd/schema/print.go | 42 ++++++++++ cmd/skaffold/app/cmd/schema/print_test.go | 83 +++++++++++++++++++ docs/content/en/docs/references/cli/_index.md | 56 +++++++++++++ .../en/docs/references/cli/index_header | 1 + hack/{gen_licenses.sh => gen_statik.sh} | 1 + 13 files changed, 395 insertions(+), 6 deletions(-) create mode 100644 cmd/skaffold/app/cmd/schema.go create mode 100644 cmd/skaffold/app/cmd/schema/fs.go create mode 100644 cmd/skaffold/app/cmd/schema/fs_dummy.go create mode 100644 cmd/skaffold/app/cmd/schema/list.go create mode 100644 cmd/skaffold/app/cmd/schema/list_test.go create mode 100644 cmd/skaffold/app/cmd/schema/print.go create mode 100644 cmd/skaffold/app/cmd/schema/print_test.go rename hack/{gen_licenses.sh => gen_statik.sh} (94%) diff --git a/.gitignore b/.gitignore index b9f2be4070a..ab9f5a3d4af 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ docs/themes docs/package-lock.json pkg/skaffold/color/debug.test cmd/skaffold/app/cmd/credits/statik +cmd/skaffold/app/cmd/schema/statik diff --git a/Makefile b/Makefile index 802cab4b842..ecbb657b40f 100644 --- a/Makefile +++ b/Makefile @@ -69,10 +69,10 @@ GO_FILES := $(shell find . -type f -name '*.go' -not -path "./vendor/*") $(BUILD_DIR)/$(PROJECT): $(BUILD_DIR)/$(PROJECT)-$(GOOS)-$(GOARCH) cp $(BUILD_DIR)/$(PROJECT)-$(GOOS)-$(GOARCH) $@ -$(BUILD_DIR)/$(PROJECT)-$(GOOS)-$(GOARCH): generate-licenses $(GO_FILES) $(BUILD_DIR) +$(BUILD_DIR)/$(PROJECT)-$(GOOS)-$(GOARCH): generate-statik $(GO_FILES) $(BUILD_DIR) GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=1 go build -tags $(GO_BUILD_TAGS_$(GOOS)) -ldflags $(GO_LDFLAGS_$(GOOS)) -gcflags $(GO_GCFLAGS) -asmflags $(GO_ASMFLAGS) -o $@ $(BUILD_PACKAGE) -$(BUILD_DIR)/$(PROJECT)-%-$(GOARCH): generate-licenses $(GO_FILES) $(BUILD_DIR) +$(BUILD_DIR)/$(PROJECT)-%-$(GOARCH): generate-statik $(GO_FILES) $(BUILD_DIR) docker build --build-arg PROJECT=$(REPOPATH) \ --build-arg TARGETS=$*/$(GOARCH) \ --build-arg FLAG_LDFLAGS=$(GO_LDFLAGS_$(*)) \ @@ -117,7 +117,7 @@ quicktest: go test -short -timeout=60s ./... .PHONY: install -install: generate-licenses $(GO_FILES) $(BUILD_DIR) +install: generate-statik $(GO_FILES) $(BUILD_DIR) GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=1 go install -tags $(GO_BUILD_TAGS_$(GOOS)) -ldflags $(GO_LDFLAGS_$(GOOS)) -gcflags $(GO_GCFLAGS) -asmflags $(GO_ASMFLAGS) $(BUILD_PACKAGE) .PHONY: integration @@ -223,6 +223,6 @@ build-docs-preview: generate-schemas: go run hack/schemas/main.go -.PHONY: generate-licenses -generate-licenses: - hack/gen_licenses.sh +.PHONY: generate-statik +generate-statik: + hack/gen_statik.sh diff --git a/cmd/skaffold/app/cmd/cmd.go b/cmd/skaffold/app/cmd/cmd.go index b783b37578f..60466933ebe 100644 --- a/cmd/skaffold/app/cmd/cmd.go +++ b/cmd/skaffold/app/cmd/cmd.go @@ -159,6 +159,7 @@ func NewSkaffoldCommand(out, err io.Writer) *cobra.Command { rootCmd.AddCommand(NewCmdDiagnose()) rootCmd.AddCommand(NewCmdOptions()) rootCmd.AddCommand(NewCmdCredits()) + rootCmd.AddCommand(NewCmdSchema()) rootCmd.AddCommand(NewCmdGeneratePipeline()) diff --git a/cmd/skaffold/app/cmd/schema.go b/cmd/skaffold/app/cmd/schema.go new file mode 100644 index 00000000000..b54e93b481e --- /dev/null +++ b/cmd/skaffold/app/cmd/schema.go @@ -0,0 +1,53 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io" + + "github.com/spf13/cobra" + + "github.com/GoogleContainerTools/skaffold/cmd/skaffold/app/cmd/schema" +) + +func NewCmdSchema() *cobra.Command { + cmd := &cobra.Command{ + Use: "schema", + Short: "List and print json schemas used to validate skaffold.yaml configuration", + } + + cmd.AddCommand(NewCmdSchemaGet()) + cmd.AddCommand(NewCmdSchemaList()) + return cmd +} + +func NewCmdSchemaList() *cobra.Command { + return NewCmd("list"). + WithDescription("List skaffold.yaml's json schema versions"). + WithExample("List all the versions", "schema list"). + NoArgs(schema.List) +} + +func NewCmdSchemaGet() *cobra.Command { + return NewCmd("get"). + WithDescription("Print a given skaffold.yaml's json schema"). + WithExample("Print the schema in version `skaffold/v1`", "schema get skaffold/v1"). + ExactArgs(1, func(out io.Writer, args []string) error { + version := args[0] + return schema.Print(out, version) + }) +} diff --git a/cmd/skaffold/app/cmd/schema/fs.go b/cmd/skaffold/app/cmd/schema/fs.go new file mode 100644 index 00000000000..34e3f28cec1 --- /dev/null +++ b/cmd/skaffold/app/cmd/schema/fs.go @@ -0,0 +1,28 @@ +// +build release + +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "github.com/rakyll/statik/fs" + + //required for rakyll/statik embedded content + _ "github.com/GoogleContainerTools/skaffold/cmd/skaffold/app/cmd/schema/statik" +) + +var statikFS = fs.New diff --git a/cmd/skaffold/app/cmd/schema/fs_dummy.go b/cmd/skaffold/app/cmd/schema/fs_dummy.go new file mode 100644 index 00000000000..b54369e198b --- /dev/null +++ b/cmd/skaffold/app/cmd/schema/fs_dummy.go @@ -0,0 +1,28 @@ +// +build !release + +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import "net/http" + +// statikFS with !release build tag is just here for compilation purposes +// this file does not depend on the generated statik.go file that is not checked +// in by default to git +var statikFS = func() (http.FileSystem, error) { + panic("not implemented, skaffold should be built with make ('release' build tag)") +} diff --git a/cmd/skaffold/app/cmd/schema/list.go b/cmd/skaffold/app/cmd/schema/list.go new file mode 100644 index 00000000000..92bbe1749f3 --- /dev/null +++ b/cmd/skaffold/app/cmd/schema/list.go @@ -0,0 +1,33 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "fmt" + "io" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema" +) + +// List prints to `out` all supported schema versions. +func List(out io.Writer) error { + for _, version := range schema.SchemaVersions { + fmt.Fprintln(out, version.APIVersion) + } + + return nil +} diff --git a/cmd/skaffold/app/cmd/schema/list_test.go b/cmd/skaffold/app/cmd/schema/list_test.go new file mode 100644 index 00000000000..e75c6a45ef3 --- /dev/null +++ b/cmd/skaffold/app/cmd/schema/list_test.go @@ -0,0 +1,62 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "bytes" + "strings" + "testing" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" + "github.com/GoogleContainerTools/skaffold/testutil" +) + +func TestList(t *testing.T) { + testutil.Run(t, "", func(t *testutil.T) { + var out bytes.Buffer + + err := List(&out) + + versions := out.String() + t.CheckNoError(err) + t.CheckTrue(strings.HasSuffix(versions, latest.Version+"\n")) + t.CheckTrue(strings.HasPrefix(versions, `skaffold/v1alpha1 +skaffold/v1alpha2 +skaffold/v1alpha3 +skaffold/v1alpha4 +skaffold/v1alpha5 +skaffold/v1beta1 +skaffold/v1beta2 +skaffold/v1beta3 +skaffold/v1beta4 +skaffold/v1beta5 +skaffold/v1beta6 +skaffold/v1beta7 +skaffold/v1beta8 +skaffold/v1beta9 +skaffold/v1beta10 +skaffold/v1beta11 +skaffold/v1beta12 +skaffold/v1beta13 +skaffold/v1beta14 +skaffold/v1beta15 +skaffold/v1beta16 +skaffold/v1beta17 +skaffold/v1 +skaffold/v2alpha1`)) + }) +} diff --git a/cmd/skaffold/app/cmd/schema/print.go b/cmd/skaffold/app/cmd/schema/print.go new file mode 100644 index 00000000000..617a2eb9d8d --- /dev/null +++ b/cmd/skaffold/app/cmd/schema/print.go @@ -0,0 +1,42 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "io" + "strings" + + "github.com/pkg/errors" + "github.com/rakyll/statik/fs" +) + +// Print prints the json schema for a given version. +func Print(out io.Writer, version string) error { + statikFS, err := statikFS() + if err != nil { + return err + } + + path := "/" + strings.TrimPrefix(version, "skaffold/") + ".json" + content, err := fs.ReadFile(statikFS, path) + if err != nil { + return errors.Wrapf(err, "schema %q not found", version) + } + + out.Write(content) + return nil +} diff --git a/cmd/skaffold/app/cmd/schema/print_test.go b/cmd/skaffold/app/cmd/schema/print_test.go new file mode 100644 index 00000000000..db01d21fd24 --- /dev/null +++ b/cmd/skaffold/app/cmd/schema/print_test.go @@ -0,0 +1,83 @@ +/* +Copyright 2019 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "bytes" + "io" + "net/http" + "os" + "testing" + + "github.com/GoogleContainerTools/skaffold/testutil" +) + +type fakeFileSystem struct { + Files map[string][]byte +} + +type fakeFile struct { + http.File + content io.Reader +} + +func (f *fakeFileSystem) Open(name string) (http.File, error) { + content, found := f.Files[name] + if !found { + return nil, os.ErrNotExist + } + + return &fakeFile{ + content: bytes.NewBuffer(content), + }, nil +} + +func (f *fakeFile) Read(p []byte) (n int, err error) { + return f.content.Read(p) +} + +func (f *fakeFile) Close() error { + return nil +} + +func TestPrint(t *testing.T) { + fs := &fakeFileSystem{ + Files: map[string][]byte{ + "/v1.json": []byte("{SCHEMA}"), + }, + } + + testutil.Run(t, "found", func(t *testutil.T) { + t.Override(&statikFS, func() (http.FileSystem, error) { return fs, nil }) + + var out bytes.Buffer + err := Print(&out, "skaffold/v1") + + t.CheckNoError(err) + t.CheckDeepEqual("{SCHEMA}", out.String()) + }) + + testutil.Run(t, "not found", func(t *testutil.T) { + t.Override(&statikFS, func() (http.FileSystem, error) { return fs, nil }) + + var out bytes.Buffer + err := Print(&out, "skaffold/v0") + + t.CheckErrorContains("schema \"skaffold/v0\" not found", err) + t.CheckEmpty(out.String()) + }) +} diff --git a/docs/content/en/docs/references/cli/_index.md b/docs/content/en/docs/references/cli/_index.md index 4bccf028b36..5724a6d8c7f 100644 --- a/docs/content/en/docs/references/cli/_index.md +++ b/docs/content/en/docs/references/cli/_index.md @@ -33,6 +33,7 @@ Other Commands: * [skaffold config](#skaffold-config) - manage context specific parameters * [skaffold credits](#skaffold-credits) - export third party notices to given path (./skaffold-credits by default) * [skaffold diagnose](#skaffold-diagnose) - diagnostics of Skaffold works in your project +* [skaffold schema](#skaffold-schema) - list and print json schemas used to validate skaffold.yaml configuration ## Global flags @@ -85,6 +86,7 @@ Other Commands: config Interact with the Skaffold configuration credits Export third party notices to given path (./skaffold-credits by default) diagnose Run a diagnostic on Skaffold + schema List and print json schemas used to validate skaffold.yaml configuration version Print the version information Use "skaffold --help" for more information about a given command. @@ -741,6 +743,60 @@ Env vars: * `SKAFFOLD_TAIL` (same as `--tail`) * `SKAFFOLD_TOOT` (same as `--toot`) +### skaffold schema + +List and print json schemas used to validate skaffold.yaml configuration + +``` + + +Available Commands: + get Print a given skaffold.yaml's json schema + list List skaffold.yaml's json schema versions + +Use "skaffold --help" for more information about a given command. + + +``` + +### skaffold schema get + +Print a given skaffold.yaml's json schema + +``` + + +Examples: + # Print the schema in version `skaffold/v1` + skaffold schema get skaffold/v1 + +Usage: + skaffold schema get [options] + +Use "skaffold options" for a list of global command-line options (applies to all commands). + + +``` + +### skaffold schema list + +List skaffold.yaml's json schema versions + +``` + + +Examples: + # List all the versions + skaffold schema list + +Usage: + skaffold schema list [options] + +Use "skaffold options" for a list of global command-line options (applies to all commands). + + +``` + ### skaffold version Print the version information diff --git a/docs/content/en/docs/references/cli/index_header b/docs/content/en/docs/references/cli/index_header index 1d6aaddab0a..3a9c3b17bc8 100644 --- a/docs/content/en/docs/references/cli/index_header +++ b/docs/content/en/docs/references/cli/index_header @@ -33,6 +33,7 @@ Other Commands: * [skaffold config](#skaffold-config) - manage context specific parameters * [skaffold credits](#skaffold-credits) - export third party notices to given path (./skaffold-credits by default) * [skaffold diagnose](#skaffold-diagnose) - diagnostics of Skaffold works in your project +* [skaffold schema](#skaffold-schema) - list and print json schemas used to validate skaffold.yaml configuration ## Global flags diff --git a/hack/gen_licenses.sh b/hack/gen_statik.sh similarity index 94% rename from hack/gen_licenses.sh rename to hack/gen_statik.sh index b0fde3208fa..99fe2eb9e6d 100755 --- a/hack/gen_licenses.sh +++ b/hack/gen_statik.sh @@ -42,3 +42,4 @@ if ! [[ -f ${STATIK} ]]; then fi ${STATIK} -f -src=${TMP_DIR}/skaffold-credits/ -m -dest cmd/skaffold/app/cmd/credits +${STATIK} -f -src=docs/content/en/schemas -m -dest cmd/skaffold/app/cmd/schema