Merge pull request #94871 from neolit123/1.20-kubeadm-remove-experimental-kustomize

kubeadm: remove the --experimental-kustomize feature
This commit is contained in:
Kubernetes Prow Robot 2020-09-24 08:16:06 -07:00 committed by GitHub
commit 770eb2c4a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 32 additions and 1251 deletions

View File

@ -462,7 +462,6 @@ func isAllowedFlag(flagName string) bool {
kubeadmcmdoptions.NodeCRISocket,
kubeadmcmdoptions.KubeconfigDir,
kubeadmcmdoptions.UploadCerts,
kubeadmcmdoptions.Kustomize,
kubeadmcmdoptions.Patches,
"print-join-command", "rootfs", "v")
if knownFlags.Has(flagName) {

View File

@ -102,7 +102,6 @@ type initOptions struct {
externalClusterCfg *kubeadmapiv1beta2.ClusterConfiguration
uploadCerts bool
skipCertificateKeyPrint bool
kustomizeDir string
patchesDir string
}
@ -125,7 +124,6 @@ type initData struct {
outputWriter io.Writer
uploadCerts bool
skipCertificateKeyPrint bool
kustomizeDir string
patchesDir string
}
@ -282,7 +280,6 @@ func AddInitOtherFlags(flagSet *flag.FlagSet, initOptions *initOptions) {
&initOptions.skipCertificateKeyPrint, options.SkipCertificateKeyPrint, initOptions.skipCertificateKeyPrint,
"Don't print the key used to encrypt the control-plane certificates.",
)
options.AddKustomizePodsFlag(flagSet, &initOptions.kustomizeDir)
options.AddPatchesFlag(flagSet, &initOptions.patchesDir)
}
@ -419,7 +416,6 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io
outputWriter: out,
uploadCerts: options.uploadCerts,
skipCertificateKeyPrint: options.skipCertificateKeyPrint,
kustomizeDir: options.kustomizeDir,
patchesDir: options.patchesDir,
}, nil
}
@ -553,11 +549,6 @@ func (d *initData) Tokens() []string {
return tokens
}
// KustomizeDir returns the folder where kustomize patches for static pod manifest are stored
func (d *initData) KustomizeDir() string {
return d.kustomizeDir
}
// PatchesDir returns the folder where patches for components are stored
func (d *initData) PatchesDir() string {
return d.patchesDir

View File

@ -129,7 +129,6 @@ type joinOptions struct {
ignorePreflightErrors []string
externalcfg *kubeadmapiv1beta2.JoinConfiguration
joinControlPlane *kubeadmapiv1beta2.JoinControlPlane
kustomizeDir string
patchesDir string
}
@ -145,7 +144,6 @@ type joinData struct {
clientSet *clientset.Clientset
ignorePreflightErrors sets.String
outputWriter io.Writer
kustomizeDir string
patchesDir string
}
@ -287,7 +285,6 @@ func addJoinOtherFlags(flagSet *flag.FlagSet, joinOptions *joinOptions) {
&joinOptions.controlPlane, options.ControlPlane, joinOptions.controlPlane,
"Create a new control plane instance on this node",
)
options.AddKustomizePodsFlag(flagSet, &joinOptions.kustomizeDir)
options.AddPatchesFlag(flagSet, &joinOptions.patchesDir)
}
@ -443,7 +440,6 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri
tlsBootstrapCfg: tlsBootstrapCfg,
ignorePreflightErrors: ignorePreflightErrorsSet,
outputWriter: out,
kustomizeDir: opt.kustomizeDir,
patchesDir: opt.patchesDir,
}, nil
}
@ -510,11 +506,6 @@ func (j *joinData) OutputWriter() io.Writer {
return j.outputWriter
}
// KustomizeDir returns the folder where kustomize patches for static pod manifest are stored
func (j *joinData) KustomizeDir() string {
return j.kustomizeDir
}
// PatchesDir returns the folder where patches for components are stored
func (j *joinData) PatchesDir() string {
return j.patchesDir

View File

@ -143,9 +143,6 @@ const (
// EtcdUpgrade flag instruct kubeadm to execute etcd upgrade during upgrades
EtcdUpgrade = "etcd-upgrade"
// Kustomize flag sets the folder where kustomize patches for static pod manifest are stored
Kustomize = "experimental-kustomize"
// Patches flag sets the folder where kubeadm component patches are stored
Patches = "experimental-patches"
)

View File

@ -17,7 +17,6 @@ limitations under the License.
package options
import (
"fmt"
"strings"
"github.com/spf13/pflag"
@ -90,12 +89,6 @@ func AddKubeadmOtherFlags(flagSet *pflag.FlagSet, rootfsPath *string) {
)
}
// AddKustomizePodsFlag adds the --kustomize flag to the given flagset
func AddKustomizePodsFlag(fs *pflag.FlagSet, kustomizeDir *string) {
fs.StringVarP(kustomizeDir, Kustomize, "k", *kustomizeDir, "The path where kustomize patches for static pod manifests are stored.")
fs.MarkDeprecated(Kustomize, fmt.Sprintf("This flag is deprecated and will be removed in a future version. Please use %s instead.", Patches))
}
// AddPatchesFlag adds the --patches flag to the given flagset
func AddPatchesFlag(fs *pflag.FlagSet, patchesDir *string) {
fs.StringVar(patchesDir, Patches, *patchesDir, `Path to a directory that contains files named `+

View File

@ -100,7 +100,6 @@ func getControlPlanePhaseFlags(name string) []string {
options.CertificatesDir,
options.KubernetesVersion,
options.ImageRepository,
options.Kustomize,
}
if name == "all" || name == kubeadmconstants.KubeAPIServer {
flags = append(flags,
@ -145,6 +144,6 @@ func runControlPlaneSubphase(component string) func(c workflow.RunData) error {
cfg := data.Cfg()
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
return controlplane.CreateStaticPodFiles(data.ManifestDir(), data.KustomizeDir(), data.PatchesDir(), &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, component)
return controlplane.CreateStaticPodFiles(data.ManifestDir(), data.PatchesDir(), &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, component)
}
}

View File

@ -45,6 +45,5 @@ type InitData interface {
OutputWriter() io.Writer
Client() (clientset.Interface, error)
Tokens() []string
KustomizeDir() string
PatchesDir() string
}

View File

@ -48,5 +48,4 @@ func (t *testInitData) ExternalCA() bool { return false }
func (t *testInitData) OutputWriter() io.Writer { return nil }
func (t *testInitData) Client() (clientset.Interface, error) { return nil, nil }
func (t *testInitData) Tokens() []string { return nil }
func (t *testInitData) KustomizeDir() string { return "" }
func (t *testInitData) PatchesDir() string { return "" }

View File

@ -69,7 +69,6 @@ func getEtcdPhaseFlags() []string {
options.CertificatesDir,
options.CfgPath,
options.ImageRepository,
options.Kustomize,
options.Patches,
}
return flags
@ -95,7 +94,7 @@ func runEtcdPhaseLocal() func(c workflow.RunData) error {
fmt.Printf("[dryrun] Would ensure that %q directory is present\n", cfg.Etcd.Local.DataDir)
}
fmt.Printf("[etcd] Creating static Pod manifest for local etcd in %q\n", data.ManifestDir())
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(data.ManifestDir(), data.KustomizeDir(), data.PatchesDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(data.ManifestDir(), data.PatchesDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
return errors.Wrap(err, "error creating local etcd static pod manifest file")
}
} else {

View File

@ -44,7 +44,7 @@ func getControlPlaneJoinPhaseFlags(name string) []string {
options.NodeName,
}
if name == "etcd" {
flags = append(flags, options.Kustomize, options.Patches)
flags = append(flags, options.Patches)
}
if name != "mark-control-plane" {
flags = append(flags, options.APIServerAdvertiseAddress)
@ -147,7 +147,7 @@ func runEtcdPhase(c workflow.RunData) error {
// because it needs two members as majority to agree on the consensus. You will only see this behavior between the time
// etcdctl member add informs the cluster about the new member and the new member successfully establishing a connection to the
// existing one."
if err := etcdphase.CreateStackedEtcdStaticPodManifestFile(client, kubeadmconstants.GetStaticPodDirectory(), data.KustomizeDir(), data.PatchesDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
if err := etcdphase.CreateStackedEtcdStaticPodManifestFile(client, kubeadmconstants.GetStaticPodDirectory(), data.PatchesDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
return errors.Wrap(err, "error creating local etcd static pod manifest file")
}

View File

@ -78,7 +78,6 @@ func getControlPlanePreparePhaseFlags(name string) []string {
options.TLSBootstrapToken,
options.TokenStr,
options.CertificateKey,
options.Kustomize,
options.Patches,
}
case "download-certs":
@ -124,7 +123,6 @@ func getControlPlanePreparePhaseFlags(name string) []string {
options.APIServerBindPort,
options.CfgPath,
options.ControlPlane,
options.Kustomize,
options.Patches,
}
default:
@ -191,7 +189,6 @@ func runControlPlanePrepareControlPlaneSubphase(c workflow.RunData) error {
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
err := controlplane.CreateStaticPodFiles(
kubeadmconstants.GetStaticPodDirectory(),
data.KustomizeDir(),
data.PatchesDir(),
&cfg.ClusterConfiguration,
&cfg.LocalAPIEndpoint,

View File

@ -35,6 +35,5 @@ type JoinData interface {
ClientSet() (*clientset.Clientset, error)
IgnorePreflightErrors() sets.String
OutputWriter() io.Writer
KustomizeDir() string
PatchesDir() string
}

View File

@ -38,5 +38,4 @@ func (j *testJoinData) InitCfg() (*kubeadmapi.InitConfiguration, error) { return
func (j *testJoinData) ClientSet() (*clientset.Clientset, error) { return nil, nil }
func (j *testJoinData) IgnorePreflightErrors() sets.String { return nil }
func (j *testJoinData) OutputWriter() io.Writer { return nil }
func (j *testJoinData) KustomizeDir() string { return "" }
func (j *testJoinData) PatchesDir() string { return "" }

View File

@ -39,7 +39,6 @@ func NewControlPlane() workflow.Phase {
options.KubeconfigPath,
options.CertificateRenewal,
options.EtcdUpgrade,
options.Kustomize,
options.Patches,
},
}
@ -65,18 +64,17 @@ func runControlPlane() func(c workflow.RunData) error {
dryRun := data.DryRun()
etcdUpgrade := data.EtcdUpgrade()
renewCerts := data.RenewCerts()
kustomizeDir := data.KustomizeDir()
patchesDir := data.PatchesDir()
// Upgrade the control plane and etcd if installed on this node
fmt.Printf("[upgrade] Upgrading your Static Pod-hosted control plane instance to version %q...\n", cfg.KubernetesVersion)
if dryRun {
return upgrade.DryRunStaticPodUpgrade(kustomizeDir, patchesDir, cfg)
return upgrade.DryRunStaticPodUpgrade(patchesDir, cfg)
}
waiter := apiclient.NewKubeWaiter(data.Client(), upgrade.UpgradeManifestTimeout, os.Stdout)
if err := upgrade.PerformStaticPodUpgrade(client, waiter, cfg, etcdUpgrade, renewCerts, kustomizeDir, patchesDir); err != nil {
if err := upgrade.PerformStaticPodUpgrade(client, waiter, cfg, etcdUpgrade, renewCerts, patchesDir); err != nil {
return errors.Wrap(err, "couldn't complete the static pod upgrade")
}

View File

@ -32,6 +32,5 @@ type Data interface {
IsControlPlaneNode() bool
Client() clientset.Interface
IgnorePreflightErrors() sets.String
KustomizeDir() string
PatchesDir() string
}

View File

@ -51,7 +51,6 @@ type applyFlags struct {
etcdUpgrade bool
renewCerts bool
imagePullTimeout time.Duration
kustomizeDir string
patchesDir string
}
@ -89,7 +88,6 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
cmd.Flags().DurationVar(&flags.imagePullTimeout, "image-pull-timeout", flags.imagePullTimeout, "The maximum amount of time to wait for the control plane pods to be downloaded.")
// TODO: The flag was deprecated in 1.19; remove the flag following a GA deprecation policy of 12 months or 2 releases (whichever is longer)
cmd.Flags().MarkDeprecated("image-pull-timeout", "This flag is deprecated and will be removed in a future version.")
options.AddKustomizePodsFlag(cmd.Flags(), &flags.kustomizeDir)
options.AddPatchesFlag(cmd.Flags(), &flags.patchesDir)
return cmd
@ -217,8 +215,8 @@ func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, w
fmt.Printf("[upgrade/apply] Upgrading your Static Pod-hosted control plane to version %q...\n", internalcfg.KubernetesVersion)
if flags.dryRun {
return upgrade.DryRunStaticPodUpgrade(flags.kustomizeDir, flags.patchesDir, internalcfg)
return upgrade.DryRunStaticPodUpgrade(flags.patchesDir, internalcfg)
}
return upgrade.PerformStaticPodUpgrade(client, waiter, internalcfg, flags.etcdUpgrade, flags.renewCerts, flags.kustomizeDir, flags.patchesDir)
return upgrade.PerformStaticPodUpgrade(client, waiter, internalcfg, flags.etcdUpgrade, flags.renewCerts, flags.patchesDir)
}

View File

@ -42,7 +42,6 @@ type nodeOptions struct {
etcdUpgrade bool
renewCerts bool
dryRun bool
kustomizeDir string
patchesDir string
ignorePreflightErrors []string
}
@ -59,7 +58,6 @@ type nodeData struct {
cfg *kubeadmapi.InitConfiguration
isControlPlaneNode bool
client clientset.Interface
kustomizeDir string
patchesDir string
ignorePreflightErrors sets.String
}
@ -81,7 +79,6 @@ func NewCmdNode() *cobra.Command {
// adds flags to the node command
// flags could be eventually inherited by the sub-commands automatically generated for phases
addUpgradeNodeFlags(cmd.Flags(), nodeOptions)
options.AddKustomizePodsFlag(cmd.Flags(), &nodeOptions.kustomizeDir)
options.AddPatchesFlag(cmd.Flags(), &nodeOptions.patchesDir)
// initialize the workflow runner with the list of phases
@ -159,7 +156,6 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions) (*node
cfg: cfg,
client: client,
isControlPlaneNode: isControlPlaneNode,
kustomizeDir: options.kustomizeDir,
patchesDir: options.patchesDir,
ignorePreflightErrors: ignorePreflightErrorsSet,
}, nil
@ -195,11 +191,6 @@ func (d *nodeData) Client() clientset.Interface {
return d.client
}
// KustomizeDir returns the folder where kustomize patches for static pod manifest are stored
func (d *nodeData) KustomizeDir() string {
return d.kustomizeDir
}
// PatchesDir returns the folder where patches for components are stored
func (d *nodeData) PatchesDir() string {
return d.patchesDir

View File

@ -38,9 +38,9 @@ import (
)
// CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane.
func CreateInitStaticPodManifestFiles(manifestDir, kustomizeDir, patchesDir string, cfg *kubeadmapi.InitConfiguration) error {
func CreateInitStaticPodManifestFiles(manifestDir, patchesDir string, cfg *kubeadmapi.InitConfiguration) error {
klog.V(1).Infoln("[control-plane] creating static Pod files")
return CreateStaticPodFiles(manifestDir, kustomizeDir, patchesDir, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler)
return CreateStaticPodFiles(manifestDir, patchesDir, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint, kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler)
}
// GetStaticPodSpecs returns all staticPodSpecs actualized to the context of the current configuration
@ -91,7 +91,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmap
}
// CreateStaticPodFiles creates all the requested static pod files.
func CreateStaticPodFiles(manifestDir, kustomizeDir, patchesDir string, cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.APIEndpoint, componentNames ...string) error {
func CreateStaticPodFiles(manifestDir, patchesDir string, cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.APIEndpoint, componentNames ...string) error {
// gets the StaticPodSpecs, actualized for the current ClusterConfiguration
klog.V(1).Infoln("[control-plane] getting StaticPodSpecs")
specs := GetStaticPodSpecs(cfg, endpoint)
@ -109,15 +109,6 @@ func CreateStaticPodFiles(manifestDir, kustomizeDir, patchesDir string, cfg *kub
klog.V(2).Infof("[control-plane] adding volume %q for component %q", v.Name, componentName)
}
// if kustomizeDir is defined, customize the static pod manifest
if kustomizeDir != "" {
kustomizedSpec, err := staticpodutil.KustomizeStaticPod(&spec, kustomizeDir)
if err != nil {
return errors.Wrapf(err, "failed to kustomize static pod manifest file for %q", componentName)
}
spec = *kustomizedSpec
}
// if patchesDir is defined, patch the static Pod manifest
if patchesDir != "" {
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)

View File

@ -125,7 +125,7 @@ func TestCreateStaticPodFilesAndWrappers(t *testing.T) {
// Execute createStaticPodFunction
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
err := CreateStaticPodFiles(manifestPath, "", "", cfg, &kubeadmapi.APIEndpoint{}, test.components...)
err := CreateStaticPodFiles(manifestPath, "", cfg, &kubeadmapi.APIEndpoint{}, test.components...)
if err != nil {
t.Errorf("Error executing createStaticPodFunction: %v", err)
return
@ -141,56 +141,6 @@ func TestCreateStaticPodFilesAndWrappers(t *testing.T) {
}
}
func TestCreateStaticPodFilesKustomize(t *testing.T) {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Creates a Cluster Configuration
cfg := &kubeadmapi.ClusterConfiguration{
KubernetesVersion: "v1.9.0",
}
kustomizePath := filepath.Join(tmpdir, "kustomize")
err := os.MkdirAll(kustomizePath, 0777)
if err != nil {
t.Fatalf("Couldn't create %s", kustomizePath)
}
patchString := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
annotations:
kustomize: patch for kube-apiserver
`)
err = ioutil.WriteFile(filepath.Join(kustomizePath, "patch.yaml"), []byte(patchString), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
// Execute createStaticPodFunction with kustomizations
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
err = CreateStaticPodFiles(manifestPath, kustomizePath, "", cfg, &kubeadmapi.APIEndpoint{}, kubeadmconstants.KubeAPIServer)
if err != nil {
t.Errorf("Error executing createStaticPodFunction: %v", err)
return
}
pod, err := staticpodutil.ReadStaticPodFromDisk(filepath.Join(manifestPath, fmt.Sprintf("%s.yaml", kubeadmconstants.KubeAPIServer)))
if err != nil {
t.Errorf("Error executing ReadStaticPodFromDisk: %v", err)
return
}
if _, ok := pod.ObjectMeta.Annotations["kustomize"]; !ok {
t.Error("Kustomize did not apply patches corresponding to the resource")
}
}
func TestCreateStaticPodFilesWithPatches(t *testing.T) {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
@ -220,7 +170,7 @@ func TestCreateStaticPodFilesWithPatches(t *testing.T) {
// Execute createStaticPodFunction with patches
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
err = CreateStaticPodFiles(manifestPath, "", patchesPath, cfg, &kubeadmapi.APIEndpoint{}, kubeadmconstants.KubeAPIServer)
err = CreateStaticPodFiles(manifestPath, patchesPath, cfg, &kubeadmapi.APIEndpoint{}, kubeadmconstants.KubeAPIServer)
if err != nil {
t.Errorf("Error executing createStaticPodFunction: %v", err)
return

View File

@ -50,22 +50,13 @@ const (
// CreateLocalEtcdStaticPodManifestFile will write local etcd static pod manifest file.
// This function is used by init - when the etcd cluster is empty - or by kubeadm
// upgrade - when the etcd cluster is already up and running (and the --initial-cluster flag have no impact)
func CreateLocalEtcdStaticPodManifestFile(manifestDir, kustomizeDir, patchesDir string, nodeName string, cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.APIEndpoint) error {
func CreateLocalEtcdStaticPodManifestFile(manifestDir, patchesDir string, nodeName string, cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.APIEndpoint) error {
if cfg.Etcd.External != nil {
return errors.New("etcd static pod manifest cannot be generated for cluster using external etcd")
}
// gets etcd StaticPodSpec
spec := GetEtcdPodSpec(cfg, endpoint, nodeName, []etcdutil.Member{})
// if kustomizeDir is defined, customize the static pod manifest
if kustomizeDir != "" {
kustomizedSpec, err := staticpodutil.KustomizeStaticPod(&spec, kustomizeDir)
if err != nil {
return errors.Wrapf(err, "failed to kustomize static pod manifest file for %q", kubeadmconstants.Etcd)
}
spec = *kustomizedSpec
}
// if patchesDir is defined, patch the static Pod manifest
if patchesDir != "" {
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)
@ -152,7 +143,7 @@ func RemoveStackedEtcdMemberFromCluster(client clientset.Interface, cfg *kubeadm
// CreateStackedEtcdStaticPodManifestFile will write local etcd static pod manifest file
// for an additional etcd member that is joining an existing local/stacked etcd cluster.
// Other members of the etcd cluster will be notified of the joining node in beforehand as well.
func CreateStackedEtcdStaticPodManifestFile(client clientset.Interface, manifestDir, kustomizeDir, patchesDir string, nodeName string, cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.APIEndpoint) error {
func CreateStackedEtcdStaticPodManifestFile(client clientset.Interface, manifestDir, patchesDir string, nodeName string, cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.APIEndpoint) error {
// creates an etcd client that connects to all the local/stacked etcd members
klog.V(1).Info("creating etcd client that connects to etcd pods")
etcdClient, err := etcdutil.NewFromCluster(client, cfg.CertificatesDir)
@ -196,15 +187,6 @@ func CreateStackedEtcdStaticPodManifestFile(client clientset.Interface, manifest
// gets etcd StaticPodSpec, actualized for the current InitConfiguration and the new list of etcd members
spec := GetEtcdPodSpec(cfg, endpoint, nodeName, initialCluster)
// if kustomizeDir is defined, customize the static pod manifest
if kustomizeDir != "" {
kustomizedSpec, err := staticpodutil.KustomizeStaticPod(&spec, kustomizeDir)
if err != nil {
return errors.Wrapf(err, "failed to kustomize static pod manifest file for %q", kubeadmconstants.Etcd)
}
spec = *kustomizedSpec
}
// if patchesDir is defined, patch the static Pod manifest
if patchesDir != "" {
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)

View File

@ -96,7 +96,7 @@ func TestCreateLocalEtcdStaticPodManifestFile(t *testing.T) {
for _, test := range tests {
// Execute createStaticPodFunction
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
err := CreateLocalEtcdStaticPodManifestFile(manifestPath, "", "", "", test.cfg, &kubeadmapi.APIEndpoint{})
err := CreateLocalEtcdStaticPodManifestFile(manifestPath, "", "", test.cfg, &kubeadmapi.APIEndpoint{})
if !test.expectedError {
if err != nil {
@ -111,61 +111,6 @@ func TestCreateLocalEtcdStaticPodManifestFile(t *testing.T) {
}
}
func TestCreateLocalEtcdStaticPodManifestFileKustomize(t *testing.T) {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Creates a Cluster Configuration
cfg := &kubeadmapi.ClusterConfiguration{
KubernetesVersion: "v1.7.0",
Etcd: kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{
DataDir: tmpdir + "/etcd",
},
},
}
kustomizePath := filepath.Join(tmpdir, "kustomize")
err := os.MkdirAll(kustomizePath, 0777)
if err != nil {
t.Fatalf("Couldn't create %s", kustomizePath)
}
patchString := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: etcd
namespace: kube-system
annotations:
kustomize: patch for etcd
`)
err = ioutil.WriteFile(filepath.Join(kustomizePath, "patch.yaml"), []byte(patchString), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
// Execute createStaticPodFunction with kustomizations
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
err = CreateLocalEtcdStaticPodManifestFile(manifestPath, kustomizePath, "", "", cfg, &kubeadmapi.APIEndpoint{})
if err != nil {
t.Errorf("Error executing createStaticPodFunction: %v", err)
return
}
pod, err := staticpodutil.ReadStaticPodFromDisk(filepath.Join(manifestPath, fmt.Sprintf("%s.yaml", kubeadmconstants.Etcd)))
if err != nil {
t.Errorf("Error executing ReadStaticPodFromDisk: %v", err)
return
}
if _, ok := pod.ObjectMeta.Annotations["kustomize"]; !ok {
t.Error("Kustomize did not apply patches corresponding to the resource")
}
}
func TestCreateLocalEtcdStaticPodManifestFileWithPatches(t *testing.T) {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
@ -199,7 +144,7 @@ func TestCreateLocalEtcdStaticPodManifestFileWithPatches(t *testing.T) {
}
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
err = CreateLocalEtcdStaticPodManifestFile(manifestPath, "", patchesPath, "", cfg, &kubeadmapi.APIEndpoint{})
err = CreateLocalEtcdStaticPodManifestFile(manifestPath, patchesPath, "", cfg, &kubeadmapi.APIEndpoint{})
if err != nil {
t.Errorf("Error executing createStaticPodFunction: %v", err)
return

View File

@ -53,8 +53,6 @@ type StaticPodPathManager interface {
MoveFile(oldPath, newPath string) error
// KubernetesDir is the directory Kubernetes owns for storing various configuration files
KubernetesDir() string
// KustomizeDir should point to the folder where kustomize patches for static pod manifest are stored
KustomizeDir() string
// PatchesDir should point to the folder where patches for components are stored
PatchesDir() string
// RealManifestPath gets the file path for the component in the "real" static pod manifest directory used by the kubelet
@ -78,7 +76,6 @@ type StaticPodPathManager interface {
// KubeStaticPodPathManager is a real implementation of StaticPodPathManager that is used when upgrading a static pod cluster
type KubeStaticPodPathManager struct {
kubernetesDir string
kustomizeDir string
patchesDir string
realManifestDir string
tempManifestDir string
@ -90,10 +87,9 @@ type KubeStaticPodPathManager struct {
}
// NewKubeStaticPodPathManager creates a new instance of KubeStaticPodPathManager
func NewKubeStaticPodPathManager(kubernetesDir, kustomizeDir, patchesDir, tempDir, backupDir, backupEtcdDir string, keepManifestDir, keepEtcdDir bool) StaticPodPathManager {
func NewKubeStaticPodPathManager(kubernetesDir, patchesDir, tempDir, backupDir, backupEtcdDir string, keepManifestDir, keepEtcdDir bool) StaticPodPathManager {
return &KubeStaticPodPathManager{
kubernetesDir: kubernetesDir,
kustomizeDir: kustomizeDir,
patchesDir: patchesDir,
realManifestDir: filepath.Join(kubernetesDir, constants.ManifestsSubDirName),
tempManifestDir: tempDir,
@ -105,7 +101,7 @@ func NewKubeStaticPodPathManager(kubernetesDir, kustomizeDir, patchesDir, tempDi
}
// NewKubeStaticPodPathManagerUsingTempDirs creates a new instance of KubeStaticPodPathManager with temporary directories backing it
func NewKubeStaticPodPathManagerUsingTempDirs(kubernetesDir, kustomizeDir, patchesDir string, saveManifestsDir, saveEtcdDir bool) (StaticPodPathManager, error) {
func NewKubeStaticPodPathManagerUsingTempDirs(kubernetesDir, patchesDir string, saveManifestsDir, saveEtcdDir bool) (StaticPodPathManager, error) {
upgradedManifestsDir, err := constants.CreateTempDirForKubeadm(kubernetesDir, "kubeadm-upgraded-manifests")
if err != nil {
@ -120,7 +116,7 @@ func NewKubeStaticPodPathManagerUsingTempDirs(kubernetesDir, kustomizeDir, patch
return nil, err
}
return NewKubeStaticPodPathManager(kubernetesDir, kustomizeDir, patchesDir, upgradedManifestsDir, backupManifestsDir, backupEtcdDir, saveManifestsDir, saveEtcdDir), nil
return NewKubeStaticPodPathManager(kubernetesDir, patchesDir, upgradedManifestsDir, backupManifestsDir, backupEtcdDir, saveManifestsDir, saveEtcdDir), nil
}
// MoveFile should move a file from oldPath to newPath
@ -133,11 +129,6 @@ func (spm *KubeStaticPodPathManager) KubernetesDir() string {
return spm.kubernetesDir
}
// KustomizeDir should point to the folder where kustomize patches for static pod manifest are stored
func (spm *KubeStaticPodPathManager) KustomizeDir() string {
return spm.kustomizeDir
}
// PatchesDir should point to the folder where patches for components are stored
func (spm *KubeStaticPodPathManager) PatchesDir() string {
return spm.patchesDir
@ -332,7 +323,7 @@ func performEtcdStaticPodUpgrade(certsRenewMgr *renewal.Manager, client clientse
// Write the updated etcd static Pod manifest into the temporary directory, at this point no etcd change
// has occurred in any aspects.
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(pathMgr.TempManifestDir(), pathMgr.KustomizeDir(), pathMgr.PatchesDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(pathMgr.TempManifestDir(), pathMgr.PatchesDir(), cfg.NodeRegistration.Name, &cfg.ClusterConfiguration, &cfg.LocalAPIEndpoint); err != nil {
return true, errors.Wrap(err, "error creating local etcd static pod manifest file")
}
@ -478,7 +469,7 @@ func StaticPodControlPlane(client clientset.Interface, waiter apiclient.Waiter,
// Write the updated static Pod manifests into the temporary directory
fmt.Printf("[upgrade/staticpods] Writing new Static Pod manifests to %q\n", pathMgr.TempManifestDir())
err = controlplane.CreateInitStaticPodManifestFiles(pathMgr.TempManifestDir(), pathMgr.KustomizeDir(), pathMgr.PatchesDir(), cfg)
err = controlplane.CreateInitStaticPodManifestFiles(pathMgr.TempManifestDir(), pathMgr.PatchesDir(), cfg)
if err != nil {
return errors.Wrap(err, "error creating init static pod manifest files")
}
@ -605,14 +596,14 @@ func renewCertsByComponent(cfg *kubeadmapi.InitConfiguration, component string,
}
// GetPathManagerForUpgrade returns a path manager properly configured for the given InitConfiguration.
func GetPathManagerForUpgrade(kubernetesDir, kustomizeDir, patchesDir string, internalcfg *kubeadmapi.InitConfiguration, etcdUpgrade bool) (StaticPodPathManager, error) {
func GetPathManagerForUpgrade(kubernetesDir, patchesDir string, internalcfg *kubeadmapi.InitConfiguration, etcdUpgrade bool) (StaticPodPathManager, error) {
isExternalEtcd := internalcfg.Etcd.External != nil
return NewKubeStaticPodPathManagerUsingTempDirs(kubernetesDir, kustomizeDir, patchesDir, true, etcdUpgrade && !isExternalEtcd)
return NewKubeStaticPodPathManagerUsingTempDirs(kubernetesDir, patchesDir, true, etcdUpgrade && !isExternalEtcd)
}
// PerformStaticPodUpgrade performs the upgrade of the control plane components for a static pod hosted cluster
func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.InitConfiguration, etcdUpgrade, renewCerts bool, kustomizeDir, patchesDir string) error {
pathManager, err := GetPathManagerForUpgrade(constants.KubernetesDir, kustomizeDir, patchesDir, internalcfg, etcdUpgrade)
func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.InitConfiguration, etcdUpgrade, renewCerts bool, patchesDir string) error {
pathManager, err := GetPathManagerForUpgrade(constants.KubernetesDir, patchesDir, internalcfg, etcdUpgrade)
if err != nil {
return err
}
@ -622,14 +613,14 @@ func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter
}
// DryRunStaticPodUpgrade fakes an upgrade of the control plane
func DryRunStaticPodUpgrade(kustomizeDir, patchesDir string, internalcfg *kubeadmapi.InitConfiguration) error {
func DryRunStaticPodUpgrade(patchesDir string, internalcfg *kubeadmapi.InitConfiguration) error {
dryRunManifestDir, err := constants.CreateTempDirForKubeadm("", "kubeadm-upgrade-dryrun")
if err != nil {
return err
}
defer os.RemoveAll(dryRunManifestDir)
if err := controlplane.CreateInitStaticPodManifestFiles(dryRunManifestDir, kustomizeDir, patchesDir, internalcfg); err != nil {
if err := controlplane.CreateInitStaticPodManifestFiles(dryRunManifestDir, patchesDir, internalcfg); err != nil {
return err
}

View File

@ -143,7 +143,6 @@ func (w *fakeWaiter) WaitForKubeletAndFunc(f func() error) error {
type fakeStaticPodPathManager struct {
kubernetesDir string
kustomizeDir string
patchesDir string
realManifestDir string
tempManifestDir string
@ -196,10 +195,6 @@ func (spm *fakeStaticPodPathManager) KubernetesDir() string {
return spm.kubernetesDir
}
func (spm *fakeStaticPodPathManager) KustomizeDir() string {
return spm.kustomizeDir
}
func (spm *fakeStaticPodPathManager) PatchesDir() string {
return spm.patchesDir
}
@ -495,11 +490,11 @@ func TestStaticPodControlPlane(t *testing.T) {
}
// Initialize the directory with v1.7 manifests; should then be upgraded to v1.8 using the method
err = controlplanephase.CreateInitStaticPodManifestFiles(pathMgr.RealManifestDir(), pathMgr.KustomizeDir(), pathMgr.PatchesDir(), oldcfg)
err = controlplanephase.CreateInitStaticPodManifestFiles(pathMgr.RealManifestDir(), pathMgr.PatchesDir(), oldcfg)
if err != nil {
t.Fatalf("couldn't run CreateInitStaticPodManifestFiles: %v", err)
}
err = etcdphase.CreateLocalEtcdStaticPodManifestFile(pathMgr.RealManifestDir(), pathMgr.KustomizeDir(), pathMgr.PatchesDir(), oldcfg.NodeRegistration.Name, &oldcfg.ClusterConfiguration, &oldcfg.LocalAPIEndpoint)
err = etcdphase.CreateLocalEtcdStaticPodManifestFile(pathMgr.RealManifestDir(), pathMgr.PatchesDir(), oldcfg.NodeRegistration.Name, &oldcfg.ClusterConfiguration, &oldcfg.LocalAPIEndpoint)
if err != nil {
t.Fatalf("couldn't run CreateLocalEtcdStaticPodManifestFile: %v", err)
}
@ -635,7 +630,7 @@ func TestCleanupDirs(t *testing.T) {
backupEtcdDir, cleanup := getTempDir(t, "backupEtcdDir")
defer cleanup()
mgr := NewKubeStaticPodPathManager(realKubernetesDir, "", "", tempManifestDir, backupManifestDir, backupEtcdDir, test.keepManifest, test.keepEtcd)
mgr := NewKubeStaticPodPathManager(realKubernetesDir, "", tempManifestDir, backupManifestDir, backupEtcdDir, test.keepManifest, test.keepEtcd)
err := mgr.CleanupDirs()
if err != nil {
t.Errorf("unexpected error cleaning up: %v", err)
@ -953,7 +948,7 @@ func TestGetPathManagerForUpgrade(t *testing.T) {
os.RemoveAll(tmpdir)
}()
pathmgr, err := GetPathManagerForUpgrade(tmpdir, "", "", test.cfg, test.etcdUpgrade)
pathmgr, err := GetPathManagerForUpgrade(tmpdir, "", test.cfg, test.etcdUpgrade)
if err != nil {
t.Fatalf("unexpected error creating path manager: %v", err)
}

View File

@ -86,7 +86,6 @@ filegroup(
"//cmd/kubeadm/app/util/image:all-srcs",
"//cmd/kubeadm/app/util/initsystem:all-srcs",
"//cmd/kubeadm/app/util/kubeconfig:all-srcs",
"//cmd/kubeadm/app/util/kustomize:all-srcs",
"//cmd/kubeadm/app/util/output:all-srcs",
"//cmd/kubeadm/app/util/patches:all-srcs",
"//cmd/kubeadm/app/util/pkiutil:all-srcs",

View File

@ -1,54 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"json6902.go",
"kustomize.go",
"strategicmerge.go",
],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/kustomize",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize: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/loader:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
"//vendor/sigs.k8s.io/yaml: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"],
)
go_test(
name = "go_default_test",
srcs = [
"kustomize_test.go",
"strategicmerge_test.go",
],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/github.com/lithammer/dedent:go_default_library",
],
)

View File

@ -1,64 +0,0 @@
/*
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 kustomize contains helpers for working with embedded kustomize commands
package kustomize
import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/patch"
)
// json6902 represents a json6902 patch
type json6902 struct {
// Target refers to a Kubernetes object that the json patch will be applied to
*patch.Target
// Patch contain the json patch as a string
Patch string
}
// json6902Slice is a slice of json6902 patches.
type json6902Slice []*json6902
// newJSON6902FromFile returns a json6902 patch from a file
func newJSON6902FromFile(f patch.Json6902, ldr ifc.Loader, file string) (*json6902, error) {
patch, err := ldr.Load(file)
if err != nil {
return nil, err
}
return &json6902{
Target: f.Target,
Patch: string(patch),
}, nil
}
// filterByResource returns all the json6902 patches in the json6902Slice corresponding to a given resource
func (s *json6902Slice) filterByResource(r *unstructured.Unstructured) json6902Slice {
var result json6902Slice
for _, p := range *s {
if p.Group == r.GroupVersionKind().Group &&
p.Version == r.GroupVersionKind().Version &&
p.Kind == r.GroupVersionKind().Kind &&
p.Namespace == r.GetNamespace() &&
p.Name == r.GetName() {
result = append(result, p)
}
}
return result
}

View File

@ -1,251 +0,0 @@
/*
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 kustomize contains helpers for working with embedded kustomize commands
package kustomize
import (
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"runtime"
"sync"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
yamlutil "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/cli-runtime/pkg/kustomize"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/patch"
"sigs.k8s.io/kustomize/pkg/types"
"sigs.k8s.io/yaml"
)
// Manager define a manager that allow access to kustomize capabilities
type Manager struct {
kustomizeDir string
kustomizationFile *types.Kustomization
strategicMergePatches strategicMergeSlice
json6902Patches json6902Slice
}
var (
lock = &sync.Mutex{}
instances = map[string]*Manager{}
)
// GetManager return the KustomizeManager singleton instance
// NB. this is done at singleton instance level because kubeadm has a unique pool
// of patches that are applied to different content, at different time
func GetManager(kustomizeDir string) (*Manager, error) {
lock.Lock()
defer lock.Unlock()
// if the instance does not exists, create it
if _, ok := instances[kustomizeDir]; !ok {
km := &Manager{
kustomizeDir: kustomizeDir,
}
// Create a loader that mimics the behavior of kubectl kustomize, including support for reading from
// a local folder or git repository like git@github.com:someOrg/someRepo.git or https://github.com/someOrg/someRepo?ref=someHash
// in order to do so you must use ldr.Root() instead of km.kustomizeDir and ldr.Load instead of other ways to read files
fSys := fs.MakeRealFS()
ldr, err := loader.NewLoader(km.kustomizeDir, fSys)
if err != nil {
return nil, err
}
defer ldr.Cleanup()
// read the Kustomization file and all the patches it is
// referencing (either stategicMerge or json6902 patches)
if err := km.loadFromKustomizationFile(ldr); err != nil {
return nil, err
}
// if a Kustomization file was not found, kubeadm creates
// one using all the patches in the folder; however in this
// case only stategicMerge patches are supported
if km.kustomizationFile == nil {
km.kustomizationFile = &types.Kustomization{}
if err := km.loadFromFolder(ldr); err != nil {
return nil, err
}
}
instances[kustomizeDir] = km
}
return instances[kustomizeDir], nil
}
// loadFromKustomizationFile reads a Kustomization file and all the patches it is
// referencing (either stategicMerge or json6902 patches)
func (km *Manager) loadFromKustomizationFile(ldr ifc.Loader) error {
// Kustomize support different KustomizationFileNames, so we try to read all
var content []byte
match := 0
for _, kf := range constants.KustomizationFileNames {
c, err := ldr.Load(kf)
if err == nil {
match++
content = c
}
}
// if no kustomization file is found return
if match == 0 {
return nil
}
// if more that one kustomization file is found, return error
if match > 1 {
return errors.Errorf("Found multiple kustomization files under: %s\n", ldr.Root())
}
// Decode the kustomization file
decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader(content), 1024)
var k = &types.Kustomization{}
if err := decoder.Decode(k); err != nil {
return errors.Wrap(err, "Error decoding kustomization file")
}
km.kustomizationFile = k
// gets all the strategic merge patches
for _, f := range km.kustomizationFile.PatchesStrategicMerge {
smp, err := newStrategicMergeSliceFromFile(ldr, string(f))
if err != nil {
return err
}
km.strategicMergePatches = append(km.strategicMergePatches, smp...)
}
// gets all the json6902 patches
for _, f := range km.kustomizationFile.PatchesJson6902 {
jp, err := newJSON6902FromFile(f, ldr, f.Path)
if err != nil {
return err
}
km.json6902Patches = append(km.json6902Patches, jp)
}
return nil
}
// loadFromFolder returns all the stategicMerge patches in a folder
func (km *Manager) loadFromFolder(ldr ifc.Loader) error {
files, err := ioutil.ReadDir(ldr.Root())
if err != nil {
return err
}
for _, fileInfo := range files {
if fileInfo.IsDir() {
continue
}
smp, err := newStrategicMergeSliceFromFile(ldr, fileInfo.Name())
if err != nil {
return err
}
km.strategicMergePatches = append(km.strategicMergePatches, smp...)
}
return nil
}
// Kustomize apply a set of patches to a resource.
// Portions of the kustomize logic in this function are taken from the kubernetes-sigs/kind project
func (km *Manager) Kustomize(data []byte) ([]byte, error) {
// parse the resource to kustomize
decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader(data), 1024)
var resource *unstructured.Unstructured
if err := decoder.Decode(&resource); err != nil {
return nil, err
}
// get patches corresponding to this resource
strategicMerge := km.strategicMergePatches.filterByResource(resource)
json6902 := km.json6902Patches.filterByResource(resource)
// if there are no patches, for the target resources, exit
patchesCnt := len(strategicMerge) + len(json6902)
if patchesCnt == 0 {
return data, nil
}
fmt.Printf("[kustomize] Applying %d patches to %s Resource=%s/%s\n", patchesCnt, resource.GroupVersionKind(), resource.GetNamespace(), resource.GetName())
// create an in memory fs to use for the kustomization
memFS := fs.MakeFakeFS()
fakeDir := "/"
// for Windows we need this to be a drive because kustomize uses filepath.Abs()
// which will add a drive letter if there is none. which drive letter is
// unimportant as the path is on the fake filesystem anyhow
if runtime.GOOS == "windows" {
fakeDir = `C:\`
}
// writes the resource to a file in the temp file system
b, err := yaml.Marshal(resource)
if err != nil {
return nil, err
}
name := "resource.yaml"
memFS.WriteFile(filepath.Join(fakeDir, name), b)
km.kustomizationFile.Resources = []string{name}
// writes strategic merge patches to files in the temp file system
km.kustomizationFile.PatchesStrategicMerge = []patch.StrategicMerge{}
for i, p := range strategicMerge {
b, err := yaml.Marshal(p)
if err != nil {
return nil, err
}
name := fmt.Sprintf("patch-%d.yaml", i)
memFS.WriteFile(filepath.Join(fakeDir, name), b)
km.kustomizationFile.PatchesStrategicMerge = append(km.kustomizationFile.PatchesStrategicMerge, patch.StrategicMerge(name))
}
// writes json6902 patches to files in the temp file system
km.kustomizationFile.PatchesJson6902 = []patch.Json6902{}
for i, p := range json6902 {
name := fmt.Sprintf("patchjson-%d.yaml", i)
memFS.WriteFile(filepath.Join(fakeDir, name), []byte(p.Patch))
km.kustomizationFile.PatchesJson6902 = append(km.kustomizationFile.PatchesJson6902, patch.Json6902{Target: p.Target, Path: name})
}
// writes the kustomization file to the temp file system
kbytes, err := yaml.Marshal(km.kustomizationFile)
if err != nil {
return nil, err
}
memFS.WriteFile(filepath.Join(fakeDir, "kustomization.yaml"), kbytes)
// Finally customize the target resource
var out bytes.Buffer
if err := kustomize.RunKustomizeBuild(&out, memFS, fakeDir); err != nil {
return nil, err
}
return out.Bytes(), nil
}

View File

@ -1,203 +0,0 @@
/*
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 kustomize
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/lithammer/dedent"
)
func TestKustomizeWithoutKustomizationFile(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("Couldn't create tmpdir")
}
defer os.RemoveAll(tmpdir)
strategicMergePatch1 := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
annotations:
kustomize: patch for kube-apiserver
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-1.yaml"), []byte(strategicMergePatch1), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
strategicMergePatch2 := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-scheduler
annotations:
kustomize: patch for kube-scheduler
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-2.yaml"), []byte(strategicMergePatch2), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
km, err := GetManager(tmpdir)
if err != nil {
t.Fatalf("GetManager returned unexpected error: %v", err)
}
resource := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
`)
kustomized, err := km.Kustomize([]byte(resource))
if err != nil {
t.Fatalf("Kustomize returned unexpected error: %v", err)
}
if !strings.Contains(string(kustomized), "kustomize: patch for kube-apiserver") {
t.Error("Kustomize did not apply strategicMergePatch")
}
if strings.Contains(string(kustomized), "kustomize: patch for kube-scheduler") {
t.Error("Kustomize did apply patches not corresponding to the resource")
}
}
func TestKustomizeWithKustomizationFile(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("Couldn't create tmpdir")
}
defer os.RemoveAll(tmpdir)
kustomizationFile := dedent.Dedent(`
patchesJson6902:
- target:
version: v1
kind: Pod
name: kube-apiserver
path: patch-1.yaml
- target:
version: v1
kind: Pod
name: kube-scheduler
path: patch-2.yaml
patchesStrategicMerge:
- patch-3.yaml
- patch-4.yaml
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "kustomization.yaml"), []byte(kustomizationFile), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
jsonPatch1 := dedent.Dedent(`
- op: add
path: "/metadata/labels"
value:
kustomize1: patch for kube-apiserver
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-1.yaml"), []byte(jsonPatch1), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
jsonPatch2 := dedent.Dedent(`
- op: add
path: "/metadata/labels"
value:
kustomize1: patch for kube-scheduler
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-2.yaml"), []byte(jsonPatch2), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
strategicMergePatch1 := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
annotations:
kustomize2: patch for kube-apiserver
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-3.yaml"), []byte(strategicMergePatch1), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
strategicMergePatch2 := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-scheduler
annotations:
kustomize2: patch for kube-scheduler
`)
err = ioutil.WriteFile(filepath.Join(tmpdir, "patch-4.yaml"), []byte(strategicMergePatch2), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
km, err := GetManager(tmpdir)
if err != nil {
t.Fatalf("GetManager returned unexpected error: %v", err)
}
resource := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
`)
kustomized, err := km.Kustomize([]byte(resource))
if err != nil {
t.Fatalf("Kustomize returned unexpected error: %v", err)
}
if !strings.Contains(string(kustomized), "kustomize1: patch for kube-apiserver") {
t.Error("Kustomize did not apply json patches corresponding to the resource")
}
if strings.Contains(string(kustomized), "kustomize1: patch for kube-scheduler") {
t.Error("Kustomize did apply json patches not corresponding to the resource")
}
if !strings.Contains(string(kustomized), "kustomize2: patch for kube-apiserver") {
t.Error("Kustomize did not apply strategic merge patches corresponding to the resource")
}
if strings.Contains(string(kustomized), "kustomize2: patch for kube-scheduler") {
t.Error("Kustomize did apply strategic merge patches not corresponding to the resource")
}
}

View File

@ -1,140 +0,0 @@
/*
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 kustomize
import (
"bytes"
"encoding/json"
"io"
"strings"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/kustomize/pkg/ifc"
)
// strategicMergeSlice is a slice of strategic merge patches.
// Unstructured objects are used to represent strategic merge patches of any group/version/kind.
type strategicMergeSlice []*unstructured.Unstructured
// newStrategicMergeSliceFromFile returns a slice of strategic merge patches from a file
func newStrategicMergeSliceFromFile(loader ifc.Loader, path string) (strategicMergeSlice, error) {
content, err := loader.Load(path)
if err != nil {
return nil, errors.Wrapf(err, "load from path %q failed", path)
}
res, err := newStrategicMergeSliceFromBytes(content)
if err != nil {
return nil, errors.Wrapf(err, "convert %q to Unstructured failed", path)
}
return res, nil
}
// newStrategicMergeSliceFromBytes returns a strategic merge patches contained in a []byte.
// This functions handles all the nuances of Kubernetes yaml (e.g. many yaml
// documents in one file, List of objects)
func newStrategicMergeSliceFromBytes(in []byte) (strategicMergeSlice, error) {
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
var result strategicMergeSlice
var err error
// Parse all the yaml documents in the file
for err == nil || isEmptyYamlError(err) {
var u unstructured.Unstructured
err = decoder.Decode(&u)
// if the yaml document is a valid unstructured object
if err == nil {
// it the unstructured object is empty, move to the next
if len(u.Object) == 0 {
continue
}
// validate the object has kind, metadata.name as required by Kustomize
if err := validate(u); err != nil {
return nil, err
}
// if the document is a list of objects
if strings.HasSuffix(u.GetKind(), "List") {
// for each item in the list of objects
if err := u.EachListItem(func(item runtime.Object) error {
// Marshal the object
itemJSON, err := json.Marshal(item)
if err != nil {
return err
}
// Get the strategicMergeSlice for the item
itemU, err := newStrategicMergeSliceFromBytes(itemJSON)
if err != nil {
return err
}
// append the strategicMergeSlice for the item to the strategicMergeSlice
result = append(result, itemU...)
return nil
}); err != nil {
return nil, err
}
continue
}
// append the object to the stategicMergeSlice
result = append(result, &u)
}
}
if err != io.EOF {
return nil, err
}
return result, nil
}
// filterByResource returns all the strategic merge patches in the strategicMergeSlice corresponding to a given resource
func (s *strategicMergeSlice) filterByResource(r *unstructured.Unstructured) strategicMergeSlice {
var result strategicMergeSlice
for _, p := range *s {
if p.GroupVersionKind() == r.GroupVersionKind() &&
p.GetNamespace() == r.GetNamespace() &&
p.GetName() == r.GetName() {
result = append(result, p)
}
}
return result
}
// validate validates that u has kind and name
// except for kind `List`, which doesn't require a name
func validate(u unstructured.Unstructured) error {
kind := u.GetKind()
if kind == "" {
return errors.New("missing kind in object")
} else if strings.HasSuffix(kind, "List") {
return nil
}
if u.GetName() == "" {
return errors.New("missing metadata.name in object")
}
return nil
}
func isEmptyYamlError(err error) bool {
return strings.Contains(err.Error(), "is missing in 'null'")
}

View File

@ -1,228 +0,0 @@
/*
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 kustomize
import (
"testing"
"github.com/lithammer/dedent"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestNewStategicMergeSliceFromBytes(t *testing.T) {
var useCases = []struct {
name string
in string
expectedPatches int
expectedError bool
}{
{
name: "empty",
in: "",
expectedPatches: 0,
},
{
name: "single patch",
in: dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
`),
expectedPatches: 1,
},
{
name: "two patches as separated yaml documents",
in: dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
---
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
`),
expectedPatches: 2,
},
{
name: "two patches as a k8s list",
in: dedent.Dedent(`
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
- apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
`),
expectedPatches: 2,
},
{
name: "nested k8s lists",
in: dedent.Dedent(`
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
- apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
`),
expectedPatches: 2,
},
{
name: "invalid yaml",
in: "$$$",
expectedError: true,
},
{
name: "invalid patch (missing kind)",
in: dedent.Dedent(`
apiVersion: v1
#kind: Pod
metadata:
name: kube-apiserver
`),
expectedError: true,
},
{
name: "invalid patch (missing name)",
in: dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
#name: kube-apiserver
`),
expectedError: true,
},
}
for _, rt := range useCases {
t.Run(rt.name, func(t *testing.T) {
r, err := newStrategicMergeSliceFromBytes([]byte(rt.in))
if err != nil {
if !rt.expectedError {
t.Errorf("newStrategicMergeSliceFromBytes returned unexpected error: %v", err)
}
return
}
if err == nil && rt.expectedError {
t.Error("newStrategicMergeSliceFromBytes does not returned expected error")
}
if len(r) != rt.expectedPatches {
t.Errorf("Expected %d strategic merge patches in the slice, actual %d", rt.expectedPatches, len(r))
}
})
}
}
func TestFilterResource(t *testing.T) {
in := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
---
apiVersion: v1
kind: Pod
metadata:
name: kube-scheduler
namespace: kube-system
---
apiVersion: v1
kind: Pod
metadata:
name: kube-scheduler
namespace: kube-system
`)
u, err := newStrategicMergeSliceFromBytes([]byte(in))
if err != nil {
t.Fatalf("newStategicMergeSliceFromBytes returned unexpected error: %v", err)
}
var useCases = []struct {
name string
rgvk schema.GroupVersionKind
rnamespace string
rname string
expectedPatches int
}{
{
name: "match 1",
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
rnamespace: "kube-system",
rname: "kube-apiserver",
expectedPatches: 1,
},
{
name: "match 2",
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
rnamespace: "kube-system",
rname: "kube-scheduler",
expectedPatches: 2,
},
{
name: "match 0 (wrong gvk)",
rgvk: schema.GroupVersionKind{Group: "something", Version: "v1", Kind: "Pod"},
rnamespace: "kube-system",
rname: "kube-scheduler",
expectedPatches: 0,
},
{
name: "match 0 (wrong namespace)",
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
rnamespace: "kube-something",
rname: "kube-scheduler",
expectedPatches: 0,
},
{
name: "match 0 (wrong namr)",
rgvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
rnamespace: "kube-system",
rname: "kube-something",
expectedPatches: 0,
},
}
for _, rt := range useCases {
t.Run(rt.name, func(t *testing.T) {
resource := &unstructured.Unstructured{}
resource.SetGroupVersionKind(rt.rgvk)
resource.SetNamespace(rt.rnamespace)
resource.SetName(rt.rname)
r := u.filterByResource(resource)
if len(r) != rt.expectedPatches {
t.Errorf("Expected %d strategic merge patches in the slice, actual %d", rt.expectedPatches, len(r))
}
})
}
}

View File

@ -16,7 +16,6 @@ go_test(
"//cmd/kubeadm/test:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/github.com/lithammer/dedent:go_default_library",
],
)
@ -28,7 +27,6 @@ go_library(
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util/kustomize:go_default_library",
"//cmd/kubeadm/app/util/patches:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",

View File

@ -37,7 +37,6 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/cmd/kubeadm/app/util/kustomize"
"k8s.io/kubernetes/cmd/kubeadm/app/util/patches"
)
@ -150,38 +149,6 @@ func GetExtraParameters(overrides map[string]string, defaults map[string]string)
return command
}
// KustomizeStaticPod applies patches defined in kustomizeDir to a static Pod manifest
func KustomizeStaticPod(pod *v1.Pod, kustomizeDir string) (*v1.Pod, error) {
// marshal the pod manifest into yaml
serialized, err := kubeadmutil.MarshalToYaml(pod, v1.SchemeGroupVersion)
if err != nil {
return pod, errors.Wrapf(err, "failed to marshal manifest to YAML")
}
km, err := kustomize.GetManager(kustomizeDir)
if err != nil {
return pod, errors.Wrapf(err, "failed to GetPatches from %q", kustomizeDir)
}
kustomized, err := km.Kustomize(serialized)
if err != nil {
return pod, errors.Wrap(err, "failed to kustomize static Pod manifest")
}
// unmarshal kustomized yaml back into a pod manifest
obj, err := kubeadmutil.UnmarshalFromYaml(kustomized, v1.SchemeGroupVersion)
if err != nil {
return pod, errors.Wrap(err, "failed to unmarshal kustomize manifest from YAML")
}
pod2, ok := obj.(*v1.Pod)
if !ok {
return pod, errors.Wrap(err, "kustomized manifest is not a valid Pod object")
}
return pod2, nil
}
// PatchStaticPod applies patches stored in patchesDir to a static Pod.
func PatchStaticPod(pod *v1.Pod, patchesDir string, output io.Writer) (*v1.Pod, error) {
// Marshal the Pod manifest into YAML.

View File

@ -25,8 +25,6 @@ import (
"strconv"
"testing"
"github.com/lithammer/dedent"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
@ -756,47 +754,6 @@ func TestManifestFilesAreEqual(t *testing.T) {
}
}
func TestKustomizeStaticPod(t *testing.T) {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
patchString := dedent.Dedent(`
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
annotations:
kustomize: patch for kube-apiserver
`)
err := ioutil.WriteFile(filepath.Join(tmpdir, "patch.yaml"), []byte(patchString), 0644)
if err != nil {
t.Fatalf("WriteFile returned unexpected error: %v", err)
}
pod := &v1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kube-apiserver",
Namespace: "kube-system",
},
}
kpod, err := KustomizeStaticPod(pod, tmpdir)
if err != nil {
t.Errorf("KustomizeStaticPod returned unexpected error: %v", err)
}
if _, ok := kpod.ObjectMeta.Annotations["kustomize"]; !ok {
t.Error("Kustomize did not apply patches corresponding to the resource")
}
}
func TestPatchStaticPod(t *testing.T) {
type file struct {
name string

1
go.mod
View File

@ -139,7 +139,6 @@ require (
k8s.io/sample-apiserver v0.0.0
k8s.io/system-validators v1.2.0
k8s.io/utils v0.0.0-20200729134348-d5654de09c73
sigs.k8s.io/kustomize v2.0.3+incompatible
sigs.k8s.io/yaml v1.2.0
)

1
vendor/modules.txt vendored
View File

@ -2497,7 +2497,6 @@ k8s.io/utils/trace
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client
# sigs.k8s.io/kustomize v2.0.3+incompatible => sigs.k8s.io/kustomize v2.0.3+incompatible
## explicit
# sigs.k8s.io/kustomize => sigs.k8s.io/kustomize v2.0.3+incompatible
sigs.k8s.io/kustomize/pkg/commands/build
sigs.k8s.io/kustomize/pkg/constants