mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
kubeadm: remove the --experimental-kustomize feature
The feature was replaced by --experimental-patches and deprecated in 1.19.
This commit is contained in:
parent
2aa1cd25f3
commit
8ece27bf4b
@ -462,7 +462,6 @@ func isAllowedFlag(flagName string) bool {
|
|||||||
kubeadmcmdoptions.NodeCRISocket,
|
kubeadmcmdoptions.NodeCRISocket,
|
||||||
kubeadmcmdoptions.KubeconfigDir,
|
kubeadmcmdoptions.KubeconfigDir,
|
||||||
kubeadmcmdoptions.UploadCerts,
|
kubeadmcmdoptions.UploadCerts,
|
||||||
kubeadmcmdoptions.Kustomize,
|
|
||||||
kubeadmcmdoptions.Patches,
|
kubeadmcmdoptions.Patches,
|
||||||
"print-join-command", "rootfs", "v")
|
"print-join-command", "rootfs", "v")
|
||||||
if knownFlags.Has(flagName) {
|
if knownFlags.Has(flagName) {
|
||||||
|
@ -102,7 +102,6 @@ type initOptions struct {
|
|||||||
externalClusterCfg *kubeadmapiv1beta2.ClusterConfiguration
|
externalClusterCfg *kubeadmapiv1beta2.ClusterConfiguration
|
||||||
uploadCerts bool
|
uploadCerts bool
|
||||||
skipCertificateKeyPrint bool
|
skipCertificateKeyPrint bool
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +124,6 @@ type initData struct {
|
|||||||
outputWriter io.Writer
|
outputWriter io.Writer
|
||||||
uploadCerts bool
|
uploadCerts bool
|
||||||
skipCertificateKeyPrint bool
|
skipCertificateKeyPrint bool
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +280,6 @@ func AddInitOtherFlags(flagSet *flag.FlagSet, initOptions *initOptions) {
|
|||||||
&initOptions.skipCertificateKeyPrint, options.SkipCertificateKeyPrint, initOptions.skipCertificateKeyPrint,
|
&initOptions.skipCertificateKeyPrint, options.SkipCertificateKeyPrint, initOptions.skipCertificateKeyPrint,
|
||||||
"Don't print the key used to encrypt the control-plane certificates.",
|
"Don't print the key used to encrypt the control-plane certificates.",
|
||||||
)
|
)
|
||||||
options.AddKustomizePodsFlag(flagSet, &initOptions.kustomizeDir)
|
|
||||||
options.AddPatchesFlag(flagSet, &initOptions.patchesDir)
|
options.AddPatchesFlag(flagSet, &initOptions.patchesDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +416,6 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io
|
|||||||
outputWriter: out,
|
outputWriter: out,
|
||||||
uploadCerts: options.uploadCerts,
|
uploadCerts: options.uploadCerts,
|
||||||
skipCertificateKeyPrint: options.skipCertificateKeyPrint,
|
skipCertificateKeyPrint: options.skipCertificateKeyPrint,
|
||||||
kustomizeDir: options.kustomizeDir,
|
|
||||||
patchesDir: options.patchesDir,
|
patchesDir: options.patchesDir,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -553,11 +549,6 @@ func (d *initData) Tokens() []string {
|
|||||||
return tokens
|
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
|
// PatchesDir returns the folder where patches for components are stored
|
||||||
func (d *initData) PatchesDir() string {
|
func (d *initData) PatchesDir() string {
|
||||||
return d.patchesDir
|
return d.patchesDir
|
||||||
|
@ -129,7 +129,6 @@ type joinOptions struct {
|
|||||||
ignorePreflightErrors []string
|
ignorePreflightErrors []string
|
||||||
externalcfg *kubeadmapiv1beta2.JoinConfiguration
|
externalcfg *kubeadmapiv1beta2.JoinConfiguration
|
||||||
joinControlPlane *kubeadmapiv1beta2.JoinControlPlane
|
joinControlPlane *kubeadmapiv1beta2.JoinControlPlane
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +144,6 @@ type joinData struct {
|
|||||||
clientSet *clientset.Clientset
|
clientSet *clientset.Clientset
|
||||||
ignorePreflightErrors sets.String
|
ignorePreflightErrors sets.String
|
||||||
outputWriter io.Writer
|
outputWriter io.Writer
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +285,6 @@ func addJoinOtherFlags(flagSet *flag.FlagSet, joinOptions *joinOptions) {
|
|||||||
&joinOptions.controlPlane, options.ControlPlane, joinOptions.controlPlane,
|
&joinOptions.controlPlane, options.ControlPlane, joinOptions.controlPlane,
|
||||||
"Create a new control plane instance on this node",
|
"Create a new control plane instance on this node",
|
||||||
)
|
)
|
||||||
options.AddKustomizePodsFlag(flagSet, &joinOptions.kustomizeDir)
|
|
||||||
options.AddPatchesFlag(flagSet, &joinOptions.patchesDir)
|
options.AddPatchesFlag(flagSet, &joinOptions.patchesDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +440,6 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri
|
|||||||
tlsBootstrapCfg: tlsBootstrapCfg,
|
tlsBootstrapCfg: tlsBootstrapCfg,
|
||||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||||
outputWriter: out,
|
outputWriter: out,
|
||||||
kustomizeDir: opt.kustomizeDir,
|
|
||||||
patchesDir: opt.patchesDir,
|
patchesDir: opt.patchesDir,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -510,11 +506,6 @@ func (j *joinData) OutputWriter() io.Writer {
|
|||||||
return j.outputWriter
|
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
|
// PatchesDir returns the folder where patches for components are stored
|
||||||
func (j *joinData) PatchesDir() string {
|
func (j *joinData) PatchesDir() string {
|
||||||
return j.patchesDir
|
return j.patchesDir
|
||||||
|
@ -143,9 +143,6 @@ const (
|
|||||||
// EtcdUpgrade flag instruct kubeadm to execute etcd upgrade during upgrades
|
// EtcdUpgrade flag instruct kubeadm to execute etcd upgrade during upgrades
|
||||||
EtcdUpgrade = "etcd-upgrade"
|
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 flag sets the folder where kubeadm component patches are stored
|
||||||
Patches = "experimental-patches"
|
Patches = "experimental-patches"
|
||||||
)
|
)
|
||||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package options
|
package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"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
|
// AddPatchesFlag adds the --patches flag to the given flagset
|
||||||
func AddPatchesFlag(fs *pflag.FlagSet, patchesDir *string) {
|
func AddPatchesFlag(fs *pflag.FlagSet, patchesDir *string) {
|
||||||
fs.StringVar(patchesDir, Patches, *patchesDir, `Path to a directory that contains files named `+
|
fs.StringVar(patchesDir, Patches, *patchesDir, `Path to a directory that contains files named `+
|
||||||
|
@ -100,7 +100,6 @@ func getControlPlanePhaseFlags(name string) []string {
|
|||||||
options.CertificatesDir,
|
options.CertificatesDir,
|
||||||
options.KubernetesVersion,
|
options.KubernetesVersion,
|
||||||
options.ImageRepository,
|
options.ImageRepository,
|
||||||
options.Kustomize,
|
|
||||||
}
|
}
|
||||||
if name == "all" || name == kubeadmconstants.KubeAPIServer {
|
if name == "all" || name == kubeadmconstants.KubeAPIServer {
|
||||||
flags = append(flags,
|
flags = append(flags,
|
||||||
@ -145,6 +144,6 @@ func runControlPlaneSubphase(component string) func(c workflow.RunData) error {
|
|||||||
cfg := data.Cfg()
|
cfg := data.Cfg()
|
||||||
|
|
||||||
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,5 @@ type InitData interface {
|
|||||||
OutputWriter() io.Writer
|
OutputWriter() io.Writer
|
||||||
Client() (clientset.Interface, error)
|
Client() (clientset.Interface, error)
|
||||||
Tokens() []string
|
Tokens() []string
|
||||||
KustomizeDir() string
|
|
||||||
PatchesDir() string
|
PatchesDir() string
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,4 @@ func (t *testInitData) ExternalCA() bool { return false }
|
|||||||
func (t *testInitData) OutputWriter() io.Writer { return nil }
|
func (t *testInitData) OutputWriter() io.Writer { return nil }
|
||||||
func (t *testInitData) Client() (clientset.Interface, error) { return nil, nil }
|
func (t *testInitData) Client() (clientset.Interface, error) { return nil, nil }
|
||||||
func (t *testInitData) Tokens() []string { return nil }
|
func (t *testInitData) Tokens() []string { return nil }
|
||||||
func (t *testInitData) KustomizeDir() string { return "" }
|
|
||||||
func (t *testInitData) PatchesDir() string { return "" }
|
func (t *testInitData) PatchesDir() string { return "" }
|
||||||
|
@ -69,7 +69,6 @@ func getEtcdPhaseFlags() []string {
|
|||||||
options.CertificatesDir,
|
options.CertificatesDir,
|
||||||
options.CfgPath,
|
options.CfgPath,
|
||||||
options.ImageRepository,
|
options.ImageRepository,
|
||||||
options.Kustomize,
|
|
||||||
options.Patches,
|
options.Patches,
|
||||||
}
|
}
|
||||||
return flags
|
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("[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())
|
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")
|
return errors.Wrap(err, "error creating local etcd static pod manifest file")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -44,7 +44,7 @@ func getControlPlaneJoinPhaseFlags(name string) []string {
|
|||||||
options.NodeName,
|
options.NodeName,
|
||||||
}
|
}
|
||||||
if name == "etcd" {
|
if name == "etcd" {
|
||||||
flags = append(flags, options.Kustomize, options.Patches)
|
flags = append(flags, options.Patches)
|
||||||
}
|
}
|
||||||
if name != "mark-control-plane" {
|
if name != "mark-control-plane" {
|
||||||
flags = append(flags, options.APIServerAdvertiseAddress)
|
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
|
// 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
|
// etcdctl member add informs the cluster about the new member and the new member successfully establishing a connection to the
|
||||||
// existing one."
|
// 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")
|
return errors.Wrap(err, "error creating local etcd static pod manifest file")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,6 @@ func getControlPlanePreparePhaseFlags(name string) []string {
|
|||||||
options.TLSBootstrapToken,
|
options.TLSBootstrapToken,
|
||||||
options.TokenStr,
|
options.TokenStr,
|
||||||
options.CertificateKey,
|
options.CertificateKey,
|
||||||
options.Kustomize,
|
|
||||||
options.Patches,
|
options.Patches,
|
||||||
}
|
}
|
||||||
case "download-certs":
|
case "download-certs":
|
||||||
@ -124,7 +123,6 @@ func getControlPlanePreparePhaseFlags(name string) []string {
|
|||||||
options.APIServerBindPort,
|
options.APIServerBindPort,
|
||||||
options.CfgPath,
|
options.CfgPath,
|
||||||
options.ControlPlane,
|
options.ControlPlane,
|
||||||
options.Kustomize,
|
|
||||||
options.Patches,
|
options.Patches,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -191,7 +189,6 @@ func runControlPlanePrepareControlPlaneSubphase(c workflow.RunData) error {
|
|||||||
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
|
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
|
||||||
err := controlplane.CreateStaticPodFiles(
|
err := controlplane.CreateStaticPodFiles(
|
||||||
kubeadmconstants.GetStaticPodDirectory(),
|
kubeadmconstants.GetStaticPodDirectory(),
|
||||||
data.KustomizeDir(),
|
|
||||||
data.PatchesDir(),
|
data.PatchesDir(),
|
||||||
&cfg.ClusterConfiguration,
|
&cfg.ClusterConfiguration,
|
||||||
&cfg.LocalAPIEndpoint,
|
&cfg.LocalAPIEndpoint,
|
||||||
|
@ -35,6 +35,5 @@ type JoinData interface {
|
|||||||
ClientSet() (*clientset.Clientset, error)
|
ClientSet() (*clientset.Clientset, error)
|
||||||
IgnorePreflightErrors() sets.String
|
IgnorePreflightErrors() sets.String
|
||||||
OutputWriter() io.Writer
|
OutputWriter() io.Writer
|
||||||
KustomizeDir() string
|
|
||||||
PatchesDir() string
|
PatchesDir() string
|
||||||
}
|
}
|
||||||
|
@ -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) ClientSet() (*clientset.Clientset, error) { return nil, nil }
|
||||||
func (j *testJoinData) IgnorePreflightErrors() sets.String { return nil }
|
func (j *testJoinData) IgnorePreflightErrors() sets.String { return nil }
|
||||||
func (j *testJoinData) OutputWriter() io.Writer { return nil }
|
func (j *testJoinData) OutputWriter() io.Writer { return nil }
|
||||||
func (j *testJoinData) KustomizeDir() string { return "" }
|
|
||||||
func (j *testJoinData) PatchesDir() string { return "" }
|
func (j *testJoinData) PatchesDir() string { return "" }
|
||||||
|
@ -39,7 +39,6 @@ func NewControlPlane() workflow.Phase {
|
|||||||
options.KubeconfigPath,
|
options.KubeconfigPath,
|
||||||
options.CertificateRenewal,
|
options.CertificateRenewal,
|
||||||
options.EtcdUpgrade,
|
options.EtcdUpgrade,
|
||||||
options.Kustomize,
|
|
||||||
options.Patches,
|
options.Patches,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -65,18 +64,17 @@ func runControlPlane() func(c workflow.RunData) error {
|
|||||||
dryRun := data.DryRun()
|
dryRun := data.DryRun()
|
||||||
etcdUpgrade := data.EtcdUpgrade()
|
etcdUpgrade := data.EtcdUpgrade()
|
||||||
renewCerts := data.RenewCerts()
|
renewCerts := data.RenewCerts()
|
||||||
kustomizeDir := data.KustomizeDir()
|
|
||||||
patchesDir := data.PatchesDir()
|
patchesDir := data.PatchesDir()
|
||||||
|
|
||||||
// Upgrade the control plane and etcd if installed on this node
|
// 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)
|
fmt.Printf("[upgrade] Upgrading your Static Pod-hosted control plane instance to version %q...\n", cfg.KubernetesVersion)
|
||||||
if dryRun {
|
if dryRun {
|
||||||
return upgrade.DryRunStaticPodUpgrade(kustomizeDir, patchesDir, cfg)
|
return upgrade.DryRunStaticPodUpgrade(patchesDir, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
waiter := apiclient.NewKubeWaiter(data.Client(), upgrade.UpgradeManifestTimeout, os.Stdout)
|
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")
|
return errors.Wrap(err, "couldn't complete the static pod upgrade")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,5 @@ type Data interface {
|
|||||||
IsControlPlaneNode() bool
|
IsControlPlaneNode() bool
|
||||||
Client() clientset.Interface
|
Client() clientset.Interface
|
||||||
IgnorePreflightErrors() sets.String
|
IgnorePreflightErrors() sets.String
|
||||||
KustomizeDir() string
|
|
||||||
PatchesDir() string
|
PatchesDir() string
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,6 @@ type applyFlags struct {
|
|||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
imagePullTimeout time.Duration
|
imagePullTimeout time.Duration
|
||||||
kustomizeDir string
|
|
||||||
patchesDir 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.")
|
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)
|
// 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.")
|
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)
|
options.AddPatchesFlag(cmd.Flags(), &flags.patchesDir)
|
||||||
|
|
||||||
return cmd
|
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)
|
fmt.Printf("[upgrade/apply] Upgrading your Static Pod-hosted control plane to version %q...\n", internalcfg.KubernetesVersion)
|
||||||
|
|
||||||
if flags.dryRun {
|
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)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,6 @@ type nodeOptions struct {
|
|||||||
etcdUpgrade bool
|
etcdUpgrade bool
|
||||||
renewCerts bool
|
renewCerts bool
|
||||||
dryRun bool
|
dryRun bool
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
ignorePreflightErrors []string
|
ignorePreflightErrors []string
|
||||||
}
|
}
|
||||||
@ -61,7 +60,6 @@ type nodeData struct {
|
|||||||
cfg *kubeadmapi.InitConfiguration
|
cfg *kubeadmapi.InitConfiguration
|
||||||
isControlPlaneNode bool
|
isControlPlaneNode bool
|
||||||
client clientset.Interface
|
client clientset.Interface
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
ignorePreflightErrors sets.String
|
ignorePreflightErrors sets.String
|
||||||
}
|
}
|
||||||
@ -83,7 +81,6 @@ func NewCmdNode() *cobra.Command {
|
|||||||
// adds flags to the node command
|
// adds flags to the node command
|
||||||
// flags could be eventually inherited by the sub-commands automatically generated for phases
|
// flags could be eventually inherited by the sub-commands automatically generated for phases
|
||||||
addUpgradeNodeFlags(cmd.Flags(), nodeOptions)
|
addUpgradeNodeFlags(cmd.Flags(), nodeOptions)
|
||||||
options.AddKustomizePodsFlag(cmd.Flags(), &nodeOptions.kustomizeDir)
|
|
||||||
options.AddPatchesFlag(cmd.Flags(), &nodeOptions.patchesDir)
|
options.AddPatchesFlag(cmd.Flags(), &nodeOptions.patchesDir)
|
||||||
|
|
||||||
// initialize the workflow runner with the list of phases
|
// initialize the workflow runner with the list of phases
|
||||||
@ -164,7 +161,6 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions) (*node
|
|||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
client: client,
|
client: client,
|
||||||
isControlPlaneNode: isControlPlaneNode,
|
isControlPlaneNode: isControlPlaneNode,
|
||||||
kustomizeDir: options.kustomizeDir,
|
|
||||||
patchesDir: options.patchesDir,
|
patchesDir: options.patchesDir,
|
||||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||||
}, nil
|
}, nil
|
||||||
@ -205,11 +201,6 @@ func (d *nodeData) Client() clientset.Interface {
|
|||||||
return d.client
|
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
|
// PatchesDir returns the folder where patches for components are stored
|
||||||
func (d *nodeData) PatchesDir() string {
|
func (d *nodeData) PatchesDir() string {
|
||||||
return d.patchesDir
|
return d.patchesDir
|
||||||
|
@ -38,9 +38,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane.
|
// 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")
|
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
|
// 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.
|
// 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
|
// gets the StaticPodSpecs, actualized for the current ClusterConfiguration
|
||||||
klog.V(1).Infoln("[control-plane] getting StaticPodSpecs")
|
klog.V(1).Infoln("[control-plane] getting StaticPodSpecs")
|
||||||
specs := GetStaticPodSpecs(cfg, endpoint)
|
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)
|
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 is defined, patch the static Pod manifest
|
||||||
if patchesDir != "" {
|
if patchesDir != "" {
|
||||||
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)
|
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)
|
||||||
|
@ -125,7 +125,7 @@ func TestCreateStaticPodFilesAndWrappers(t *testing.T) {
|
|||||||
|
|
||||||
// Execute createStaticPodFunction
|
// Execute createStaticPodFunction
|
||||||
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
|
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 {
|
if err != nil {
|
||||||
t.Errorf("Error executing createStaticPodFunction: %v", err)
|
t.Errorf("Error executing createStaticPodFunction: %v", err)
|
||||||
return
|
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) {
|
func TestCreateStaticPodFilesWithPatches(t *testing.T) {
|
||||||
// Create temp folder for the test case
|
// Create temp folder for the test case
|
||||||
tmpdir := testutil.SetupTempDir(t)
|
tmpdir := testutil.SetupTempDir(t)
|
||||||
@ -220,7 +170,7 @@ func TestCreateStaticPodFilesWithPatches(t *testing.T) {
|
|||||||
|
|
||||||
// Execute createStaticPodFunction with patches
|
// Execute createStaticPodFunction with patches
|
||||||
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
|
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 {
|
if err != nil {
|
||||||
t.Errorf("Error executing createStaticPodFunction: %v", err)
|
t.Errorf("Error executing createStaticPodFunction: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -50,22 +50,13 @@ const (
|
|||||||
// CreateLocalEtcdStaticPodManifestFile will write local etcd static pod manifest file.
|
// CreateLocalEtcdStaticPodManifestFile will write local etcd static pod manifest file.
|
||||||
// This function is used by init - when the etcd cluster is empty - or by kubeadm
|
// 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)
|
// 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 {
|
if cfg.Etcd.External != nil {
|
||||||
return errors.New("etcd static pod manifest cannot be generated for cluster using external etcd")
|
return errors.New("etcd static pod manifest cannot be generated for cluster using external etcd")
|
||||||
}
|
}
|
||||||
// gets etcd StaticPodSpec
|
// gets etcd StaticPodSpec
|
||||||
spec := GetEtcdPodSpec(cfg, endpoint, nodeName, []etcdutil.Member{})
|
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 is defined, patch the static Pod manifest
|
||||||
if patchesDir != "" {
|
if patchesDir != "" {
|
||||||
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)
|
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
|
// CreateStackedEtcdStaticPodManifestFile will write local etcd static pod manifest file
|
||||||
// for an additional etcd member that is joining an existing local/stacked etcd cluster.
|
// 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.
|
// 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
|
// 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")
|
klog.V(1).Info("creating etcd client that connects to etcd pods")
|
||||||
etcdClient, err := etcdutil.NewFromCluster(client, cfg.CertificatesDir)
|
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
|
// gets etcd StaticPodSpec, actualized for the current InitConfiguration and the new list of etcd members
|
||||||
spec := GetEtcdPodSpec(cfg, endpoint, nodeName, initialCluster)
|
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 is defined, patch the static Pod manifest
|
||||||
if patchesDir != "" {
|
if patchesDir != "" {
|
||||||
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)
|
patchedSpec, err := staticpodutil.PatchStaticPod(&spec, patchesDir, os.Stdout)
|
||||||
|
@ -96,7 +96,7 @@ func TestCreateLocalEtcdStaticPodManifestFile(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
// Execute createStaticPodFunction
|
// Execute createStaticPodFunction
|
||||||
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
|
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
|
||||||
err := CreateLocalEtcdStaticPodManifestFile(manifestPath, "", "", "", test.cfg, &kubeadmapi.APIEndpoint{})
|
err := CreateLocalEtcdStaticPodManifestFile(manifestPath, "", "", test.cfg, &kubeadmapi.APIEndpoint{})
|
||||||
|
|
||||||
if !test.expectedError {
|
if !test.expectedError {
|
||||||
if err != nil {
|
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) {
|
func TestCreateLocalEtcdStaticPodManifestFileWithPatches(t *testing.T) {
|
||||||
// Create temp folder for the test case
|
// Create temp folder for the test case
|
||||||
tmpdir := testutil.SetupTempDir(t)
|
tmpdir := testutil.SetupTempDir(t)
|
||||||
@ -199,7 +144,7 @@ func TestCreateLocalEtcdStaticPodManifestFileWithPatches(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
|
manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName)
|
||||||
err = CreateLocalEtcdStaticPodManifestFile(manifestPath, "", patchesPath, "", cfg, &kubeadmapi.APIEndpoint{})
|
err = CreateLocalEtcdStaticPodManifestFile(manifestPath, patchesPath, "", cfg, &kubeadmapi.APIEndpoint{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error executing createStaticPodFunction: %v", err)
|
t.Errorf("Error executing createStaticPodFunction: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -53,8 +53,6 @@ type StaticPodPathManager interface {
|
|||||||
MoveFile(oldPath, newPath string) error
|
MoveFile(oldPath, newPath string) error
|
||||||
// KubernetesDir is the directory Kubernetes owns for storing various configuration files
|
// KubernetesDir is the directory Kubernetes owns for storing various configuration files
|
||||||
KubernetesDir() string
|
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 should point to the folder where patches for components are stored
|
||||||
PatchesDir() string
|
PatchesDir() string
|
||||||
// RealManifestPath gets the file path for the component in the "real" static pod manifest directory used by the kubelet
|
// 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
|
// KubeStaticPodPathManager is a real implementation of StaticPodPathManager that is used when upgrading a static pod cluster
|
||||||
type KubeStaticPodPathManager struct {
|
type KubeStaticPodPathManager struct {
|
||||||
kubernetesDir string
|
kubernetesDir string
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
realManifestDir string
|
realManifestDir string
|
||||||
tempManifestDir string
|
tempManifestDir string
|
||||||
@ -90,10 +87,9 @@ type KubeStaticPodPathManager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewKubeStaticPodPathManager creates a new instance of KubeStaticPodPathManager
|
// 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{
|
return &KubeStaticPodPathManager{
|
||||||
kubernetesDir: kubernetesDir,
|
kubernetesDir: kubernetesDir,
|
||||||
kustomizeDir: kustomizeDir,
|
|
||||||
patchesDir: patchesDir,
|
patchesDir: patchesDir,
|
||||||
realManifestDir: filepath.Join(kubernetesDir, constants.ManifestsSubDirName),
|
realManifestDir: filepath.Join(kubernetesDir, constants.ManifestsSubDirName),
|
||||||
tempManifestDir: tempDir,
|
tempManifestDir: tempDir,
|
||||||
@ -105,7 +101,7 @@ func NewKubeStaticPodPathManager(kubernetesDir, kustomizeDir, patchesDir, tempDi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewKubeStaticPodPathManagerUsingTempDirs creates a new instance of KubeStaticPodPathManager with temporary directories backing it
|
// 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")
|
upgradedManifestsDir, err := constants.CreateTempDirForKubeadm(kubernetesDir, "kubeadm-upgraded-manifests")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -120,7 +116,7 @@ func NewKubeStaticPodPathManagerUsingTempDirs(kubernetesDir, kustomizeDir, patch
|
|||||||
return nil, err
|
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
|
// MoveFile should move a file from oldPath to newPath
|
||||||
@ -133,11 +129,6 @@ func (spm *KubeStaticPodPathManager) KubernetesDir() string {
|
|||||||
return spm.kubernetesDir
|
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
|
// PatchesDir should point to the folder where patches for components are stored
|
||||||
func (spm *KubeStaticPodPathManager) PatchesDir() string {
|
func (spm *KubeStaticPodPathManager) PatchesDir() string {
|
||||||
return spm.patchesDir
|
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
|
// Write the updated etcd static Pod manifest into the temporary directory, at this point no etcd change
|
||||||
// has occurred in any aspects.
|
// 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")
|
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
|
// Write the updated static Pod manifests into the temporary directory
|
||||||
fmt.Printf("[upgrade/staticpods] Writing new Static Pod manifests to %q\n", pathMgr.TempManifestDir())
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error creating init static pod manifest files")
|
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.
|
// 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
|
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
|
// 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 {
|
func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.InitConfiguration, etcdUpgrade, renewCerts bool, patchesDir string) error {
|
||||||
pathManager, err := GetPathManagerForUpgrade(constants.KubernetesDir, kustomizeDir, patchesDir, internalcfg, etcdUpgrade)
|
pathManager, err := GetPathManagerForUpgrade(constants.KubernetesDir, patchesDir, internalcfg, etcdUpgrade)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -622,14 +613,14 @@ func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DryRunStaticPodUpgrade fakes an upgrade of the control plane
|
// 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")
|
dryRunManifestDir, err := constants.CreateTempDirForKubeadm("", "kubeadm-upgrade-dryrun")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dryRunManifestDir)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,6 @@ func (w *fakeWaiter) WaitForKubeletAndFunc(f func() error) error {
|
|||||||
|
|
||||||
type fakeStaticPodPathManager struct {
|
type fakeStaticPodPathManager struct {
|
||||||
kubernetesDir string
|
kubernetesDir string
|
||||||
kustomizeDir string
|
|
||||||
patchesDir string
|
patchesDir string
|
||||||
realManifestDir string
|
realManifestDir string
|
||||||
tempManifestDir string
|
tempManifestDir string
|
||||||
@ -196,10 +195,6 @@ func (spm *fakeStaticPodPathManager) KubernetesDir() string {
|
|||||||
return spm.kubernetesDir
|
return spm.kubernetesDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spm *fakeStaticPodPathManager) KustomizeDir() string {
|
|
||||||
return spm.kustomizeDir
|
|
||||||
}
|
|
||||||
|
|
||||||
func (spm *fakeStaticPodPathManager) PatchesDir() string {
|
func (spm *fakeStaticPodPathManager) PatchesDir() string {
|
||||||
return spm.patchesDir
|
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
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("couldn't run CreateInitStaticPodManifestFiles: %v", err)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("couldn't run CreateLocalEtcdStaticPodManifestFile: %v", err)
|
t.Fatalf("couldn't run CreateLocalEtcdStaticPodManifestFile: %v", err)
|
||||||
}
|
}
|
||||||
@ -635,7 +630,7 @@ func TestCleanupDirs(t *testing.T) {
|
|||||||
backupEtcdDir, cleanup := getTempDir(t, "backupEtcdDir")
|
backupEtcdDir, cleanup := getTempDir(t, "backupEtcdDir")
|
||||||
defer cleanup()
|
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()
|
err := mgr.CleanupDirs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error cleaning up: %v", err)
|
t.Errorf("unexpected error cleaning up: %v", err)
|
||||||
@ -953,7 +948,7 @@ func TestGetPathManagerForUpgrade(t *testing.T) {
|
|||||||
os.RemoveAll(tmpdir)
|
os.RemoveAll(tmpdir)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pathmgr, err := GetPathManagerForUpgrade(tmpdir, "", "", test.cfg, test.etcdUpgrade)
|
pathmgr, err := GetPathManagerForUpgrade(tmpdir, "", test.cfg, test.etcdUpgrade)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error creating path manager: %v", err)
|
t.Fatalf("unexpected error creating path manager: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ filegroup(
|
|||||||
"//cmd/kubeadm/app/util/image:all-srcs",
|
"//cmd/kubeadm/app/util/image:all-srcs",
|
||||||
"//cmd/kubeadm/app/util/initsystem:all-srcs",
|
"//cmd/kubeadm/app/util/initsystem:all-srcs",
|
||||||
"//cmd/kubeadm/app/util/kubeconfig: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/output:all-srcs",
|
||||||
"//cmd/kubeadm/app/util/patches:all-srcs",
|
"//cmd/kubeadm/app/util/patches:all-srcs",
|
||||||
"//cmd/kubeadm/app/util/pkiutil:all-srcs",
|
"//cmd/kubeadm/app/util/pkiutil:all-srcs",
|
||||||
|
@ -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",
|
|
||||||
],
|
|
||||||
)
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
@ -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'")
|
|
||||||
}
|
|
@ -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))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ go_test(
|
|||||||
"//cmd/kubeadm/test:go_default_library",
|
"//cmd/kubeadm/test:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1: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",
|
"//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/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//cmd/kubeadm/app/util: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",
|
"//cmd/kubeadm/app/util/patches:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
|
@ -37,7 +37,6 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/kustomize"
|
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/patches"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/patches"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -150,38 +149,6 @@ func GetExtraParameters(overrides map[string]string, defaults map[string]string)
|
|||||||
return command
|
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.
|
// PatchStaticPod applies patches stored in patchesDir to a static Pod.
|
||||||
func PatchStaticPod(pod *v1.Pod, patchesDir string, output io.Writer) (*v1.Pod, error) {
|
func PatchStaticPod(pod *v1.Pod, patchesDir string, output io.Writer) (*v1.Pod, error) {
|
||||||
// Marshal the Pod manifest into YAML.
|
// Marshal the Pod manifest into YAML.
|
||||||
|
@ -25,8 +25,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lithammer/dedent"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
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) {
|
func TestPatchStaticPod(t *testing.T) {
|
||||||
type file struct {
|
type file struct {
|
||||||
name string
|
name string
|
||||||
|
Loading…
Reference in New Issue
Block a user