Commit 23a9b0c2 authored by Jingfang Liu's avatar Jingfang Liu

vendor kustomize

parent 7693a1d5
......@@ -4164,6 +4164,116 @@
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/constants",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/expansion",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/factory",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/fs",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/git",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/gvk",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/image",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/loader",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resid",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resmap",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resource",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/target",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/types",
"Comment": "v2.0.1",
"Rev": "ce7e5ee2c30cc5856fea01fe423cf167f2a2d0c3"
},
{
"ImportPath": "sigs.k8s.io/structured-merge-diff/fieldpath",
"Rev": "e5e029740eb81ee0217ecf9d950c25a0eeb9688a"
},
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -7,14 +7,50 @@
],
"Deps": [
{
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
},
{
"ImportPath": "github.com/davecgh/go-spew/spew",
"Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8"
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/emicklei/go-restful/log",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/evanphx/json-patch",
"Rev": "d4020504c68b6bfa818032bedfb48e33e9638506"
},
{
"ImportPath": "github.com/ghodss/yaml",
"Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "8483a886a90412cd6858df4ea3483dce9c8e35a3"
},
{
"ImportPath": "github.com/go-openapi/spec",
"Rev": "5bae59e25b21498baea7f9d46e9c147ec106a42e"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "5899d5c5e619fda5fa86e14795a835f473ca284c"
},
{
"ImportPath": "github.com/gogo/protobuf/proto",
"Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02"
},
......@@ -83,6 +119,18 @@
"Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82"
},
{
"ImportPath": "github.com/mailru/easyjson/buffer",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/mailru/easyjson/jlexer",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/mailru/easyjson/jwriter",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/modern-go/concurrent",
"Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
},
......@@ -95,6 +143,10 @@
"Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6"
},
{
"ImportPath": "github.com/pkg/errors",
"Rev": "645ef00459ed84a119197bfb8d8205042c6df63d"
},
{
"ImportPath": "github.com/pmezard/go-difflib/difflib",
"Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
},
......@@ -191,6 +243,10 @@
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/width",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/time/rate",
"Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631"
},
......@@ -351,6 +407,10 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
......@@ -363,6 +423,10 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
......@@ -443,6 +507,10 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/naming",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
......@@ -459,6 +527,10 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
......@@ -479,6 +551,10 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
......@@ -567,6 +643,14 @@
"Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/common",
"Rev": "ced9eb3070a5f1c548ef46e8dfe2a97c208d9f03"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "ced9eb3070a5f1c548ef46e8dfe2a97c208d9f03"
},
{
"ImportPath": "k8s.io/client-go/discovery",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
......@@ -615,6 +699,94 @@
"Rev": "ed37f7428a91fc2a81070808937195dcd46d320e"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/constants",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/expansion",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/factory",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/fs",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/git",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/gvk",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/image",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/loader",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resid",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resmap",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resource",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/target",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/types",
"Rev": "0184d5b69700607a1b9280f303152e2959bc19e7"
},
{
"ImportPath": "sigs.k8s.io/structured-merge-diff/fieldpath",
"Rev": "e5e029740eb81ee0217ecf9d950c25a0eeb9688a"
},
......
......@@ -482,6 +482,24 @@ filegroup(
"//vendor/k8s.io/utils/pointer:all-srcs",
"//vendor/k8s.io/utils/strings:all-srcs",
"//vendor/k8s.io/utils/trace:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/commands/build:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/constants:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/expansion:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/factory:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/git:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/image:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/internal/error:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/loader:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/patch:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/target:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/types:all-srcs",
"//vendor/sigs.k8s.io/structured-merge-diff/fieldpath:all-srcs",
"//vendor/sigs.k8s.io/structured-merge-diff/merge:all-srcs",
"//vendor/sigs.k8s.io/structured-merge-diff/schema:all-srcs",
......
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["build.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/commands/build",
importpath = "sigs.k8s.io/kustomize/pkg/commands/build",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/target:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 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 build
import (
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc/transformer"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/target"
)
// Options contain the options for running a build
type Options struct {
kustomizationPath string
outputPath string
}
// NewOptions creates a Options object
func NewOptions(p, o string) *Options {
return &Options{
kustomizationPath: p,
outputPath: o,
}
}
var examples = `
Use the file somedir/kustomization.yaml to generate a set of api resources:
build somedir
Use a url pointing to a remote directory/kustomization.yaml to generate a set of api resources:
build url
The url should follow hashicorp/go-getter URL format described in
https://github.com/hashicorp/go-getter#url-format
url examples:
sigs.k8s.io/kustomize//examples/multibases?ref=v1.0.6
github.com/Liujingfang1/mysql
github.com/Liujingfang1/kustomize//examples/helloWorld?ref=repoUrl2
`
// NewCmdBuild creates a new build command.
func NewCmdBuild(
out io.Writer, fs fs.FileSystem,
rf *resmap.Factory,
ptf transformer.Factory) *cobra.Command {
var o Options
cmd := &cobra.Command{
Use: "build [path]",
Short: "Print current configuration per contents of " + constants.KustomizationFileNames[0],
Example: examples,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
if err != nil {
return err
}
return o.RunBuild(out, fs, rf, ptf)
},
}
cmd.Flags().StringVarP(
&o.outputPath,
"output", "o", "",
"If specified, write the build output to this path.")
return cmd
}
// Validate validates build command.
func (o *Options) Validate(args []string) error {
if len(args) > 1 {
return errors.New("specify one path to " + constants.KustomizationFileNames[0])
}
if len(args) == 0 {
o.kustomizationPath = "./"
} else {
o.kustomizationPath = args[0]
}
return nil
}
// RunBuild runs build command.
func (o *Options) RunBuild(
out io.Writer, fSys fs.FileSystem,
rf *resmap.Factory, ptf transformer.Factory) error {
ldr, err := loader.NewLoader(o.kustomizationPath, fSys)
if err != nil {
return err
}
defer ldr.Cleanup()
kt, err := target.NewKustTarget(ldr, fSys, rf, ptf)
if err != nil {
return err
}
allResources, err := kt.MakeCustomizedResMap()
if err != nil {
return err
}
// Output the objects.
res, err := allResources.EncodeAsYaml()
if err != nil {
return err
}
if o.outputPath != "" {
return fSys.WriteFile(o.outputPath, res)
}
_, err = out.Write(res)
return err
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["constants.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/constants",
importpath = "sigs.k8s.io/kustomize/pkg/constants",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 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 constants holds global constants for the kustomize tool.
package constants
// KustomizationFileNames is a list of filenames that can be recognized and consumbed
// by Kustomize.
// In each directory, Kustomize searches for file with the name in this list.
// Only one match is allowed.
var KustomizationFileNames = []string{
"kustomization.yaml",
"kustomization.yml",
"Kustomization",
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["expand.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/expansion",
importpath = "sigs.k8s.io/kustomize/pkg/expansion",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 expansion provides functions find and replace $(FOO) style variables in strings.
package expansion
import (
"bytes"
)
const (
operator = '$'
referenceOpener = '('
referenceCloser = ')'
)
// syntaxWrap returns the input string wrapped by the expansion syntax.
func syntaxWrap(input string) string {
return string(operator) + string(referenceOpener) + input + string(referenceCloser)
}
// MappingFuncFor returns a mapping function for use with Expand that
// implements the expansion semantics defined in the expansion spec; it
// returns the input string wrapped in the expansion syntax if no mapping
// for the input is found.
func MappingFuncFor(context ...map[string]string) func(string) string {
return func(input string) string {
for _, vars := range context {
val, ok := vars[input]
if ok {
return val
}
}
return syntaxWrap(input)
}
}
// Expand replaces variable references in the input string according to
// the expansion spec using the given mapping function to resolve the
// values of variables.
func Expand(input string, mapping func(string) string) string {
var buf bytes.Buffer
checkpoint := 0
for cursor := 0; cursor < len(input); cursor++ {
if input[cursor] == operator && cursor+1 < len(input) {
// Copy the portion of the input string since the last
// checkpoint into the buffer
buf.WriteString(input[checkpoint:cursor])
// Attempt to read the variable name as defined by the
// syntax from the input string
read, isVar, advance := tryReadVariableName(input[cursor+1:])
if isVar {
// We were able to read a variable name correctly;
// apply the mapping to the variable name and copy the
// bytes into the buffer
buf.WriteString(mapping(read))
} else {
// Not a variable name; copy the read bytes into the buffer
buf.WriteString(read)
}
// Advance the cursor in the input string to account for
// bytes consumed to read the variable name expression
cursor += advance
// Advance the checkpoint in the input string
checkpoint = cursor + 1
}
}
// Return the buffer and any remaining unwritten bytes in the
// input string.
return buf.String() + input[checkpoint:]
}
// tryReadVariableName attempts to read a variable name from the input
// string and returns the content read from the input, whether that content
// represents a variable name to perform mapping on, and the number of bytes
// consumed in the input string.
//
// The input string is assumed not to contain the initial operator.
func tryReadVariableName(input string) (string, bool, int) {
switch input[0] {
case operator:
// Escaped operator; return it.
return input[0:1], false, 1
case referenceOpener:
// Scan to expression closer
for i := 1; i < len(input); i++ {
if input[i] == referenceCloser {
return input[1:i], true, i + 1
}
}
// Incomplete reference; return it.
return string(operator) + string(referenceOpener), false, 1
default:
// Not the beginning of an expression, ie, an operator
// that doesn't begin an expression. Return the operator
// and the first rune in the string.
return string(operator) + string(input[0]), false, 1
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["factory.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/factory",
importpath = "sigs.k8s.io/kustomize/pkg/factory",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 factory provides factories for kustomize.
package factory
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/ifc/transformer"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
// KustFactory provides different factories for kustomize
type KustFactory struct {
ResmapF *resmap.Factory
TransformerF transformer.Factory
ValidatorF ifc.Validator
UnstructF ifc.KunstructuredFactory
}
// NewKustFactory creats a KustFactory instance
func NewKustFactory(u ifc.KunstructuredFactory, v ifc.Validator, t transformer.Factory) *KustFactory {
return &KustFactory{
ResmapF: resmap.NewFactory(resource.NewFactory(u)),
TransformerF: t,
ValidatorF: v,
UnstructF: u,
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"confirmeddir.go",
"fakefile.go",
"fakefileinfo.go",
"fakefs.go",
"fs.go",
"realfile.go",
"realfs.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/fs",
importpath = "sigs.k8s.io/kustomize/pkg/fs",
visibility = ["//visibility:public"],
deps = ["//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 fs
import (
"io/ioutil"
"path/filepath"
"strings"
)
// ConfirmedDir is a clean, absolute, delinkified path
// that was confirmed to point to an existing directory.
type ConfirmedDir string
// Return a temporary dir, else error.
// The directory is cleaned, no symlinks, etc. so its
// returned as a ConfirmedDir.
func NewTmpConfirmedDir() (ConfirmedDir, error) {
n, err := ioutil.TempDir("", "kustomize-")
if err != nil {
return "", err
}
return ConfirmedDir(n), nil
}
// HasPrefix returns true if the directory argument
// is a prefix of self (d) from the point of view of
// a file system.
//
// I.e., it's true if the argument equals or contains
// self (d) in a file path sense.
//
// HasPrefix emulates the semantics of strings.HasPrefix
// such that the following are true:
//
// strings.HasPrefix("foobar", "foobar")
// strings.HasPrefix("foobar", "foo")
// strings.HasPrefix("foobar", "")
//
// d := fSys.ConfirmDir("/foo/bar")
// d.HasPrefix("/foo/bar")
// d.HasPrefix("/foo")
// d.HasPrefix("/")
//
// Not contacting a file system here to check for
// actual path existence.
//
// This is tested on linux, but will have trouble
// on other operating systems.
// TODO(monopole) Refactor when #golang/go/18358 closes.
// See also:
// https://github.com/golang/go/issues/18358
// https://github.com/golang/dep/issues/296
// https://github.com/golang/dep/blob/master/internal/fs/fs.go#L33
// https://codereview.appspot.com/5712045
func (d ConfirmedDir) HasPrefix(path ConfirmedDir) bool {
if path.String() == string(filepath.Separator) || path == d {
return true
}
return strings.HasPrefix(
string(d),
string(path)+string(filepath.Separator))
}
func (d ConfirmedDir) Join(path string) string {
return filepath.Join(string(d), path)
}
func (d ConfirmedDir) String() string {
return string(d)
}
/*
Copyright 2018 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 fs
import (
"bytes"
"os"
)
var _ File = &FakeFile{}
// FakeFile implements File in-memory for tests.
type FakeFile struct {
name string
content []byte
dir bool
open bool
}
// makeDir makes a fake directory.
func makeDir(name string) *FakeFile {
return &FakeFile{name: name, dir: true}
}
// Close marks the fake file closed.
func (f *FakeFile) Close() error {
f.open = false
return nil
}
// Read never fails, and doesn't mutate p.
func (f *FakeFile) Read(p []byte) (n int, err error) {
return len(p), nil
}
// Write saves the contents of the argument to memory.
func (f *FakeFile) Write(p []byte) (n int, err error) {
f.content = p
return len(p), nil
}
// ContentMatches returns true if v matches fake file's content.
func (f *FakeFile) ContentMatches(v []byte) bool {
return bytes.Equal(v, f.content)
}
// GetContent the content of a fake file.
func (f *FakeFile) GetContent() []byte {
return f.content
}
// Stat returns nil.
func (f *FakeFile) Stat() (os.FileInfo, error) {
return nil, nil
}
/*
Copyright 2018 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 fs
import (
"os"
"time"
)
var _ os.FileInfo = &Fakefileinfo{}
// Fakefileinfo implements Fakefileinfo using a fake in-memory filesystem.
type Fakefileinfo struct {
*FakeFile
}
// Name returns the name of the file
func (fi *Fakefileinfo) Name() string { return fi.name }
// Size returns the size of the file
func (fi *Fakefileinfo) Size() int64 { return int64(len(fi.content)) }
// Mode returns the file mode
func (fi *Fakefileinfo) Mode() os.FileMode { return 0777 }
// ModTime returns the modification time
func (fi *Fakefileinfo) ModTime() time.Time { return time.Time{} }
// IsDir returns if it is a directory
func (fi *Fakefileinfo) IsDir() bool { return fi.dir }
// Sys should return underlying data source, but it now returns nil
func (fi *Fakefileinfo) Sys() interface{} { return nil }
/*
Copyright 2018 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 fs
import (
"fmt"
"path/filepath"
"sort"
"strings"
"sigs.k8s.io/kustomize/pkg/constants"
)
var _ FileSystem = &fakeFs{}
// fakeFs implements FileSystem using a fake in-memory filesystem.
type fakeFs struct {
m map[string]*FakeFile
}
// MakeFakeFS returns an instance of fakeFs with no files in it.
func MakeFakeFS() *fakeFs {
result := &fakeFs{m: map[string]*FakeFile{}}
result.Mkdir("/")
return result
}
// kustomizationContent is used in tests.
const kustomizationContent = `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: some-prefix
nameSuffix: some-suffix
# Labels to add to all objects and selectors.
# These labels would also be used to form the selector for apply --prune
# Named differently than “labels” to avoid confusion with metadata for this object
commonLabels:
app: helloworld
commonAnnotations:
note: This is an example annotation
resources: []
#- service.yaml
#- ../some-dir/
# There could also be configmaps in Base, which would make these overlays
configMapGenerator: []
# There could be secrets in Base, if just using a fork/rebase workflow
secretGenerator: []
`
// Create assures a fake file appears in the in-memory file system.
func (fs *fakeFs) Create(name string) (File, error) {
f := &FakeFile{}
f.open = true
fs.m[name] = f
return fs.m[name], nil
}
// Mkdir assures a fake directory appears in the in-memory file system.
func (fs *fakeFs) Mkdir(name string) error {
fs.m[name] = makeDir(name)
return nil
}
// MkdirAll delegates to Mkdir
func (fs *fakeFs) MkdirAll(name string) error {
return fs.Mkdir(name)
}
// RemoveAll presumably does rm -r on a path.
// There's no error.
func (fs *fakeFs) RemoveAll(name string) error {
var toRemove []string
for k := range fs.m {
if strings.HasPrefix(k, name) {
toRemove = append(toRemove, k)
}
}
for _, k := range toRemove {
delete(fs.m, k)
}
return nil
}
// Open returns a fake file in the open state.
func (fs *fakeFs) Open(name string) (File, error) {
if _, found := fs.m[name]; !found {
return nil, fmt.Errorf("file %q cannot be opened", name)
}
return fs.m[name], nil
}
// CleanedAbs cannot fail.
func (fs *fakeFs) CleanedAbs(path string) (ConfirmedDir, string, error) {
if fs.IsDir(path) {
return ConfirmedDir(path), "", nil
}
d := filepath.Dir(path)
if d == path {
return ConfirmedDir(d), "", nil
}
return ConfirmedDir(d), filepath.Base(path), nil
}
// Exists returns true if file is known.
func (fs *fakeFs) Exists(name string) bool {
_, found := fs.m[name]
return found
}
// Glob returns the list of matching files
func (fs *fakeFs) Glob(pattern string) ([]string, error) {
var result []string
for p := range fs.m {
if fs.pathMatch(p, pattern) {
result = append(result, p)
}
}
sort.Strings(result)
return result, nil
}
// IsDir returns true if the file exists and is a directory.
func (fs *fakeFs) IsDir(name string) bool {
f, found := fs.m[name]
if found && f.dir {
return true
}
if !strings.HasSuffix(name, "/") {
name = name + "/"
}
for k := range fs.m {
if strings.HasPrefix(k, name) {
return true
}
}
return false
}
// ReadFile always returns an empty bytes and error depending on content of m.
func (fs *fakeFs) ReadFile(name string) ([]byte, error) {
if ff, found := fs.m[name]; found {
return ff.content, nil
}
return nil, fmt.Errorf("cannot read file %q", name)
}
func (fs *fakeFs) ReadTestKustomization() ([]byte, error) {
return fs.ReadFile(constants.KustomizationFileNames[0])
}
// WriteFile always succeeds and does nothing.
func (fs *fakeFs) WriteFile(name string, c []byte) error {
ff := &FakeFile{}
ff.Write(c)
fs.m[name] = ff
return nil
}
// WriteTestKustomization writes a standard test file.
func (fs *fakeFs) WriteTestKustomization() {
fs.WriteTestKustomizationWith([]byte(kustomizationContent))
}
// WriteTestKustomizationWith writes a standard test file.
func (fs *fakeFs) WriteTestKustomizationWith(bytes []byte) {
fs.WriteFile(constants.KustomizationFileNames[0], bytes)
}
func (fs *fakeFs) pathMatch(path, pattern string) bool {
match, _ := filepath.Match(pattern, path)
return match
}
/*
Copyright 2018 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 fs provides a file system abstraction layer.
package fs
import (
"io"
"os"
)
// FileSystem groups basic os filesystem methods.
type FileSystem interface {
Create(name string) (File, error)
Mkdir(name string) error
MkdirAll(name string) error
RemoveAll(name string) error
Open(name string) (File, error)
IsDir(name string) bool
CleanedAbs(path string) (ConfirmedDir, string, error)
Exists(name string) bool
Glob(pattern string) ([]string, error)
ReadFile(name string) ([]byte, error)
WriteFile(name string, data []byte) error
}
// File groups the basic os.File methods.
type File interface {
io.ReadWriteCloser
Stat() (os.FileInfo, error)
}
/*
Copyright 2018 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 fs
import (
"os"
)
var _ File = &realFile{}
// realFile implements File using the local filesystem.
type realFile struct {
file *os.File
}
// Close closes a file.
func (f *realFile) Close() error { return f.file.Close() }
// Read reads a file's content.
func (f *realFile) Read(p []byte) (n int, err error) { return f.file.Read(p) }
// Write writes bytes to a file
func (f *realFile) Write(p []byte) (n int, err error) { return f.file.Write(p) }
// Stat returns an interface which has all the information regarding the file.
func (f *realFile) Stat() (os.FileInfo, error) { return f.file.Stat() }
/*
Copyright 2018 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 fs
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
)
var _ FileSystem = realFS{}
// realFS implements FileSystem using the local filesystem.
type realFS struct{}
// MakeRealFS makes an instance of realFS.
func MakeRealFS() FileSystem {
return realFS{}
}
// Create delegates to os.Create.
func (realFS) Create(name string) (File, error) { return os.Create(name) }
// Mkdir delegates to os.Mkdir.
func (realFS) Mkdir(name string) error {
return os.Mkdir(name, 0777|os.ModeDir)
}
// MkdirAll delegates to os.MkdirAll.
func (realFS) MkdirAll(name string) error {
return os.MkdirAll(name, 0777|os.ModeDir)
}
// RemoveAll delegates to os.RemoveAll.
func (realFS) RemoveAll(name string) error {
return os.RemoveAll(name)
}
// Open delegates to os.Open.
func (realFS) Open(name string) (File, error) { return os.Open(name) }
// CleanedAbs returns a cleaned, absolute path
// with no symbolic links split into directory
// and file components. If the entire path is
// a directory, the file component is an empty
// string.
func (x realFS) CleanedAbs(
path string) (ConfirmedDir, string, error) {
absRoot, err := filepath.Abs(path)
if err != nil {
return "", "", fmt.Errorf(
"abs path error on '%s' : %v", path, err)
}
deLinked, err := filepath.EvalSymlinks(absRoot)
if err != nil {
return "", "", fmt.Errorf(
"evalsymlink failure on '%s' : %v", path, err)
}
if x.IsDir(deLinked) {
return ConfirmedDir(deLinked), "", nil
}
d := filepath.Dir(deLinked)
if !x.IsDir(d) {
// Programmer/assumption error.
log.Fatalf("first part of '%s' not a directory", deLinked)
}
if d == deLinked {
// Programmer/assumption error.
log.Fatalf("d '%s' should be a subset of deLinked", d)
}
f := filepath.Base(deLinked)
if filepath.Join(d, f) != deLinked {
// Programmer/assumption error.
log.Fatalf("these should be equal: '%s', '%s'",
filepath.Join(d, f), deLinked)
}
return ConfirmedDir(d), f, nil
}
// Exists returns true if os.Stat succeeds.
func (realFS) Exists(name string) bool {
_, err := os.Stat(name)
return err == nil
}
// Glob returns the list of matching files
func (realFS) Glob(pattern string) ([]string, error) {
return filepath.Glob(pattern)
}
// IsDir delegates to os.Stat and FileInfo.IsDir
func (realFS) IsDir(name string) bool {
info, err := os.Stat(name)
if err != nil {
return false
}
return info.IsDir()
}
// ReadFile delegates to ioutil.ReadFile.
func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) }
// WriteFile delegates to ioutil.WriteFile with read/write permissions.
func (realFS) WriteFile(name string, c []byte) error {
return ioutil.WriteFile(name, c, 0666)
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"cloner.go",
"repospec.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/git",
importpath = "sigs.k8s.io/kustomize/pkg/git",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 git
import (
"bytes"
"os/exec"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/fs"
)
// Cloner is a function that can clone a git repo.
type Cloner func(repoSpec *RepoSpec) error
// ClonerUsingGitExec uses a local git install, as opposed
// to say, some remote API, to obtain a local clone of
// a remote repo.
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
gitProgram, err := exec.LookPath("git")
if err != nil {
return errors.Wrap(err, "no 'git' program on path")
}
repoSpec.cloneDir, err = fs.NewTmpConfirmedDir()
if err != nil {
return err
}
cmd := exec.Command(
gitProgram,
"clone",
repoSpec.CloneSpec(),
repoSpec.cloneDir.String())
var out bytes.Buffer
cmd.Stdout = &out
err = cmd.Run()
if err != nil {
return errors.Wrapf(err, "trouble cloning %s", repoSpec.raw)
}
if repoSpec.ref == "" {
return nil
}
cmd = exec.Command(gitProgram, "checkout", repoSpec.ref)
cmd.Dir = repoSpec.cloneDir.String()
err = cmd.Run()
if err != nil {
return errors.Wrapf(
err, "trouble checking out href %s", repoSpec.ref)
}
return nil
}
// DoNothingCloner returns a cloner that only sets
// cloneDir field in the repoSpec. It's assumed that
// the cloneDir is associated with some fake filesystem
// used in a test.
func DoNothingCloner(dir fs.ConfirmedDir) Cloner {
return func(rs *RepoSpec) error {
rs.cloneDir = dir
return nil
}
}
/*
Copyright 2018 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 git
import (
"fmt"
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/pkg/fs"
)
// RepoSpec specifies a git repository and a branch and path therein.
type RepoSpec struct {
// Raw, original spec, used to look for cycles.
// TODO(monopole): Drop raw, use processed fields instead.
raw string
// Host, e.g. github.com
host string
// orgRepo name (organization/repoName),
// e.g. kubernetes-sigs/kustomize
orgRepo string
// ConfirmedDir where the orgRepo is cloned to.
cloneDir fs.ConfirmedDir
// Relative path in the repository, and in the cloneDir,
// to a Kustomization.
path string
// Branch or tag reference.
ref string
}
// CloneSpec returns a string suitable for "git clone {spec}".
func (x *RepoSpec) CloneSpec() string {
if isAzureHost(x.host) || isAWSHost(x.host) {
return x.host + x.orgRepo
}
return x.host + x.orgRepo + gitSuffix
}
func (x *RepoSpec) CloneDir() fs.ConfirmedDir {
return x.cloneDir
}
func (x *RepoSpec) Raw() string {
return x.raw
}
func (x *RepoSpec) AbsPath() string {
return x.cloneDir.Join(x.path)
}
func (x *RepoSpec) Cleaner(fSys fs.FileSystem) func() error {
return func() error { return fSys.RemoveAll(x.cloneDir.String()) }
}
// From strings like git@github.com:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
if filepath.IsAbs(n) {
return nil, fmt.Errorf("uri looks like abs path: %s", n)
}
host, orgRepo, path, gitRef := parseGithubUrl(n)
if orgRepo == "" {
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
}
if host == "" {
return nil, fmt.Errorf("url lacks host: %s", n)
}
return &RepoSpec{
raw: n, host: host, orgRepo: orgRepo,
path: path, ref: gitRef}, nil
}
const (
refQuery = "?ref="
gitSuffix = ".git"
)
// From strings like git@github.com:someOrg/someRepo.git or
// https://github.com/someOrg/someRepo?ref=someHash, extract
// the parts.
func parseGithubUrl(n string) (
host string, orgRepo string, path string, gitRef string) {
host, n = parseHostSpec(n)
if strings.Contains(n, gitSuffix) {
index := strings.Index(n, gitSuffix)
orgRepo = n[0:index]
n = n[index+len(gitSuffix):]
path, gitRef = peelQuery(n)
return
}
i := strings.Index(n, "/")
if i < 1 {
return "", "", "", ""
}
j := strings.Index(n[i+1:], "/")
if j >= 0 {
j += i + 1
orgRepo = n[:j]
path, gitRef = peelQuery(n[j+1:])
} else {
path = ""
orgRepo, gitRef = peelQuery(n)
}
return
}
func peelQuery(arg string) (string, string) {
j := strings.Index(arg, refQuery)
if j >= 0 {
return arg[:j], arg[j+len(refQuery):]
}
return arg, ""
}
func parseHostSpec(n string) (string, string) {
var host string
// Start accumulating the host part.
for _, p := range []string{
// Order matters here.
"git::", "gh:", "ssh://", "https://", "http://",
"git@", "github.com:", "github.com/"} {
if len(p) < len(n) && strings.ToLower(n[:len(p)]) == p {
n = n[len(p):]
host += p
}
}
if host == "git@" {
i := strings.Index(n, "/")
if i > -1 {
host += n[:i+1]
n = n[i+1:]
} else {
i = strings.Index(n, ":")
if i > -1 {
host += n[:i+1]
n = n[i+1:]
}
}
return host, n
}
// If host is a http(s) or ssh URL, grab the domain part.
for _, p := range []string{
"ssh://", "https://", "http://"} {
if strings.HasSuffix(host, p) {
i := strings.Index(n, "/")
if i > -1 {
host = host + n[0:i+1]
n = n[i+1:]
}
break
}
}
return normalizeGitHostSpec(host), n
}
func normalizeGitHostSpec(host string) string {
s := strings.ToLower(host)
if strings.Contains(s, "github.com") {
if strings.Contains(s, "git@") || strings.Contains(s, "ssh:") {
host = "git@github.com:"
} else {
host = "https://github.com/"
}
}
if strings.HasPrefix(s, "git::") {
host = strings.TrimLeft(s, "git::")
}
return host
}
// The format of Azure repo URL is documented
// https://docs.microsoft.com/en-us/azure/devops/repos/git/clone?view=vsts&tabs=visual-studio#clone_url
func isAzureHost(host string) bool {
return strings.Contains(host, "dev.azure.com") ||
strings.Contains(host, "visualstudio.com")
}
// The format of AWS repo URL is documented
// https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html
func isAWSHost(host string) bool {
return strings.Contains(host, "amazonaws.com")
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["gvk.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/gvk",
importpath = "sigs.k8s.io/kustomize/pkg/gvk",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 gvk
import (
"strings"
)
// Gvk identifies a Kubernetes API type.
// https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md
type Gvk struct {
Group string `json:"group,omitempty" yaml:"group,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
}
// FromKind makes a Gvk with only the kind specified.
func FromKind(k string) Gvk {
return Gvk{
Kind: k,
}
}
// Values that are brief but meaningful in logs.
const (
noGroup = "~G"
noVersion = "~V"
noKind = "~K"
separator = "_"
)
// String returns a string representation of the GVK.
func (x Gvk) String() string {
g := x.Group
if g == "" {
g = noGroup
}
v := x.Version
if v == "" {
v = noVersion
}
k := x.Kind
if k == "" {
k = noKind
}
return strings.Join([]string{g, v, k}, separator)
}
// Equals returns true if the Gvk's have equal fields.
func (x Gvk) Equals(o Gvk) bool {
return x.Group == o.Group && x.Version == o.Version && x.Kind == o.Kind
}
// An attempt to order things to help k8s, e.g.
// a Service should come before things that refer to it.
// Namespace should be first.
// In some cases order just specified to provide determinism.
var order = []string{
"Namespace",
"StorageClass",
"CustomResourceDefinition",
"ServiceAccount",
"Role",
"ClusterRole",
"RoleBinding",
"ClusterRoleBinding",
"ConfigMap",
"Secret",
"Service",
"Deployment",
"StatefulSet",
"CronJob",
"PodDisruptionBudget",
}
var typeOrders = func() map[string]int {
m := map[string]int{}
for i, n := range order {
m[n] = i
}
return m
}()
// IsLessThan returns true if self is less than the argument.
func (x Gvk) IsLessThan(o Gvk) bool {
indexI, foundI := typeOrders[x.Kind]
indexJ, foundJ := typeOrders[o.Kind]
if foundI && foundJ {
if indexI != indexJ {
return indexI < indexJ
}
}
if foundI && !foundJ {
return true
}
if !foundI && foundJ {
return false
}
return x.String() < o.String()
}
// IsSelected returns true if `selector` selects `x`; otherwise, false.
// If `selector` and `x` are the same, return true.
// If `selector` is nil, it is considered a wildcard match, returning true.
// If selector fields are empty, they are considered wildcards matching
// anything in the corresponding fields, e.g.
//
// this item:
// <Group: "extensions", Version: "v1beta1", Kind: "Deployment">
//
// is selected by
// <Group: "", Version: "", Kind: "Deployment">
//
// but rejected by
// <Group: "apps", Version: "", Kind: "Deployment">
//
func (x Gvk) IsSelected(selector *Gvk) bool {
if selector == nil {
return true
}
if len(selector.Group) > 0 {
if x.Group != selector.Group {
return false
}
}
if len(selector.Version) > 0 {
if x.Version != selector.Version {
return false
}
}
if len(selector.Kind) > 0 {
if x.Kind != selector.Kind {
return false
}
}
return true
}
var clusterLevelKinds = []string{
"APIService",
"ClusterRoleBinding",
"ClusterRole",
"CustomResourceDefinition",
"Namespace",
"PersistentVolume",
}
// IsClusterKind returns true if x is a cluster-level Gvk
func (x Gvk) IsClusterKind() bool {
for _, k := range clusterLevelKinds {
if k == x.Kind {
return true
}
}
return false
}
// ClusterLevelGvks returns a slice of cluster-level Gvks
func ClusterLevelGvks() []Gvk {
var result []Gvk
for _, k := range clusterLevelKinds {
result = append(result, Gvk{Kind: k})
}
return result
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["ifc.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/ifc",
importpath = "sigs.k8s.io/kustomize/pkg/ifc",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 ifc holds miscellaneous interfaces used by kustomize.
package ifc
import (
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/types"
)
// Validator provides functions to validate annotations and labels
type Validator interface {
MakeAnnotationValidator() func(map[string]string) error
MakeLabelValidator() func(map[string]string) error
ValidateNamespace(string) []string
}
// Loader interface exposes methods to read bytes.
type Loader interface {
// Root returns the root location for this Loader.
Root() string
// New returns Loader located at newRoot.
New(newRoot string) (Loader, error)
// Load returns the bytes read from the location or an error.
Load(location string) ([]byte, error)
// Cleanup cleans the loader
Cleanup() error
}
// Kunstructured allows manipulation of k8s objects
// that do not have Golang structs.
type Kunstructured interface {
Map() map[string]interface{}
SetMap(map[string]interface{})
Copy() Kunstructured
GetFieldValue(string) (string, error)
MarshalJSON() ([]byte, error)
UnmarshalJSON([]byte) error
GetGvk() gvk.Gvk
GetKind() string
GetName() string
SetName(string)
GetLabels() map[string]string
SetLabels(map[string]string)
GetAnnotations() map[string]string
SetAnnotations(map[string]string)
}
// KunstructuredFactory makes instances of Kunstructured.
type KunstructuredFactory interface {
SliceFromBytes([]byte) ([]Kunstructured, error)
FromMap(m map[string]interface{}) Kunstructured
MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (Kunstructured, error)
MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (Kunstructured, error)
Set(ldr Loader)
}
// See core.v1.SecretTypeOpaque
const SecretTypeOpaque = "Opaque"
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["factory.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer",
importpath = "sigs.k8s.io/kustomize/pkg/ifc/transformer",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 patch holds miscellaneous interfaces used by kustomize.
package transformer
import (
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// Factory makes transformers
type Factory interface {
MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error)
MakeHashTransformer() transformers.Transformer
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"deprecatedimage.go",
"image.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/image",
importpath = "sigs.k8s.io/kustomize/pkg/image",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2019 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 image
// DeprecatedImage contains an image and a new tag,
// which will replace the original tag.
// Deprecated, instead use Image.
type DeprecatedImage struct {
// Name is a tag-less image name.
Name string `json:"name,omitempty" yaml:"name,omitempty"`
// NewTag is the value to use in replacing the original tag.
NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"`
// Digest is the value used to replace the original image tag.
// If digest is present NewTag value is ignored.
Digest string `json:"digest,omitempty" yaml:"digest,omitempty"`
}
/*
Copyright 2019 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 image provides struct definitions and libraries
// for image overwriting of names, tags and digest.
package image
// Image contains an image name, a new name, a new tag or digest,
// which will replace the original name and tag.
type Image struct {
// Name is a tag-less image name.
Name string `json:"name,omitempty" yaml:"name,omitempty"`
// NewName is the value used to replace the original name.
NewName string `json:"newName,omitempty" yaml:"newName,omitempty"`
// NewTag is the value used to replace the original tag.
NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"`
// Digest is the value used to replace the original image tag.
// If digest is present NewTag value is ignored.
Digest string `json:"digest,omitempty" yaml:"digest,omitempty"`
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"configmaperror.go",
"kustomizationerror.go",
"patcherror.go",
"resourceerror.go",
"secreterror.go",
"yamlformaterror.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/internal/error",
importpath = "sigs.k8s.io/kustomize/pkg/internal/error",
visibility = ["//vendor/sigs.k8s.io/kustomize/pkg:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 error has contextual error types.
package error
import "fmt"
// ConfigmapError represents error with a configmap.
type ConfigmapError struct {
Path string
ErrorMsg string
}
func (e ConfigmapError) Error() string {
return fmt.Sprintf("Kustomization file [%s] encounters a configmap error: %s\n", e.Path, e.ErrorMsg)
}
/*
Copyright 2018 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 error
import (
"fmt"
)
// KustomizationError represents an error with a kustomization.
type KustomizationError struct {
KustomizationPath string
ErrorMsg string
}
func (ke KustomizationError) Error() string {
return fmt.Sprintf("Kustomization File [%s]: %s\n", ke.KustomizationPath, ke.ErrorMsg)
}
// KustomizationErrors collects all errors.
type KustomizationErrors struct {
kErrors []error
}
func (ke *KustomizationErrors) Error() string {
errormsg := ""
for _, e := range ke.kErrors {
errormsg += e.Error() + "\n"
}
return errormsg
}
// Append adds error to a collection of errors.
func (ke *KustomizationErrors) Append(e error) {
ke.kErrors = append(ke.kErrors, e)
}
// Get returns all collected errors.
func (ke *KustomizationErrors) Get() []error {
return ke.kErrors
}
// BatchAppend adds all errors from another KustomizationErrors
func (ke *KustomizationErrors) BatchAppend(e KustomizationErrors) {
for _, err := range e.Get() {
ke.kErrors = append(ke.kErrors, err)
}
}
/*
Copyright 2018 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 error
import (
"fmt"
)
// PatchError represents error during Patch.
type PatchError struct {
KustomizationPath string
PatchFilepath string
ErrorMsg string
}
func (e PatchError) Error() string {
return fmt.Sprintf("Kustomization file [%s] encounters a patch error for [%s]: %s\n", e.KustomizationPath, e.PatchFilepath, e.ErrorMsg)
}
/*
Copyright 2018 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 error
import "fmt"
// ResourceError represents error in a resource.
type ResourceError struct {
KustomizationPath string
ResourceFilepath string
ErrorMsg string
}
func (e ResourceError) Error() string {
return fmt.Sprintf("Kustomization file [%s] encounters a resource error for [%s]: %s\n", e.KustomizationPath, e.ResourceFilepath, e.ErrorMsg)
}
/*
Copyright 2018 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 error
import "fmt"
// SecretError represents error with a secret.
type SecretError struct {
KustomizationPath string
// ErrorMsg is an error message
ErrorMsg string
}
func (e SecretError) Error() string {
return fmt.Sprintf("Kustomization file [%s] encounters a secret error: %s\n", e.KustomizationPath, e.ErrorMsg)
}
/*
Copyright 2018 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 error has contextual error types.
package error
import (
"fmt"
"strings"
)
// YamlFormatError represents error with yaml file name where json/yaml format error happens.
type YamlFormatError struct {
Path string
ErrorMsg string
}
func (e YamlFormatError) Error() string {
return fmt.Sprintf("YAML file [%s] encounters a format error.\n%s\n", e.Path, e.ErrorMsg)
}
// Handler handles YamlFormatError
func Handler(e error, path string) error {
if isYAMLSyntaxError(e) {
return YamlFormatError{
Path: path,
ErrorMsg: e.Error(),
}
}
return e
}
func isYAMLSyntaxError(e error) bool {
return strings.Contains(e.Error(), "error converting YAML to JSON") || strings.Contains(e.Error(), "error unmarshaling JSON")
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"fileloader.go",
"loader.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/loader",
importpath = "sigs.k8s.io/kustomize/pkg/loader",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/git:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 loader
import (
"fmt"
"log"
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/git"
"sigs.k8s.io/kustomize/pkg/ifc"
)
// fileLoader is a kustomization's interface to files.
//
// The directory in which a kustomization file sits
// is referred to below as the kustomization's root.
//
// An instance of fileLoader has an immutable root,
// and offers a `New` method returning a new loader
// with a new root.
//
// A kustomization file refers to two kinds of files:
//
// * supplemental data paths
//
// `Load` is used to visit these paths.
//
// They must terminate in or below the root.
//
// They hold things like resources, patches,
// data for ConfigMaps, etc.
//
// * bases; other kustomizations
//
// `New` is used to load bases.
//
// A base can be either a remote git repo URL, or
// a directory specified relative to the current
// root. In the former case, the repo is locally
// cloned, and the new loader is rooted on a path
// in that clone.
//
// As loaders create new loaders, a root history
// is established, and used to disallow:
//
// - A base that is a repository that, in turn,
// specifies a base repository seen previously
// in the loading stack (a cycle).
//
// - An overlay depending on a base positioned at
// or above it. I.e. '../foo' is OK, but '.',
// '..', '../..', etc. are disallowed. Allowing
// such a base has no advantages and encourages
// cycles, particularly if some future change
// were to introduce globbing to file
// specifications in the kustomization file.
//
// These restrictions assure that kustomizations
// are self-contained and relocatable, and impose
// some safety when relying on remote kustomizations,
// e.g. a ConfigMap generator specified to read
// from /etc/passwd will fail.
//
type fileLoader struct {
// Loader that spawned this loader.
// Used to avoid cycles.
referrer *fileLoader
// An absolute, cleaned path to a directory.
// The Load function reads from this directory,
// or directories below it.
root fs.ConfirmedDir
// If this is non-nil, the files were
// obtained from the given repository.
repoSpec *git.RepoSpec
// File system utilities.
fSys fs.FileSystem
// Used to clone repositories.
cloner git.Cloner
// Used to clean up, as needed.
cleaner func() error
}
// NewFileLoaderAtCwd returns a loader that loads from ".".
func NewFileLoaderAtCwd(fSys fs.FileSystem) *fileLoader {
return newLoaderOrDie(fSys, ".")
}
// NewFileLoaderAtRoot returns a loader that loads from "/".
func NewFileLoaderAtRoot(fSys fs.FileSystem) *fileLoader {
return newLoaderOrDie(fSys, string(filepath.Separator))
}
// Root returns the absolute path that is prepended to any
// relative paths used in Load.
func (l *fileLoader) Root() string {
return l.root.String()
}
func newLoaderOrDie(fSys fs.FileSystem, path string) *fileLoader {
root, err := demandDirectoryRoot(fSys, path)
if err != nil {
log.Fatalf("unable to make loader at '%s'; %v", path, err)
}
return newLoaderAtConfirmedDir(
root, fSys, nil, git.ClonerUsingGitExec)
}
// newLoaderAtConfirmedDir returns a new fileLoader with given root.
func newLoaderAtConfirmedDir(
root fs.ConfirmedDir, fSys fs.FileSystem,
referrer *fileLoader, cloner git.Cloner) *fileLoader {
return &fileLoader{
root: root,
referrer: referrer,
fSys: fSys,
cloner: cloner,
cleaner: func() error { return nil },
}
}
// Assure that the given path is in fact a directory.
func demandDirectoryRoot(
fSys fs.FileSystem, path string) (fs.ConfirmedDir, error) {
if path == "" {
return "", fmt.Errorf(
"loader root cannot be empty")
}
d, f, err := fSys.CleanedAbs(path)
if err != nil {
return "", fmt.Errorf(
"absolute path error in '%s' : %v", path, err)
}
if f != "" {
return "", fmt.Errorf(
"got file '%s', but '%s' must be a directory to be a root",
f, path)
}
return d, nil
}
// New returns a new Loader, rooted relative to current loader,
// or rooted in a temp directory holding a git repo clone.
func (l *fileLoader) New(path string) (ifc.Loader, error) {
if path == "" {
return nil, fmt.Errorf("new root cannot be empty")
}
repoSpec, err := git.NewRepoSpecFromUrl(path)
if err == nil {
// Treat this as git repo clone request.
if err := l.errIfRepoCycle(repoSpec); err != nil {
return nil, err
}
return newLoaderAtGitClone(repoSpec, l.fSys, l.referrer, l.cloner)
}
if filepath.IsAbs(path) {
return nil, fmt.Errorf("new root '%s' cannot be absolute", path)
}
root, err := demandDirectoryRoot(l.fSys, l.root.Join(path))
if err != nil {
return nil, err
}
if err := l.errIfGitContainmentViolation(root); err != nil {
return nil, err
}
if err := l.errIfArgEqualOrHigher(root); err != nil {
return nil, err
}
return newLoaderAtConfirmedDir(
root, l.fSys, l, l.cloner), nil
}
// newLoaderAtGitClone returns a new Loader pinned to a temporary
// directory holding a cloned git repo.
func newLoaderAtGitClone(
repoSpec *git.RepoSpec, fSys fs.FileSystem,
referrer *fileLoader, cloner git.Cloner) (ifc.Loader, error) {
err := cloner(repoSpec)
if err != nil {
return nil, err
}
root, f, err := fSys.CleanedAbs(repoSpec.AbsPath())
if err != nil {
return nil, err
}
// We don't know that the path requested in repoSpec
// is a directory until we actually clone it and look
// inside. That just happened, hence the error check
// is here.
if f != "" {
return nil, fmt.Errorf(
"'%s' refers to file '%s'; expecting directory",
repoSpec.AbsPath(), f)
}
return &fileLoader{
root: root,
referrer: referrer,
repoSpec: repoSpec,
fSys: fSys,
cloner: cloner,
cleaner: repoSpec.Cleaner(fSys),
}, nil
}
func (l *fileLoader) errIfGitContainmentViolation(
base fs.ConfirmedDir) error {
containingRepo := l.containingRepo()
if containingRepo == nil {
return nil
}
if !base.HasPrefix(containingRepo.CloneDir()) {
return fmt.Errorf(
"security; bases in kustomizations found in "+
"cloned git repos must be within the repo, "+
"but base '%s' is outside '%s'",
base, containingRepo.CloneDir())
}
return nil
}
// Looks back through referrers for a git repo, returning nil
// if none found.
func (l *fileLoader) containingRepo() *git.RepoSpec {
if l.repoSpec != nil {
return l.repoSpec
}
if l.referrer == nil {
return nil
}
return l.referrer.containingRepo()
}
// errIfArgEqualOrHigher tests whether the argument,
// is equal to or above the root of any ancestor.
func (l *fileLoader) errIfArgEqualOrHigher(
candidateRoot fs.ConfirmedDir) error {
if l.root.HasPrefix(candidateRoot) {
return fmt.Errorf(
"cycle detected: candidate root '%s' contains visited root '%s'",
candidateRoot, l.root)
}
if l.referrer == nil {
return nil
}
return l.referrer.errIfArgEqualOrHigher(candidateRoot)
}
// TODO(monopole): Distinguish branches?
// I.e. Allow a distinction between git URI with
// path foo and tag bar and a git URI with the same
// path but a different tag?
func (l *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
// TODO(monopole): Use parsed data instead of Raw().
if l.repoSpec != nil &&
strings.HasPrefix(l.repoSpec.Raw(), newRepoSpec.Raw()) {
return fmt.Errorf(
"cycle detected: URI '%s' referenced by previous URI '%s'",
newRepoSpec.Raw(), l.repoSpec.Raw())
}
if l.referrer == nil {
return nil
}
return l.referrer.errIfRepoCycle(newRepoSpec)
}
// Load returns content of file at the given relative path,
// else an error. The path must refer to a file in or
// below the current root.
func (l *fileLoader) Load(path string) ([]byte, error) {
if filepath.IsAbs(path) {
return nil, l.loadOutOfBounds(path)
}
d, f, err := l.fSys.CleanedAbs(l.root.Join(path))
if err != nil {
return nil, err
}
if f == "" {
return nil, fmt.Errorf(
"'%s' must be a file (got d='%s')", path, d)
}
if !d.HasPrefix(l.root) {
return nil, l.loadOutOfBounds(path)
}
return l.fSys.ReadFile(d.Join(f))
}
func (l *fileLoader) loadOutOfBounds(path string) error {
return fmt.Errorf(
"security; file '%s' is not in or below '%s'",
path, l.root)
}
// Cleanup runs the cleaner.
func (l *fileLoader) Cleanup() error {
return l.cleaner()
}
/*
Copyright 2018 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 loader has a data loading interface and various implementations.
package loader
import (
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/git"
"sigs.k8s.io/kustomize/pkg/ifc"
)
// NewLoader returns a Loader.
func NewLoader(path string, fSys fs.FileSystem) (ifc.Loader, error) {
repoSpec, err := git.NewRepoSpecFromUrl(path)
if err == nil {
return newLoaderAtGitClone(
repoSpec, fSys, nil, git.ClonerUsingGitExec)
}
root, err := demandDirectoryRoot(fSys, path)
if err != nil {
return nil, err
}
return newLoaderAtConfirmedDir(
root, fSys, nil, git.ClonerUsingGitExec), nil
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"json6902.go",
"strategicmerge.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/patch",
importpath = "sigs.k8s.io/kustomize/pkg/patch",
visibility = ["//visibility:public"],
deps = ["//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/patch/transformer:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 patch
import "sigs.k8s.io/kustomize/pkg/gvk"
// Json6902 represents a json patch for an object
// with format documented https://tools.ietf.org/html/rfc6902.
type Json6902 struct {
// Target refers to a Kubernetes object that the json patch will be
// applied to. It must refer to a Kubernetes resource under the
// purview of this kustomization. Target should use the
// raw name of the object (the name specified in its YAML,
// before addition of a namePrefix and a nameSuffix).
Target *Target `json:"target" yaml:"target"`
// relative file path for a json patch file inside a kustomization
Path string `json:"path,omitempty" yaml:"path,omitempty"`
}
// Target represents the kubernetes object that the patch is applied to
type Target struct {
gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Name string `json:"name" yaml:"name"`
}
/*
Copyright 2018 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 patch
// StrategicMerge represents a relative path to a
// stategic merge patch with the format
// https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md
type StrategicMerge string
// Append appends a slice of patch paths to a StrategicMerge slice
func Append(patches []StrategicMerge, paths ...string) []StrategicMerge {
for _, p := range paths {
patches = append(patches, StrategicMerge(p))
}
return patches
}
// Exist determines if a patch path exists in a slice of StrategicMerge
func Exist(patches []StrategicMerge, path string) bool {
for _, p := range patches {
if p == StrategicMerge(path) {
return true
}
}
return false
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"factory.go",
"patchjson6902json.go",
"util.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer",
importpath = "sigs.k8s.io/kustomize/pkg/patch/transformer",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 transformer
import (
"fmt"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resid"
"github.com/evanphx/json-patch"
"github.com/ghodss/yaml"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/patch"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// PatchJson6902Factory makes Json6902 transformers
type PatchJson6902Factory struct {
loader ifc.Loader
}
// NewPatchJson6902Factory returns a new PatchJson6902Factory.
func NewPatchJson6902Factory(l ifc.Loader) PatchJson6902Factory {
return PatchJson6902Factory{loader: l}
}
// MakePatchJson6902Transformer returns a transformer for applying Json6902 patch
func (f PatchJson6902Factory) MakePatchJson6902Transformer(patches []patch.Json6902) (transformers.Transformer, error) {
var ts []transformers.Transformer
for _, p := range patches {
t, err := f.makeOnePatchJson6902Transformer(p)
if err != nil {
return nil, err
}
if t != nil {
ts = append(ts, t)
}
}
return transformers.NewMultiTransformerWithConflictCheck(ts), nil
}
func (f PatchJson6902Factory) makeOnePatchJson6902Transformer(p patch.Json6902) (transformers.Transformer, error) {
if p.Target == nil {
return nil, fmt.Errorf("must specify the target field in patchesJson6902")
}
if p.Path == "" {
return nil, fmt.Errorf("must specify the path for a json patch file")
}
targetId := resid.NewResIdWithPrefixNamespace(
gvk.Gvk{
Group: p.Target.Group,
Version: p.Target.Version,
Kind: p.Target.Kind,
},
p.Target.Name,
"",
p.Target.Namespace,
)
rawOp, err := f.loader.Load(p.Path)
if err != nil {
return nil, err
}
if !isJsonFormat(rawOp) {
// if it isn't JSON, try to parse it as YAML
rawOp, err = yaml.YAMLToJSON(rawOp)
if err != nil {
return nil, err
}
}
decodedPatch, err := jsonpatch.DecodePatch(rawOp)
if err != nil {
return nil, err
}
return newPatchJson6902JSONTransformer(targetId, decodedPatch)
}
func isJsonFormat(data []byte) bool {
return data[0] == '['
}
/*
Copyright 2018 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 transformer
import (
"github.com/evanphx/json-patch"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// patchJson6902JSONTransformer applies patches.
type patchJson6902JSONTransformer struct {
target resid.ResId
patch jsonpatch.Patch
}
var _ transformers.Transformer = &patchJson6902JSONTransformer{}
// newPatchJson6902JSONTransformer constructs a PatchJson6902 transformer.
func newPatchJson6902JSONTransformer(t resid.ResId, p jsonpatch.Patch) (transformers.Transformer, error) {
if len(p) == 0 {
return transformers.NewNoOpTransformer(), nil
}
return &patchJson6902JSONTransformer{target: t, patch: p}, nil
}
// Transform apply the json patches on top of the base resources.
func (t *patchJson6902JSONTransformer) Transform(baseResourceMap resmap.ResMap) error {
obj, err := findTargetObj(baseResourceMap, t.target)
if obj == nil {
return err
}
rawObj, err := obj.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := t.patch.Apply(rawObj)
if err != nil {
return err
}
err = obj.UnmarshalJSON(modifiedObj)
if err != nil {
return err
}
return nil
}
/*
Copyright 2018 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 transformer
import (
"fmt"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
func findTargetObj(m resmap.ResMap, targetId resid.ResId) (*resource.Resource, error) {
matchedIds := m.FindByGVKN(targetId)
if targetId.Namespace() != "" {
var ids []resid.ResId
for _, id := range matchedIds {
if id.Namespace() == targetId.Namespace() {
ids = append(ids, id)
}
}
matchedIds = ids
}
if len(matchedIds) == 0 {
return nil, fmt.Errorf("couldn't find any object to apply the json patch %v", targetId)
}
if len(matchedIds) > 1 {
return nil, fmt.Errorf("found multiple objects that the patch can apply %v", matchedIds)
}
return m[matchedIds[0]], nil
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["resid.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/resid",
importpath = "sigs.k8s.io/kustomize/pkg/resid",
visibility = ["//visibility:public"],
deps = ["//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 resid
import (
"strings"
"sigs.k8s.io/kustomize/pkg/gvk"
)
// ResId conflates GroupVersionKind with a textual name to uniquely identify a kubernetes resource (object).
type ResId struct {
// Gvk of the resource.
gvKind gvk.Gvk
// original name of the resource before transformation.
name string
// namePrefix of the resource
// an untransformed resource has no prefix, fully transformed resource has an arbitrary number of prefixes
// concatenated together.
prefix string
// nameSuffix of the resource
// an untransformed resource has no suffix, fully transformed resource has an arbitrary number of suffixes
// concatenated together.
suffix string
// namespace the resource belongs to
// an untransformed resource has no namespace, fully transformed resource has the namespace from
// the top most overlay
namespace string
}
// NewResIdWithPrefixSuffixNamespace creates new resource identifier with a prefix, suffix and a namespace
func NewResIdWithPrefixSuffixNamespace(k gvk.Gvk, n, p, s, ns string) ResId {
return ResId{gvKind: k, name: n, prefix: p, suffix: s, namespace: ns}
}
// NewResIdWithPrefixNamespace creates new resource identifier with a prefix and a namespace
func NewResIdWithPrefixNamespace(k gvk.Gvk, n, p, ns string) ResId {
return ResId{gvKind: k, name: n, prefix: p, namespace: ns}
}
// NewResIdWithSuffixNamespace creates new resource identifier with a suffix and a namespace
func NewResIdWithSuffixNamespace(k gvk.Gvk, n, s, ns string) ResId {
return ResId{gvKind: k, name: n, suffix: s, namespace: ns}
}
// NewResIdWithPrefixSuffix creates new resource identifier with a prefix and suffix
func NewResIdWithPrefixSuffix(k gvk.Gvk, n, p, s string) ResId {
return ResId{gvKind: k, name: n, prefix: p, suffix: s}
}
// NewResId creates new resource identifier
func NewResId(k gvk.Gvk, n string) ResId {
return ResId{gvKind: k, name: n}
}
// NewResIdKindOnly creates new resource identifier
func NewResIdKindOnly(k string, n string) ResId {
return ResId{gvKind: gvk.FromKind(k), name: n}
}
const (
noNamespace = "~X"
noPrefix = "~P"
noName = "~N"
noSuffix = "~S"
separator = "|"
)
// String of ResId based on GVK, name and prefix
func (n ResId) String() string {
ns := n.namespace
if ns == "" {
ns = noNamespace
}
p := n.prefix
if p == "" {
p = noPrefix
}
nm := n.name
if nm == "" {
nm = noName
}
s := n.suffix
if s == "" {
s = noSuffix
}
return strings.Join(
[]string{n.gvKind.String(), ns, p, nm, s}, separator)
}
// GvknString of ResId based on GVK and name
func (n ResId) GvknString() string {
return n.gvKind.String() + separator + n.name
}
// GvknEquals return if two ResId have the same Group/Version/Kind and name
// The comparison excludes prefix and suffix
func (n ResId) GvknEquals(id ResId) bool {
return n.gvKind.Equals(id.gvKind) && n.name == id.name
}
// Gvk returns Group/Version/Kind of the resource.
func (n ResId) Gvk() gvk.Gvk {
return n.gvKind
}
// Name returns resource name.
func (n ResId) Name() string {
return n.name
}
// Namespace returns resource namespace.
func (n ResId) Namespace() string {
return n.namespace
}
// CopyWithNewPrefixSuffix make a new copy from current ResId
// and append a new prefix and suffix
func (n ResId) CopyWithNewPrefixSuffix(p, s string) ResId {
result := n
if p != "" {
result.prefix = n.concatPrefix(p)
}
if s != "" {
result.suffix = n.concatSuffix(s)
}
return result
}
// CopyWithNewNamespace make a new copy from current ResId and set a new namespace
func (n ResId) CopyWithNewNamespace(ns string) ResId {
result := n
result.namespace = ns
return result
}
// HasSameLeftmostPrefix check if two ResIds have the same
// left most prefix.
func (n ResId) HasSameLeftmostPrefix(id ResId) bool {
prefixes1 := n.prefixList()
prefixes2 := id.prefixList()
return prefixes1[0] == prefixes2[0]
}
// HasSameRightmostSuffix check if two ResIds have the same
// right most suffix.
func (n ResId) HasSameRightmostSuffix(id ResId) bool {
suffixes1 := n.suffixList()
suffixes2 := id.suffixList()
return suffixes1[len(suffixes1)-1] == suffixes2[len(suffixes2)-1]
}
func (n ResId) concatPrefix(p string) string {
if p == "" {
return n.prefix
}
if n.prefix == "" {
return p
}
return p + ":" + n.prefix
}
func (n ResId) concatSuffix(s string) string {
if s == "" {
return n.suffix
}
if n.suffix == "" {
return s
}
return n.suffix + ":" + s
}
func (n ResId) prefixList() []string {
return strings.Split(n.prefix, ":")
}
func (n ResId) suffixList() []string {
return strings.Split(n.suffix, ":")
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"factory.go",
"idslice.go",
"resmap.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/resmap",
importpath = "sigs.k8s.io/kustomize/pkg/resmap",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/internal/error:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 resmap
import (
"fmt"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/ifc"
internal "sigs.k8s.io/kustomize/pkg/internal/error"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
// Factory makes instances of ResMap.
type Factory struct {
resF *resource.Factory
}
// NewFactory returns a new resmap.Factory.
func NewFactory(rf *resource.Factory) *Factory {
return &Factory{resF: rf}
}
// RF returns a resource.Factory.
func (rmF *Factory) RF() *resource.Factory {
return rmF.resF
}
// FromFiles returns a ResMap given a resource path slice.
func (rmF *Factory) FromFiles(
loader ifc.Loader, paths []string) (ResMap, error) {
var result []ResMap
for _, path := range paths {
content, err := loader.Load(path)
if err != nil {
return nil, errors.Wrap(err, "Load from path "+path+" failed")
}
res, err := rmF.newResMapFromBytes(content)
if err != nil {
return nil, internal.Handler(err, path)
}
result = append(result, res)
}
return MergeWithErrorOnIdCollision(result...)
}
// newResMapFromBytes decodes a list of objects in byte array format.
func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) {
resources, err := rmF.resF.SliceFromBytes(b)
if err != nil {
return nil, err
}
result := ResMap{}
for _, res := range resources {
id := res.Id()
if _, found := result[id]; found {
return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id)
}
result[id] = res
}
return result, nil
}
// NewResMapFromConfigMapArgs returns a Resource slice given
// a configmap metadata slice from kustomization file.
func (rmF *Factory) NewResMapFromConfigMapArgs(argList []types.ConfigMapArgs, options *types.GeneratorOptions) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argList {
res, err := rmF.resF.MakeConfigMap(&args, options)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromConfigMapArgs")
}
resources = append(resources, res)
}
return newResMapFromResourceSlice(resources)
}
// NewResMapFromSecretArgs takes a SecretArgs slice, generates
// secrets from each entry, and accumulates them in a ResMap.
func (rmF *Factory) NewResMapFromSecretArgs(argsList []types.SecretArgs, options *types.GeneratorOptions) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argsList {
res, err := rmF.resF.MakeSecret(&args, options)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromSecretArgs")
}
resources = append(resources, res)
}
return newResMapFromResourceSlice(resources)
}
// Set sets the loader for the underlying factory
func (rmF *Factory) Set(ldr ifc.Loader) {
rmF.resF.Set(ldr)
}
func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) {
result := ResMap{}
for _, res := range resources {
id := res.Id()
if _, found := result[id]; found {
return nil, fmt.Errorf("duplicated %#v is not allowed", id)
}
result[id] = res
}
return result, nil
}
/*
Copyright 2018 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 resmap
import (
"sort"
"sigs.k8s.io/kustomize/pkg/resid"
)
// IdSlice implements the sort interface.
type IdSlice []resid.ResId
var _ sort.Interface = IdSlice{}
func (a IdSlice) Len() int { return len(a) }
func (a IdSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a IdSlice) Less(i, j int) bool {
if !a[i].Gvk().Equals(a[j].Gvk()) {
return a[i].Gvk().IsLessThan(a[j].Gvk())
}
return a[i].String() < a[j].String()
}
/*
Copyright 2018 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 resmap implements a map from ResId to Resource that tracks all resources in a kustomization.
package resmap
import (
"bytes"
"fmt"
"reflect"
"sort"
"github.com/ghodss/yaml"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
// ResMap is a map from ResId to Resource.
type ResMap map[resid.ResId]*resource.Resource
// FindByGVKN find the matched ResIds by Group/Version/Kind and Name
func (m ResMap) FindByGVKN(inputId resid.ResId) []resid.ResId {
var result []resid.ResId
for id := range m {
if id.GvknEquals(inputId) {
result = append(result, id)
}
}
return result
}
// DemandOneMatchForId find the matched resource by Group/Version/Kind and Name
func (m ResMap) DemandOneMatchForId(inputId resid.ResId) (*resource.Resource, bool) {
result := m.FindByGVKN(inputId)
if len(result) == 1 {
return m[result[0]], true
}
return nil, false
}
// EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`.
func (m ResMap) EncodeAsYaml() ([]byte, error) {
var ids []resid.ResId
for id := range m {
ids = append(ids, id)
}
sort.Sort(IdSlice(ids))
firstObj := true
var b []byte
buf := bytes.NewBuffer(b)
for _, id := range ids {
obj := m[id]
out, err := yaml.Marshal(obj.Map())
if err != nil {
return nil, err
}
if firstObj {
firstObj = false
} else {
_, err = buf.WriteString("---\n")
if err != nil {
return nil, err
}
}
_, err = buf.Write(out)
if err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}
// ErrorIfNotEqual returns error if maps are not equal.
func (m ResMap) ErrorIfNotEqual(m2 ResMap) error {
if len(m) != len(m2) {
var keySet1 []resid.ResId
var keySet2 []resid.ResId
for id := range m {
keySet1 = append(keySet1, id)
}
for id := range m2 {
keySet2 = append(keySet2, id)
}
return fmt.Errorf("maps has different number of entries: %#v doesn't equals %#v", keySet1, keySet2)
}
for id, obj1 := range m {
obj2, found := m2[id]
if !found {
return fmt.Errorf("%#v doesn't exist in %#v", id, m2)
}
if !reflect.DeepEqual(obj1, obj2) {
return fmt.Errorf("%#v doesn't deep equal %#v", obj1, obj2)
}
}
return nil
}
// DeepCopy clone the resmap into a new one
func (m ResMap) DeepCopy(rf *resource.Factory) ResMap {
mcopy := make(ResMap)
for id, obj := range m {
mcopy[id] = obj.DeepCopy()
}
return mcopy
}
// FilterBy returns a subset ResMap containing ResIds with
// the same namespace and leftmost name prefix and rightmost name
// as the inputId. If inputId is a cluster level resource, this
// returns the original ResMap.
func (m ResMap) FilterBy(inputId resid.ResId) ResMap {
if inputId.Gvk().IsClusterKind() {
return m
}
result := ResMap{}
for id, res := range m {
if id.Gvk().IsClusterKind() || id.Namespace() == inputId.Namespace() &&
id.HasSameLeftmostPrefix(inputId) &&
id.HasSameRightmostSuffix(inputId) {
result[id] = res
}
}
return result
}
// MergeWithErrorOnIdCollision combines multiple ResMap instances, failing on
// key collision and skipping nil maps.
// If all of the maps are nil, an empty ResMap is returned.
func MergeWithErrorOnIdCollision(maps ...ResMap) (ResMap, error) {
result := ResMap{}
for _, m := range maps {
if m == nil {
continue
}
for id, res := range m {
if _, found := result[id]; found {
return nil, fmt.Errorf("id '%q' already used", id)
}
result[id] = res
}
}
return result, nil
}
// MergeWithOverride combines multiple ResMap instances, allowing and sometimes
// demanding certain collisions and skipping nil maps.
// A collision would be demanded, say, when a generated ConfigMap has the
// "replace" option in its generation instructions, meaning it is supposed
// to replace something from the raw resources list.
// If all of the maps are nil, an empty ResMap is returned.
// When looping over the instances to combine them, if a resource id for
// resource X is found to be already in the combined map, then the behavior
// field for X must be BehaviorMerge or BehaviorReplace. If X is not in the
// map, then it's behavior cannot be merge or replace.
func MergeWithOverride(maps ...ResMap) (ResMap, error) {
result := maps[0]
if result == nil {
result = ResMap{}
}
for _, m := range maps[1:] {
if m == nil {
continue
}
for id, r := range m {
matchedId := result.FindByGVKN(id)
if len(matchedId) == 1 {
id = matchedId[0]
switch r.Behavior() {
case types.BehaviorReplace:
r.Replace(result[id])
result[id] = r
case types.BehaviorMerge:
r.Merge(result[id])
result[id] = r
default:
return nil, fmt.Errorf("id %#v exists; must merge or replace", id)
}
} else if len(matchedId) == 0 {
switch r.Behavior() {
case types.BehaviorMerge, types.BehaviorReplace:
return nil, fmt.Errorf("id %#v does not exist; cannot merge or replace", id)
default:
result[id] = r
}
} else {
return nil, fmt.Errorf("merge conflict, found multiple objects %v the Resmap %v can merge into", matchedId, id)
}
}
}
return result, nil
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"factory.go",
"resource.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/resource",
importpath = "sigs.k8s.io/kustomize/pkg/resource",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/internal/error:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 resource
import (
"encoding/json"
"fmt"
"log"
"sigs.k8s.io/kustomize/pkg/ifc"
internal "sigs.k8s.io/kustomize/pkg/internal/error"
"sigs.k8s.io/kustomize/pkg/patch"
"sigs.k8s.io/kustomize/pkg/types"
)
// Factory makes instances of Resource.
type Factory struct {
kf ifc.KunstructuredFactory
}
// NewFactory makes an instance of Factory.
func NewFactory(kf ifc.KunstructuredFactory) *Factory {
return &Factory{kf: kf}
}
// FromMap returns a new instance of Resource.
func (rf *Factory) FromMap(m map[string]interface{}) *Resource {
return &Resource{
Kunstructured: rf.kf.FromMap(m),
options: types.NewGenArgs(nil, nil),
}
}
// FromMapAndOption returns a new instance of Resource with given options.
func (rf *Factory) FromMapAndOption(m map[string]interface{}, args *types.GeneratorArgs, option *types.GeneratorOptions) *Resource {
return &Resource{
Kunstructured: rf.kf.FromMap(m),
options: types.NewGenArgs(args, option),
}
}
// FromKunstructured returns a new instance of Resource.
func (rf *Factory) FromKunstructured(
u ifc.Kunstructured) *Resource {
if u == nil {
log.Fatal("unstruct ifc must not be null")
}
return &Resource{
Kunstructured: u,
options: types.NewGenArgs(nil, nil),
}
}
// SliceFromPatches returns a slice of resources given a patch path
// slice from a kustomization file.
func (rf *Factory) SliceFromPatches(
ldr ifc.Loader, paths []patch.StrategicMerge) ([]*Resource, error) {
var result []*Resource
for _, path := range paths {
content, err := ldr.Load(string(path))
if err != nil {
return nil, err
}
res, err := rf.SliceFromBytes(content)
if err != nil {
return nil, internal.Handler(err, string(path))
}
result = append(result, res...)
}
return result, nil
}
// SliceFromBytes unmarshalls bytes into a Resource slice.
func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) {
kunStructs, err := rf.kf.SliceFromBytes(in)
if err != nil {
return nil, err
}
var result []*Resource
for len(kunStructs) > 0 {
u := kunStructs[0]
kunStructs = kunStructs[1:]
if u.GetKind() == "List" {
items := u.Map()["items"]
itemsSlice, ok := items.([]interface{})
if !ok {
return nil, fmt.Errorf("items in List is type %T, expected array", items)
}
for _, item := range itemsSlice {
itemJSON, err := json.Marshal(item)
if err != nil {
return nil, err
}
innerU, err := rf.kf.SliceFromBytes(itemJSON)
if err != nil {
return nil, err
}
// append innerU to kunStructs so nested Lists can be handled
kunStructs = append(kunStructs, innerU...)
}
} else {
result = append(result, rf.FromKunstructured(u))
}
}
return result, nil
}
// Set sets the loader for the underlying factory
func (rf *Factory) Set(ldr ifc.Loader) {
rf.kf.Set(ldr)
}
// MakeConfigMap makes an instance of Resource for ConfigMap
func (rf *Factory) MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (*Resource, error) {
u, err := rf.kf.MakeConfigMap(args, options)
if err != nil {
return nil, err
}
return &Resource{Kunstructured: u, options: types.NewGenArgs(&types.GeneratorArgs{Behavior: args.Behavior}, options)}, nil
}
// MakeSecret makes an instance of Resource for Secret
func (rf *Factory) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (*Resource, error) {
u, err := rf.kf.MakeSecret(args, options)
if err != nil {
return nil, err
}
return &Resource{Kunstructured: u, options: types.NewGenArgs(&types.GeneratorArgs{Behavior: args.Behavior}, options)}, nil
}
/*
Copyright 2018 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 resource implements representations of k8s API resources as "unstructured" objects.
package resource
import (
"strings"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/types"
)
// Resource is map representation of a Kubernetes API resource object
// paired with a GenerationBehavior.
type Resource struct {
ifc.Kunstructured
options *types.GenArgs
}
// String returns resource as JSON.
func (r *Resource) String() string {
bs, err := r.MarshalJSON()
if err != nil {
return "<" + err.Error() + ">"
}
return strings.TrimSpace(string(bs))
}
// DeepCopy returns a new copy of resource
func (r *Resource) DeepCopy() *Resource {
return &Resource{
Kunstructured: r.Kunstructured.Copy(),
options: r.options,
}
}
// Behavior returns the behavior for the resource.
func (r *Resource) Behavior() types.GenerationBehavior {
return r.options.Behavior()
}
// NeedAppendHash checks if the resource need a hash suffix
func (r *Resource) NeedHashSuffix() bool {
return r.options != nil && r.options.NeedsHashSuffix()
}
// Id returns the ResId for the resource.
func (r *Resource) Id() resid.ResId {
namespace, _ := r.GetFieldValue("metadata.namespace")
return resid.NewResIdWithPrefixNamespace(r.GetGvk(), r.GetName(), "", namespace)
}
// Merge performs merge with other resource.
func (r *Resource) Merge(other *Resource) {
r.Replace(other)
mergeConfigmap(r.Map(), other.Map(), r.Map())
}
// Replace performs replace with other resource.
func (r *Resource) Replace(other *Resource) {
r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels()))
r.SetAnnotations(
mergeStringMaps(other.GetAnnotations(), r.GetAnnotations()))
r.SetName(other.GetName())
r.options = other.options
}
// TODO: Add BinaryData once we sync to new k8s.io/api
func mergeConfigmap(
mergedTo map[string]interface{},
maps ...map[string]interface{}) {
mergedMap := map[string]interface{}{}
for _, m := range maps {
datamap, ok := m["data"].(map[string]interface{})
if ok {
for key, value := range datamap {
mergedMap[key] = value
}
}
}
mergedTo["data"] = mergedMap
}
func mergeStringMaps(maps ...map[string]string) map[string]string {
result := map[string]string{}
for _, m := range maps {
for key, value := range m {
result[key] = value
}
}
return result
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"kusttarget.go",
"resaccumulator.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/target",
importpath = "sigs.k8s.io/kustomize/pkg/target",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/internal/error:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/patch/transformer:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers/config:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 target implements state for the set of all resources to customize.
package target
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/ifc/transformer"
interror "sigs.k8s.io/kustomize/pkg/internal/error"
patchtransformer "sigs.k8s.io/kustomize/pkg/patch/transformer"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/kustomize/pkg/types"
)
// KustTarget encapsulates the entirety of a kustomization build.
type KustTarget struct {
kustomization *types.Kustomization
ldr ifc.Loader
fSys fs.FileSystem
rFactory *resmap.Factory
tFactory transformer.Factory
}
// NewKustTarget returns a new instance of KustTarget primed with a Loader.
func NewKustTarget(
ldr ifc.Loader,
fSys fs.FileSystem,
rFactory *resmap.Factory,
tFactory transformer.Factory) (*KustTarget, error) {
content, err := loadKustFile(ldr)
if err != nil {
return nil, err
}
content = types.DealWithDeprecatedFields(content)
var k types.Kustomization
err = unmarshal(content, &k)
if err != nil {
return nil, err
}
errs := k.EnforceFields()
if len(errs) > 0 {
return nil, fmt.Errorf("Failed to read kustomization file under %s:\n"+strings.Join(errs, "\n"), ldr.Root())
}
return &KustTarget{
kustomization: &k,
ldr: ldr,
fSys: fSys,
rFactory: rFactory,
tFactory: tFactory,
}, nil
}
func loadKustFile(ldr ifc.Loader) ([]byte, error) {
var content []byte
match := 0
for _, kf := range constants.KustomizationFileNames {
c, err := ldr.Load(kf)
if err == nil {
match += 1
content = c
}
}
switch match {
case 0:
return nil, fmt.Errorf("No kustomization file found in %s. Kustomize supports the following kustomization files: %s",
ldr.Root(), strings.Join(constants.KustomizationFileNames, ", "))
case 1:
return content, nil
default:
return nil, fmt.Errorf("Found multiple kustomization files under: %s\n", ldr.Root())
}
}
func unmarshal(y []byte, o interface{}) error {
j, err := yaml.YAMLToJSON(y)
if err != nil {
return err
}
dec := json.NewDecoder(bytes.NewReader(j))
dec.DisallowUnknownFields()
return dec.Decode(o)
}
// MakeCustomizedResMap creates a ResMap per kustomization instructions.
// The Resources in the returned ResMap are fully customized.
func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
ra, err := kt.accumulateTarget()
if err != nil {
return nil, err
}
err = ra.Transform(kt.tFactory.MakeHashTransformer())
if err != nil {
return nil, err
}
// Given that names have changed (prefixs/suffixes added),
// fix all the back references to those names.
err = ra.FixBackReferences()
if err != nil {
return nil, err
}
// With all the back references fixed, it's OK to resolve Vars.
err = ra.ResolveVars()
return ra.ResMap(), err
}
func (kt *KustTarget) shouldAddHashSuffixesToGeneratedResources() bool {
return kt.kustomization.GeneratorOptions == nil ||
!kt.kustomization.GeneratorOptions.DisableNameSuffixHash
}
// accumulateTarget returns a new ResAccumulator,
// holding customized resources and the data/rules used
// to do so. The name back references and vars are
// not yet fixed.
func (kt *KustTarget) accumulateTarget() (
ra *ResAccumulator, err error) {
// TODO(monopole): Get rid of the KustomizationErrors accumulator.
// It's not consistently used, and complicates tests.
errs := &interror.KustomizationErrors{}
ra, errs = kt.accumulateBases()
resources, err := kt.rFactory.FromFiles(
kt.ldr, kt.kustomization.Resources)
if err != nil {
errs.Append(errors.Wrap(err, "rawResources failed to read Resources"))
}
if len(errs.Get()) > 0 {
return ra, errs
}
err = ra.MergeResourcesWithErrorOnIdCollision(resources)
if err != nil {
errs.Append(errors.Wrap(err, "MergeResourcesWithErrorOnIdCollision"))
}
tConfig, err := config.MakeTransformerConfig(
kt.ldr, kt.kustomization.Configurations)
if err != nil {
return nil, err
}
err = ra.MergeConfig(tConfig)
if err != nil {
errs.Append(errors.Wrap(err, "MergeConfig"))
}
err = ra.MergeVars(kt.kustomization.Vars)
if err != nil {
errs.Append(errors.Wrap(err, "MergeVars"))
}
crdTc, err := config.LoadConfigFromCRDs(kt.ldr, kt.kustomization.Crds)
if err != nil {
errs.Append(errors.Wrap(err, "LoadCRDs"))
}
err = ra.MergeConfig(crdTc)
if err != nil {
errs.Append(errors.Wrap(err, "merge CRDs"))
}
resMap, err := kt.generateConfigMapsAndSecrets(errs)
if err != nil {
errs.Append(errors.Wrap(err, "generateConfigMapsAndSecrets"))
}
err = ra.MergeResourcesWithOverride(resMap)
if err != nil {
return nil, err
}
patches, err := kt.rFactory.RF().SliceFromPatches(
kt.ldr, kt.kustomization.PatchesStrategicMerge)
if err != nil {
errs.Append(errors.Wrap(err, "SliceFromPatches"))
}
if len(errs.Get()) > 0 {
return nil, errs
}
t, err := kt.newTransformer(patches, ra.tConfig)
if err != nil {
return nil, err
}
err = ra.Transform(t)
if err != nil {
return nil, err
}
return ra, nil
}
func (kt *KustTarget) generateConfigMapsAndSecrets(
errs *interror.KustomizationErrors) (resmap.ResMap, error) {
kt.rFactory.Set(kt.ldr)
cms, err := kt.rFactory.NewResMapFromConfigMapArgs(
kt.kustomization.ConfigMapGenerator, kt.kustomization.GeneratorOptions)
if err != nil {
errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs"))
}
secrets, err := kt.rFactory.NewResMapFromSecretArgs(
kt.kustomization.SecretGenerator, kt.kustomization.GeneratorOptions)
if err != nil {
errs.Append(errors.Wrap(err, "NewResMapFromSecretArgs"))
}
return resmap.MergeWithErrorOnIdCollision(cms, secrets)
}
// accumulateBases returns a new ResAccumulator
// holding customized resources and the data/rules
// used to customized them from only the _bases_
// of this KustTarget.
func (kt *KustTarget) accumulateBases() (
ra *ResAccumulator, errs *interror.KustomizationErrors) {
errs = &interror.KustomizationErrors{}
ra = MakeEmptyAccumulator()
for _, path := range kt.kustomization.Bases {
ldr, err := kt.ldr.New(path)
if err != nil {
errs.Append(errors.Wrap(err, "couldn't make loader for "+path))
continue
}
subKt, err := NewKustTarget(
ldr, kt.fSys, kt.rFactory, kt.tFactory)
if err != nil {
errs.Append(errors.Wrap(err, "couldn't make target for "+path))
ldr.Cleanup()
continue
}
subRa, err := subKt.accumulateTarget()
if err != nil {
errs.Append(errors.Wrap(err, "accumulateTarget"))
ldr.Cleanup()
continue
}
err = ra.MergeAccumulator(subRa)
if err != nil {
errs.Append(errors.Wrap(err, path))
}
ldr.Cleanup()
}
return ra, errs
}
// newTransformer makes a Transformer that does a collection
// of object transformations.
func (kt *KustTarget) newTransformer(
patches []*resource.Resource, tConfig *config.TransformerConfig) (
transformers.Transformer, error) {
var r []transformers.Transformer
t, err := kt.tFactory.MakePatchTransformer(patches, kt.rFactory.RF())
if err != nil {
return nil, err
}
r = append(r, t)
r = append(r, transformers.NewNamespaceTransformer(
string(kt.kustomization.Namespace), tConfig.NameSpace))
t, err = transformers.NewNamePrefixSuffixTransformer(
string(kt.kustomization.NamePrefix),
string(kt.kustomization.NameSuffix),
tConfig.NamePrefix,
)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewLabelsMapTransformer(
kt.kustomization.CommonLabels, tConfig.CommonLabels)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewAnnotationsMapTransformer(
kt.kustomization.CommonAnnotations, tConfig.CommonAnnotations)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = patchtransformer.NewPatchJson6902Factory(kt.ldr).
MakePatchJson6902Transformer(kt.kustomization.PatchesJson6902)
if err != nil {
return nil, err
}
r = append(r, t)
t, err = transformers.NewImageTransformer(kt.kustomization.Images)
if err != nil {
return nil, err
}
r = append(r, t)
return transformers.NewMultiTransformer(r), nil
}
/*
Copyright 2018 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 target
import (
"fmt"
"log"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
"sigs.k8s.io/kustomize/pkg/transformers/config"
"sigs.k8s.io/kustomize/pkg/types"
)
// ResAccumulator accumulates resources and the rules
// used to customize those resources.
// TODO(monopole): Move to "accumulator" package and make members private.
// This will make a better separation between KustTarget, which should
// be mainly concerned with data loading, and this class, which could
// become the home of all transformation data and logic.
type ResAccumulator struct {
resMap resmap.ResMap
tConfig *config.TransformerConfig
varSet types.VarSet
}
func MakeEmptyAccumulator() *ResAccumulator {
ra := &ResAccumulator{}
ra.resMap = make(resmap.ResMap)
ra.tConfig = &config.TransformerConfig{}
ra.varSet = types.VarSet{}
return ra
}
// ResMap returns a copy of the internal resMap.
func (ra *ResAccumulator) ResMap() resmap.ResMap {
result := make(resmap.ResMap)
for k, v := range ra.resMap {
result[k] = v
}
return result
}
func (ra *ResAccumulator) MergeResourcesWithErrorOnIdCollision(
resources resmap.ResMap) (err error) {
ra.resMap, err = resmap.MergeWithErrorOnIdCollision(
resources, ra.resMap)
return err
}
func (ra *ResAccumulator) MergeResourcesWithOverride(
resources resmap.ResMap) (err error) {
ra.resMap, err = resmap.MergeWithOverride(
ra.resMap, resources)
return err
}
func (ra *ResAccumulator) MergeConfig(
tConfig *config.TransformerConfig) (err error) {
ra.tConfig, err = ra.tConfig.Merge(tConfig)
return err
}
func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
return ra.varSet.MergeSlice(incoming)
}
func (ra *ResAccumulator) MergeAccumulator(other *ResAccumulator) (err error) {
err = ra.MergeResourcesWithErrorOnIdCollision(other.resMap)
if err != nil {
return err
}
err = ra.MergeConfig(other.tConfig)
if err != nil {
return err
}
return ra.varSet.MergeSet(&other.varSet)
}
// makeVarReplacementMap returns a map of Var names to
// their final values. The values are strings intended
// for substitution wherever the $(var.Name) occurs.
func (ra *ResAccumulator) makeVarReplacementMap() (map[string]string, error) {
result := map[string]string{}
for _, v := range ra.varSet.Set() {
id := resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name)
if r, found := ra.resMap.DemandOneMatchForId(id); found {
s, err := r.GetFieldValue(v.FieldRef.FieldPath)
if err != nil {
return nil, fmt.Errorf("field path err for var: %+v", v)
}
result[v.Name] = s
} else {
// Should this be an error?
log.Printf("var %v defined but not used", v)
}
}
return result, nil
}
func (ra *ResAccumulator) Transform(t transformers.Transformer) error {
return t.Transform(ra.resMap)
}
func (ra *ResAccumulator) ResolveVars() error {
replacementMap, err := ra.makeVarReplacementMap()
if err != nil {
return err
}
return ra.Transform(transformers.NewRefVarTransformer(
replacementMap, ra.tConfig.VarReference))
}
func (ra *ResAccumulator) FixBackReferences() (err error) {
if ra.tConfig.NameReference == nil {
return nil
}
return ra.Transform(transformers.NewNameReferenceTransformer(
ra.tConfig.NameReference))
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"image.go",
"labelsandannotations.go",
"multitransformer.go",
"mutatefield.go",
"namereference.go",
"namespace.go",
"nooptransformer.go",
"prefixsuffixname.go",
"refvars.go",
"transformer.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/transformers",
importpath = "sigs.k8s.io/kustomize/pkg/transformers",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/expansion:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/image:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers/config:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers/config:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"factory.go",
"factorycrd.go",
"fieldspec.go",
"namebackreferences.go",
"transformerconfig.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/transformers/config",
importpath = "sigs.k8s.io/kustomize/pkg/transformers/config",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/go-openapi/spec:go_default_library",
"//vendor/k8s.io/kube-openapi/pkg/common:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"commonannotations.go",
"commonlabels.go",
"defaultconfig.go",
"nameprefix.go",
"namereference.go",
"namespace.go",
"varreference.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
importpath = "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 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 defaultconfig
const commonAnnotationFieldSpecs = `
commonAnnotations:
- path: metadata/annotations
create: true
- path: spec/template/metadata/annotations
create: true
version: v1
kind: ReplicationController
- path: spec/template/metadata/annotations
create: true
kind: Deployment
- path: spec/template/metadata/annotations
create: true
kind: ReplicaSet
- path: spec/template/metadata/annotations
create: true
kind: DaemonSet
- path: spec/template/metadata/annotations
create: true
kind: StatefulSet
- path: spec/template/metadata/annotations
create: true
group: batch
kind: Job
- path: spec/jobTemplate/metadata/annotations
create: true
group: batch
kind: CronJob
- path: spec/jobTemplate/spec/template/metadata/annotations
create: true
group: batch
kind: CronJob
`
/*
Copyright 2018 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 defaultconfig
const commonLabelFieldSpecs = `
commonLabels:
- path: metadata/labels
create: true
- path: spec/selector
create: true
version: v1
kind: Service
- path: spec/selector
create: true
version: v1
kind: ReplicationController
- path: spec/template/metadata/labels
create: true
version: v1
kind: ReplicationController
- path: spec/selector/matchLabels
create: true
kind: Deployment
- path: spec/template/metadata/labels
create: true
kind: Deployment
- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/selector/matchLabels
create: true
kind: ReplicaSet
- path: spec/template/metadata/labels
create: true
kind: ReplicaSet
- path: spec/selector/matchLabels
create: true
kind: DaemonSet
- path: spec/template/metadata/labels
create: true
kind: DaemonSet
- path: spec/selector/matchLabels
create: true
group: apps
kind: StatefulSet
- path: spec/template/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/volumeClaimTemplates/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/selector/matchLabels
create: false
group: batch
kind: Job
- path: spec/template/metadata/labels
create: true
group: batch
kind: Job
- path: spec/jobTemplate/spec/selector/matchLabels
create: false
group: batch
kind: CronJob
- path: spec/jobTemplate/metadata/labels
create: true
group: batch
kind: CronJob
- path: spec/jobTemplate/spec/template/metadata/labels
create: true
group: batch
kind: CronJob
- path: spec/selector/matchLabels
create: false
group: policy
kind: PodDisruptionBudget
- path: spec/podSelector/matchLabels
create: false
group: networking.k8s.io
kind: NetworkPolicy
- path: spec/ingress/from/podSelector/matchLabels
create: false
group: networking.k8s.io
kind: NetworkPolicy
- path: spec/egress/to/podSelector/matchLabels
create: false
group: networking.k8s.io
kind: NetworkPolicy
`
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment