diff --git a/cmd/yamlfmt/OWNERS b/cmd/yamlfmt/OWNERS new file mode 100644 index 00000000000..1cc9a523ff0 --- /dev/null +++ b/cmd/yamlfmt/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - dims diff --git a/cmd/yamlfmt/yamlfmt.go b/cmd/yamlfmt/yamlfmt.go new file mode 100644 index 00000000000..e22e00add27 --- /dev/null +++ b/cmd/yamlfmt/yamlfmt.go @@ -0,0 +1,71 @@ +/* +Copyright 2021 The Kubernetes 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 main + +import ( + "flag" + "io" + "io/ioutil" + "os" + + "gopkg.in/yaml.v3" +) + +func main() { + indent := flag.Int("indent", 2, "default indent") + flag.Parse() + + if flag.NArg() > 0 { + for _, path := range flag.Args() { + sourceYaml, err := ioutil.ReadFile(path) + if err != nil { + panic(err) + } + rootNode, err := fetchYaml(sourceYaml) + if err != nil { + panic(err) + } + writer, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + panic(err) + } + err = streamYaml(writer, indent, rootNode) + if err != nil { + panic(err) + } + } + } +} + +func fetchYaml(sourceYaml []byte) (*yaml.Node, error) { + rootNode := yaml.Node{} + err := yaml.Unmarshal(sourceYaml, &rootNode) + if err != nil { + return nil, err + } + return &rootNode, nil +} + +func streamYaml(writer io.Writer, indent *int, in *yaml.Node) error { + encoder := yaml.NewEncoder(writer) + encoder.SetIndent(*indent) + err := encoder.Encode(in) + if err != nil { + return err + } + return encoder.Close() +} diff --git a/cmd/yamlfmt/yamlfmt_test.go b/cmd/yamlfmt/yamlfmt_test.go new file mode 100644 index 00000000000..b4a3f2fd704 --- /dev/null +++ b/cmd/yamlfmt/yamlfmt_test.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 The Kubernetes 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 main + +import ( + "bufio" + "bytes" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestFetchYaml(t *testing.T) { + sourceYaml := ` # See the OWNERS docs at https://go.k8s.io/owners +approvers: +- dep-approvers +- thockin # Network +- liggitt + +labels: +- sig/architecture +` + + outputYaml := `# See the OWNERS docs at https://go.k8s.io/owners +approvers: + - dep-approvers + - thockin # Network + - liggitt +labels: + - sig/architecture +` + node, _ := fetchYaml([]byte(sourceYaml)) + var output bytes.Buffer + indent := 2 + writer := bufio.NewWriter(&output) + _ = streamYaml(writer, &indent, node) + _ = writer.Flush() + assert.Equal(t, outputYaml, string(output.Bytes()), "yaml was not formatted correctly") +} diff --git a/go.mod b/go.mod index aa4afae1ad7..a31c9cf689f 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( gopkg.in/gcfg.v1 v1.2.0 gopkg.in/square/go-jose.v2 v2.2.2 gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b k8s.io/api v0.0.0 k8s.io/apiextensions-apiserver v0.0.0 k8s.io/apimachinery v0.0.0 diff --git a/hack/update-yamlfmt.sh b/hack/update-yamlfmt.sh new file mode 100755 index 00000000000..d663830a2a3 --- /dev/null +++ b/hack/update-yamlfmt.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Copyright 2021 The Kubernetes 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. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +source "${KUBE_ROOT}/hack/lib/init.sh" + +kube::golang::verify_go_version + +cd "${KUBE_ROOT}" + +find_files() { + find . -not \( \ + \( \ + -wholename './output' \ + -o -wholename './.git' \ + -o -wholename './_output' \ + -o -wholename './_gopath' \ + -o -wholename './release' \ + -o -wholename './target' \ + -o -wholename '*/vendor/*' \ + \) -prune \ + \) -name 'OWNERS*' +} + +find_files | xargs go run cmd/yamlfmt/yamlfmt.go diff --git a/hack/verify-yamlfmt.sh b/hack/verify-yamlfmt.sh new file mode 100755 index 00000000000..e9986ac5ff8 --- /dev/null +++ b/hack/verify-yamlfmt.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +# Copyright 2021 The Kubernetes 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. + +# This script checks whether the OWNERS files need to be formatted or not by +# `yamlfmt`. Run `hack/update-yamlfmt.sh` to actually format sources. +# +# Usage: `hack/verify-yamlfmt.sh`. + + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +export KUBE_ROOT +source "${KUBE_ROOT}/hack/lib/init.sh" + +kube::util::ensure_clean_working_dir + +_tmpdir="$(kube::realpath "$(mktemp -d -t verify-generated-files.XXXXXX)")" + +_tmp_gopath="${_tmpdir}/go" +_tmp_kuberoot="${_tmp_gopath}/src/k8s.io/kubernetes" +git worktree add -f "${_tmp_kuberoot}" HEAD +kube::util::trap_add "git worktree remove -f ${_tmp_kuberoot} && rm -rf ${_tmpdir}" EXIT + +find_files() { + pushd "${_tmp_kuberoot}" >/dev/null 2>&1 + find "$(pwd)" -not \( \ + \( \ + -wholename './output' \ + -o -wholename './.git' \ + -o -wholename './_output' \ + -o -wholename './_gopath' \ + -o -wholename './release' \ + -o -wholename './target' \ + -o -wholename '*/vendor/*' \ + \) -prune \ + \) -name 'OWNERS*' + popd >/dev/null 2>&1 +} + +find_files | xargs go run cmd/yamlfmt/yamlfmt.go + +cd "${_tmp_kuberoot}" +changed_files=$(git status --porcelain) + +if [[ -n "${changed_files}" ]]; then + echo "!!! OWNERS files need to be updated:" >&2 + echo "${changed_files}" >&2 + echo >&2 + echo "Please run hack/update-yamlfmt.sh." >&2 + exit 1 +fi diff --git a/vendor/modules.txt b/vendor/modules.txt index d086c678b3c..94230a84c30 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1241,6 +1241,7 @@ gopkg.in/warnings.v0 ## explicit gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b => gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b +## explicit gopkg.in/yaml.v3 # k8s.io/api v0.0.0 => ./staging/src/k8s.io/api ## explicit