From f97770b175ffb534cccc6ce023c0b984917b0816 Mon Sep 17 00:00:00 2001 From: "Rostislav M. Georgiev" Date: Wed, 19 Sep 2018 15:08:29 +0300 Subject: [PATCH] kubeadm: Detect CRIs automatically In order to allow for a smoother UX with CRIs different than Docker, we have to make the --cri-socket command line flag optional when just one CRI is installed. This change does that by doing the following: - Introduce a new runtime function (DetectCRISocket) that will attempt to detect a CRI socket, or return an appropriate error. - Default to using the above function if --cri-socket is not specified and CRISocket in NodeRegistrationOptions is empty. - Stop static defaulting to DefaultCRISocket. And rename it to DefaultDockerCRISocket. Its use is now narrowed to "Docker or not" distinguishment and tests. - Introduce AddCRISocketFlag function that adds --cri-socket flag to a flagSet. Use that in all commands, that support --cri-socket. - Remove the deprecated --cri-socket-path flag from kubeadm config images pull and deprecate --cri-socket in kubeadm upgrade apply. Signed-off-by: Rostislav M. Georgiev --- .../app/apis/kubeadm/v1alpha3/defaults.go | 8 - .../apis/kubeadm/v1alpha3/defaults_unix.go | 4 - .../apis/kubeadm/v1alpha3/defaults_windows.go | 4 - .../kubeadm/v1alpha3/zz_generated.defaults.go | 2 - .../app/apis/kubeadm/v1beta1/defaults.go | 8 - .../app/apis/kubeadm/v1beta1/defaults_unix.go | 2 - .../apis/kubeadm/v1beta1/defaults_windows.go | 2 - .../kubeadm/v1beta1/zz_generated.defaults.go | 2 - cmd/kubeadm/app/cmd/config.go | 15 +- cmd/kubeadm/app/cmd/config_test.go | 14 +- cmd/kubeadm/app/cmd/init.go | 7 +- cmd/kubeadm/app/cmd/join.go | 8 +- cmd/kubeadm/app/cmd/reset.go | 22 ++- cmd/kubeadm/app/cmd/reset_test.go | 2 +- cmd/kubeadm/app/cmd/upgrade/apply.go | 10 +- cmd/kubeadm/app/cmd/util/BUILD | 2 + cmd/kubeadm/app/cmd/util/cmdutil.go | 10 ++ cmd/kubeadm/app/constants/BUILD | 6 +- cmd/kubeadm/app/constants/constants_unix.go | 24 +++ .../app/constants/constants_windows.go | 24 +++ cmd/kubeadm/app/phases/kubelet/BUILD | 1 - cmd/kubeadm/app/phases/kubelet/flags.go | 3 +- cmd/kubeadm/app/preflight/BUILD | 1 - cmd/kubeadm/app/preflight/checks_test.go | 3 +- cmd/kubeadm/app/util/config/BUILD | 1 + .../app/util/config/initconfiguration.go | 9 + cmd/kubeadm/app/util/runtime/BUILD | 4 +- cmd/kubeadm/app/util/runtime/runtime.go | 65 ++++++- cmd/kubeadm/app/util/runtime/runtime_test.go | 165 ++++++++++++++++-- 29 files changed, 347 insertions(+), 81 deletions(-) create mode 100644 cmd/kubeadm/app/constants/constants_unix.go create mode 100644 cmd/kubeadm/app/constants/constants_windows.go diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go index 087b5b01b5..f72b326fd8 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go @@ -68,7 +68,6 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_InitConfiguration assigns default values for the InitConfiguration func SetDefaults_InitConfiguration(obj *InitConfiguration) { SetDefaults_ClusterConfiguration(&obj.ClusterConfiguration) - SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) SetDefaults_BootstrapTokens(obj) SetDefaults_APIEndpoint(&obj.APIEndpoint) } @@ -139,16 +138,9 @@ func SetDefaults_JoinConfiguration(obj *JoinConfiguration) { } } - SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) SetDefaults_APIEndpoint(&obj.APIEndpoint) } -func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) { - if obj.CRISocket == "" { - obj.CRISocket = DefaultCRISocket - } -} - // SetDefaults_AuditPolicyConfiguration sets default values for the AuditPolicyConfiguration func SetDefaults_AuditPolicyConfiguration(obj *ClusterConfiguration) { if obj.AuditPolicyConfiguration.LogDir == "" { diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go index 7e60d20b08..b7fae43be4 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go @@ -21,8 +21,4 @@ package v1alpha3 const ( // DefaultCACertPath defines default location of CA certificate on Linux DefaultCACertPath = "/etc/kubernetes/pki/ca.crt" - // DefaultUrlScheme defines default socket url prefix - DefaultUrlScheme = "unix" - // DefaultCRISocket defines the default cri socket - DefaultCRISocket = "/var/run/dockershim.sock" ) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go index fa68cf94c5..3eef579618 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go @@ -21,8 +21,4 @@ package v1alpha3 const ( // DefaultCACertPath defines default location of CA certificate on Windows DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt" - // DefaultUrlScheme defines default socket url prefix - DefaultUrlScheme = "tcp" - // DefaultCRISocket defines the default cri socket - DefaultCRISocket = "tcp://localhost:2375" ) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go index 9096818730..0c05940cba 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go @@ -49,12 +49,10 @@ func SetObjectDefaults_InitConfiguration(in *InitConfiguration) { a := &in.BootstrapTokens[i] SetDefaults_BootstrapToken(a) } - SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) SetDefaults_APIEndpoint(&in.APIEndpoint) } func SetObjectDefaults_JoinConfiguration(in *JoinConfiguration) { SetDefaults_JoinConfiguration(in) - SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) SetDefaults_APIEndpoint(&in.APIEndpoint) } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults.go index 60c72a73d3..a241f07cc5 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults.go @@ -68,7 +68,6 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_InitConfiguration assigns default values for the InitConfiguration func SetDefaults_InitConfiguration(obj *InitConfiguration) { SetDefaults_ClusterConfiguration(&obj.ClusterConfiguration) - SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) SetDefaults_BootstrapTokens(obj) SetDefaults_APIEndpoint(&obj.LocalAPIEndpoint) } @@ -138,17 +137,10 @@ func SetDefaults_JoinConfiguration(obj *JoinConfiguration) { obj.CACertPath = DefaultCACertPath } - SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) SetDefaults_JoinControlPlane(obj.ControlPlane) SetDefaults_Discovery(&obj.Discovery) } -func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) { - if obj.CRISocket == "" { - obj.CRISocket = DefaultCRISocket - } -} - func SetDefaults_JoinControlPlane(obj *JoinControlPlane) { if obj != nil { SetDefaults_APIEndpoint(&obj.LocalAPIEndpoint) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_unix.go b/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_unix.go index f4a50f9972..18510d4c86 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_unix.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_unix.go @@ -23,6 +23,4 @@ const ( DefaultCACertPath = "/etc/kubernetes/pki/ca.crt" // DefaultUrlScheme defines default socket url prefix DefaultUrlScheme = "unix" - // DefaultCRISocket defines the default cri socket - DefaultCRISocket = "/var/run/dockershim.sock" ) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_windows.go b/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_windows.go index 13b1d88ffc..8523188019 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_windows.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta1/defaults_windows.go @@ -23,6 +23,4 @@ const ( DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt" // DefaultUrlScheme defines default socket url prefix DefaultUrlScheme = "tcp" - // DefaultCRISocket defines the default cri socket - DefaultCRISocket = "tcp://localhost:2375" ) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta1/zz_generated.defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1beta1/zz_generated.defaults.go index 4860aec6a2..95a8e67963 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta1/zz_generated.defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta1/zz_generated.defaults.go @@ -50,13 +50,11 @@ func SetObjectDefaults_InitConfiguration(in *InitConfiguration) { a := &in.BootstrapTokens[i] SetDefaults_BootstrapToken(a) } - SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) SetDefaults_APIEndpoint(&in.LocalAPIEndpoint) } func SetObjectDefaults_JoinConfiguration(in *JoinConfiguration) { SetDefaults_JoinConfiguration(in) - SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) SetDefaults_Discovery(&in.Discovery) if in.Discovery.File != nil { SetDefaults_FileDiscovery(in.Discovery.File) diff --git a/cmd/kubeadm/app/cmd/config.go b/cmd/kubeadm/app/cmd/config.go index e4545c9f5c..be116f0c0e 100644 --- a/cmd/kubeadm/app/cmd/config.go +++ b/cmd/kubeadm/app/cmd/config.go @@ -185,6 +185,9 @@ func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) { KubernetesVersion: fmt.Sprintf("v1.%d.0", constants.MinimumControlPlaneVersion.Minor()+1), }, BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{placeholderToken}, + NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{ + CRISocket: constants.DefaultDockerCRISocket, // avoid CRI detection + }, }) } @@ -206,6 +209,9 @@ func getDefaultNodeConfigBytes() ([]byte, error) { UnsafeSkipCAVerification: true, // TODO: UnsafeSkipCAVerification: true needs to be set for validation to pass, but shouldn't be recommended as the default }, }, + NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{ + CRISocket: constants.DefaultDockerCRISocket, // avoid CRI detection + }, }) if err != nil { return []byte{}, err @@ -430,7 +436,7 @@ func NewCmdConfigImagesPull() *cobra.Command { }, } AddImagesCommonConfigFlags(cmd.PersistentFlags(), externalcfg, &cfgPath, &featureGatesString) - AddImagesPullFlags(cmd.PersistentFlags(), externalcfg) + cmdutil.AddCRISocketFlag(cmd.PersistentFlags(), &externalcfg.NodeRegistration.CRISocket) return cmd } @@ -525,10 +531,3 @@ func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.In "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) flagSet.StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file.") } - -// AddImagesPullFlags adds flags related to the `kubeadm config images pull` command -func AddImagesPullFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration) { - flagSet.StringVar(&cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket, "Specify the CRI socket to connect to.") - flagSet.StringVar(&cfg.NodeRegistration.CRISocket, "cri-socket-path", cfg.NodeRegistration.CRISocket, "Path to the CRI socket.") - flagSet.MarkDeprecated("cri-socket-path", "Please, use --cri-socket instead") -} diff --git a/cmd/kubeadm/app/cmd/config_test.go b/cmd/kubeadm/app/cmd/config_test.go index 0a7a9f8fc2..60cd984920 100644 --- a/cmd/kubeadm/app/cmd/config_test.go +++ b/cmd/kubeadm/app/cmd/config_test.go @@ -145,6 +145,9 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{ KubernetesVersion: dummyKubernetesVersion, }, + NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{ + CRISocket: constants.DefaultDockerCRISocket, + }, }, }, { @@ -158,6 +161,9 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { }, KubernetesVersion: dummyKubernetesVersion, }, + NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{ + CRISocket: constants.DefaultDockerCRISocket, + }, }, expectedImages: defaultNumberOfImages - 1, }, @@ -167,6 +173,9 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{ KubernetesVersion: dummyKubernetesVersion, }, + NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{ + CRISocket: constants.DefaultDockerCRISocket, + }, }, expectedImages: defaultNumberOfImages, }, @@ -179,6 +188,9 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) { Type: kubeadmapiv1beta1.KubeDNS, }, }, + NodeRegistration: kubeadmapiv1beta1.NodeRegistrationOptions{ + CRISocket: constants.DefaultDockerCRISocket, + }, }, expectedImages: defaultNumberOfImages + 2, }, @@ -226,7 +238,7 @@ func TestImagesPull(t *testing.T) { LookPathFunc: func(cmd string) (string, error) { return "/usr/bin/docker", nil }, } - containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, kubeadmapiv1beta1.DefaultCRISocket) + containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, constants.DefaultDockerCRISocket) if err != nil { t.Errorf("unexpected NewContainerRuntime error: %v", err) } diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index 9c6764d7f9..6381c29e7a 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -230,10 +230,7 @@ func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfig &cfg.NodeRegistration.Name, options.NodeName, cfg.NodeRegistration.Name, `Specify the node name.`, ) - flagSet.StringVar( - &cfg.NodeRegistration.CRISocket, options.NodeCRISocket, cfg.NodeRegistration.CRISocket, - `Specify the CRI socket to connect to.`, - ) + cmdutil.AddCRISocketFlag(flagSet, &cfg.NodeRegistration.CRISocket) flagSet.StringVar(featureGatesString, options.FeatureGatesString, *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+ "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) } @@ -316,7 +313,7 @@ func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initD if options.externalcfg.NodeRegistration.Name != "" { cfg.NodeRegistration.Name = options.externalcfg.NodeRegistration.Name } - if options.externalcfg.NodeRegistration.CRISocket != kubeadmapiv1beta1.DefaultCRISocket { + if options.externalcfg.NodeRegistration.CRISocket != "" { cfg.NodeRegistration.CRISocket = options.externalcfg.NodeRegistration.CRISocket } diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 06f0e57045..5d281a03a3 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -39,6 +39,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" + cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/discovery" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" @@ -232,10 +233,6 @@ func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.JoinConfig &cfg.NodeRegistration.Name, options.NodeName, cfg.NodeRegistration.Name, `Specify the node name.`, ) - flagSet.StringVar( - &cfg.NodeRegistration.CRISocket, options.NodeCRISocket, cfg.NodeRegistration.CRISocket, - `Specify the CRI socket to connect to.`, - ) flagSet.StringVar( &cfg.Discovery.TLSBootstrapToken, options.TLSBootstrapToken, cfg.Discovery.TLSBootstrapToken, `Specify the token used to temporarily authenticate with the Kubernetes Master while joining the node.`, @@ -243,6 +240,7 @@ func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.JoinConfig AddControlPlaneFlags(flagSet, cfg.ControlPlane) AddJoinBootstrapTokenDiscoveryFlags(flagSet, cfg.Discovery.BootstrapToken) AddJoinFileDiscoveryFlags(flagSet, cfg.Discovery.File) + cmdutil.AddCRISocketFlag(flagSet, &cfg.NodeRegistration.CRISocket) } // AddJoinBootstrapTokenDiscoveryFlags adds bootstrap token specific discovery flags to the specified flagset @@ -388,7 +386,7 @@ func newJoinData(cmd *cobra.Command, options *joinOptions, out io.Writer) (joinD if options.externalcfg.NodeRegistration.Name != "" { cfg.NodeRegistration.Name = options.externalcfg.NodeRegistration.Name } - if options.externalcfg.NodeRegistration.CRISocket != kubeadmapiv1beta1.DefaultCRISocket { + if options.externalcfg.NodeRegistration.CRISocket != "" { cfg.NodeRegistration.CRISocket = options.externalcfg.NodeRegistration.CRISocket } diff --git a/cmd/kubeadm/app/cmd/reset.go b/cmd/kubeadm/app/cmd/reset.go index e8c9986e24..6761bfc018 100644 --- a/cmd/kubeadm/app/cmd/reset.go +++ b/cmd/kubeadm/app/cmd/reset.go @@ -67,6 +67,12 @@ func NewCmdReset(in io.Reader, out io.Writer) *cobra.Command { kubeadmutil.CheckErr(err) } + if criSocketPath != "" { + criSocketPath, err = resetDetectCRISocket(client) + kubeadmutil.CheckErr(err) + klog.V(1).Infof("[reset] detected and using CRI socket: %s", criSocketPath) + } + r, err := NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) kubeadmutil.CheckErr(err) kubeadmutil.CheckErr(r.Run(out, client)) @@ -81,10 +87,7 @@ func NewCmdReset(in io.Reader, out io.Writer) *cobra.Command { "The path to the directory where the certificates are stored. If specified, clean this directory.", ) - cmd.PersistentFlags().StringVar( - &criSocketPath, "cri-socket", kubeadmapiv1beta1.DefaultCRISocket, - "The path to the CRI socket to use with crictl when cleaning up containers.", - ) + cmdutil.AddCRISocketFlag(cmd.PersistentFlags(), &criSocketPath) cmd.PersistentFlags().BoolVarP( &forceReset, "force", "f", false, @@ -295,3 +298,14 @@ func resetConfigDir(configPathDir, pkiPathDir string) { } } } + +func resetDetectCRISocket(client clientset.Interface) (string, error) { + // first try to connect to the cluster for the CRI socket + cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "reset", "", false) + if err == nil { + return cfg.NodeRegistration.CRISocket, nil + } + + // if this fails, try to detect it + return utilruntime.DetectCRISocket() +} diff --git a/cmd/kubeadm/app/cmd/reset_test.go b/cmd/kubeadm/app/cmd/reset_test.go index d7e44cad57..be05a6b098 100644 --- a/cmd/kubeadm/app/cmd/reset_test.go +++ b/cmd/kubeadm/app/cmd/reset_test.go @@ -88,7 +88,7 @@ func assertDirEmpty(t *testing.T, path string) { func TestNewReset(t *testing.T) { var in io.Reader certsDir := kubeadmapiv1beta1.DefaultCertificatesDir - criSocketPath := kubeadmapiv1beta1.DefaultCRISocket + criSocketPath := kubeadmconstants.DefaultDockerCRISocket forceReset := true ignorePreflightErrors := []string{"all"} diff --git a/cmd/kubeadm/app/cmd/upgrade/apply.go b/cmd/kubeadm/app/cmd/upgrade/apply.go index e3659209ca..b2188aa8fb 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply.go @@ -29,6 +29,7 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" @@ -70,7 +71,7 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command { applyPlanFlags: apf, imagePullTimeout: defaultImagePullTimeout, etcdUpgrade: true, - criSocket: kubeadmapiv1beta1.DefaultCRISocket, + // Don't set criSocket to a default value here, as this will override the setting in the stored config in RunApply below. } cmd := &cobra.Command{ @@ -127,8 +128,11 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command { cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output what actions would be performed.") cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.") 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: Register this flag in a generic place - cmd.Flags().StringVar(&flags.criSocket, "cri-socket", flags.criSocket, "Specify the CRI socket to connect to.") + + // The CRI socket flag is deprecated here, since it should be taken from the NodeRegistrationOptions for the current + // node instead of the command line. This prevents errors by the users (such as attempts to use wrong CRI during upgrade). + cmdutil.AddCRISocketFlag(cmd.Flags(), &flags.criSocket) + cmd.Flags().MarkDeprecated(options.NodeCRISocket, "This flag is deprecated. Please, avoid using it.") return cmd } diff --git a/cmd/kubeadm/app/cmd/util/BUILD b/cmd/kubeadm/app/cmd/util/BUILD index aadf9f89f7..72803c3183 100644 --- a/cmd/kubeadm/app/cmd/util/BUILD +++ b/cmd/kubeadm/app/cmd/util/BUILD @@ -10,6 +10,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util", visibility = ["//visibility:public"], deps = [ + "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//cmd/kubeadm/app/util/pubkeypin:go_default_library", @@ -18,6 +19,7 @@ go_library( "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", ], ) diff --git a/cmd/kubeadm/app/cmd/util/cmdutil.go b/cmd/kubeadm/app/cmd/util/cmdutil.go index 80a8563174..69827f043b 100644 --- a/cmd/kubeadm/app/cmd/util/cmdutil.go +++ b/cmd/kubeadm/app/cmd/util/cmdutil.go @@ -19,8 +19,10 @@ package util import ( "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/pflag" "k8s.io/client-go/tools/clientcmd" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) @@ -73,3 +75,11 @@ func FindExistingKubeConfig(file string) string { rules.Precedence = append(rules.Precedence, kubeadmconstants.GetAdminKubeConfigPath()) return rules.GetDefaultFilename() } + +// AddCRISocketFlag adds the cri-socket flag to the supplied flagSet +func AddCRISocketFlag(flagSet *pflag.FlagSet, criSocket *string) { + flagSet.StringVar( + criSocket, options.NodeCRISocket, *criSocket, + "Path to the CRI socket to connect. If empty kubeadm will try to auto-detect this value; use this option only if you have more than one CRI installed or if you have non-standard CRI socket.", + ) +} diff --git a/cmd/kubeadm/app/constants/BUILD b/cmd/kubeadm/app/constants/BUILD index 7c1d85a611..acd3daff0d 100644 --- a/cmd/kubeadm/app/constants/BUILD +++ b/cmd/kubeadm/app/constants/BUILD @@ -8,7 +8,11 @@ load( go_library( name = "go_default_library", - srcs = ["constants.go"], + srcs = [ + "constants.go", + "constants_unix.go", + "constants_windows.go", + ], importpath = "k8s.io/kubernetes/cmd/kubeadm/app/constants", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", diff --git a/cmd/kubeadm/app/constants/constants_unix.go b/cmd/kubeadm/app/constants/constants_unix.go new file mode 100644 index 0000000000..16ff72d555 --- /dev/null +++ b/cmd/kubeadm/app/constants/constants_unix.go @@ -0,0 +1,24 @@ +// +build !windows + +/* +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 constants + +const ( + // DefaultDockerCRISocket defines the default Docker CRI socket + DefaultDockerCRISocket = "/var/run/dockershim.sock" +) diff --git a/cmd/kubeadm/app/constants/constants_windows.go b/cmd/kubeadm/app/constants/constants_windows.go new file mode 100644 index 0000000000..4ee63a3ef4 --- /dev/null +++ b/cmd/kubeadm/app/constants/constants_windows.go @@ -0,0 +1,24 @@ +// +build windows + +/* +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 constants + +const ( + // DefaultDockerCRISocket defines the default Docker CRI socket + DefaultDockerCRISocket = "tcp://localhost:2375" +) diff --git a/cmd/kubeadm/app/phases/kubelet/BUILD b/cmd/kubeadm/app/phases/kubelet/BUILD index 856542ed43..2d639a8c00 100644 --- a/cmd/kubeadm/app/phases/kubelet/BUILD +++ b/cmd/kubeadm/app/phases/kubelet/BUILD @@ -12,7 +12,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/images:go_default_library", diff --git a/cmd/kubeadm/app/phases/kubelet/flags.go b/cmd/kubeadm/app/phases/kubelet/flags.go index a1d6ba9bd9..e57f317cd5 100644 --- a/cmd/kubeadm/app/phases/kubelet/flags.go +++ b/cmd/kubeadm/app/phases/kubelet/flags.go @@ -26,7 +26,6 @@ import ( "github.com/pkg/errors" "k8s.io/klog" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/images" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" @@ -74,7 +73,7 @@ func WriteKubeletDynamicEnvFile(cfg *kubeadmapi.InitConfiguration, registerTaint func buildKubeletArgMap(opts kubeletFlagsOpts) map[string]string { kubeletFlags := map[string]string{} - if opts.nodeRegOpts.CRISocket == kubeadmapiv1beta1.DefaultCRISocket { + if opts.nodeRegOpts.CRISocket == constants.DefaultDockerCRISocket { // These flags should only be set when running docker kubeletFlags["network-plugin"] = "cni" driver, err := kubeadmutil.GetCgroupDriverDocker(opts.execer) diff --git a/cmd/kubeadm/app/preflight/BUILD b/cmd/kubeadm/app/preflight/BUILD index 39578e47cd..9af721a525 100644 --- a/cmd/kubeadm/app/preflight/BUILD +++ b/cmd/kubeadm/app/preflight/BUILD @@ -45,7 +45,6 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/cmd/kubeadm/app/preflight/checks_test.go b/cmd/kubeadm/app/preflight/checks_test.go index 3ec7a79059..d9af3cdbb2 100644 --- a/cmd/kubeadm/app/preflight/checks_test.go +++ b/cmd/kubeadm/app/preflight/checks_test.go @@ -31,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" "k8s.io/kubernetes/cmd/kubeadm/app/constants" utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime" "k8s.io/utils/exec" @@ -756,7 +755,7 @@ func TestImagePullCheck(t *testing.T) { LookPathFunc: func(cmd string) (string, error) { return "/usr/bin/docker", nil }, } - containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, kubeadmapiv1beta1.DefaultCRISocket) + containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, constants.DefaultDockerCRISocket) if err != nil { t.Errorf("unexpected NewContainerRuntime error: %v", err) } diff --git a/cmd/kubeadm/app/util/config/BUILD b/cmd/kubeadm/app/util/config/BUILD index 738e33ab58..0533899439 100644 --- a/cmd/kubeadm/app/util/config/BUILD +++ b/cmd/kubeadm/app/util/config/BUILD @@ -24,6 +24,7 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/config/strict:go_default_library", + "//cmd/kubeadm/app/util/runtime:go_default_library", "//pkg/util/node:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/cmd/kubeadm/app/util/config/initconfiguration.go b/cmd/kubeadm/app/util/config/initconfiguration.go index f1750e0d37..860188ac87 100644 --- a/cmd/kubeadm/app/util/config/initconfiguration.go +++ b/cmd/kubeadm/app/util/config/initconfiguration.go @@ -40,6 +40,7 @@ import ( kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict" + kubeadmruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime" nodeutil "k8s.io/kubernetes/pkg/util/node" ) @@ -96,6 +97,14 @@ func SetNodeRegistrationDynamicDefaults(cfg *kubeadmapi.NodeRegistrationOptions, cfg.Taints = []v1.Taint{kubeadmconstants.MasterTaint} } + if cfg.CRISocket == "" { + cfg.CRISocket, err = kubeadmruntime.DetectCRISocket() + if err != nil { + return err + } + klog.V(1).Infof("detected and using CRI socket: %s", cfg.CRISocket) + } + return nil } diff --git a/cmd/kubeadm/app/util/runtime/BUILD b/cmd/kubeadm/app/util/runtime/BUILD index 04ddf1dbe9..27e839bb8d 100644 --- a/cmd/kubeadm/app/util/runtime/BUILD +++ b/cmd/kubeadm/app/util/runtime/BUILD @@ -6,7 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime", visibility = ["//visibility:public"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", @@ -18,7 +18,7 @@ go_test( srcs = ["runtime_test.go"], embed = [":go_default_library"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec/testing:go_default_library", diff --git a/cmd/kubeadm/app/util/runtime/runtime.go b/cmd/kubeadm/app/util/runtime/runtime.go index bbf51978d9..796f35d3bf 100644 --- a/cmd/kubeadm/app/util/runtime/runtime.go +++ b/cmd/kubeadm/app/util/runtime/runtime.go @@ -17,6 +17,7 @@ limitations under the License. package util import ( + "os" "path/filepath" goruntime "runtime" "strings" @@ -24,7 +25,7 @@ import ( "github.com/pkg/errors" errorsutil "k8s.io/apimachinery/pkg/util/errors" - kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" utilsexec "k8s.io/utils/exec" ) @@ -54,7 +55,7 @@ func NewContainerRuntime(execer utilsexec.Interface, criSocket string) (Containe var toolName string var runtime ContainerRuntime - if criSocket != kubeadmapiv1beta1.DefaultCRISocket { + if criSocket != constants.DefaultDockerCRISocket { toolName = "crictl" // !!! temporary work around crictl warning: // Using "/var/run/crio/crio.sock" as endpoint is deprecated, @@ -180,3 +181,63 @@ func (runtime *DockerRuntime) ImageExists(image string) (bool, error) { err := runtime.exec.Command("docker", "inspect", image).Run() return err == nil, nil } + +// isExistingSocket checks if path exists and is domain socket +func isExistingSocket(path string) bool { + fileInfo, err := os.Stat(path) + if err != nil { + return false + } + + return fileInfo.Mode()&os.ModeSocket != 0 +} + +// detectCRISocketImpl is separated out only for test purposes, DON'T call it directly, use DetectCRISocket instead +func detectCRISocketImpl(isSocket func(string) bool) (string, error) { + const ( + dockerSocket = "/var/run/docker.sock" // The Docker socket is not CRI compatible + containerdSocket = "/run/containerd/containerd.sock" + ) + + foundCRISockets := []string{} + knownCRISockets := []string{ + // Docker and containerd sockets are special cased below, hence not to be included here + "/var/run/crio/crio.sock", + } + + if isSocket(dockerSocket) { + // the path in dockerSocket is not CRI compatible, hence we should replace it with a CRI compatible socket + foundCRISockets = append(foundCRISockets, constants.DefaultDockerCRISocket) + } else if isSocket(containerdSocket) { + // Docker 18.09 gets bundled together with containerd, thus having both dockerSocket and containerdSocket present. + // For compatibility reasons, we use the containerd socket only if Docker is not detected. + foundCRISockets = append(foundCRISockets, containerdSocket) + } + + for _, socket := range knownCRISockets { + if isSocket(socket) { + foundCRISockets = append(foundCRISockets, socket) + } + } + + switch len(foundCRISockets) { + case 0: + // Fall back to Docker if no CRI is detected, we can error out later on if we need it + return constants.DefaultDockerCRISocket, nil + case 1: + // Precisely one CRI found, use that + return foundCRISockets[0], nil + default: + // Multiple CRIs installed? + return "", errors.Errorf("Found multiple CRI sockets, please use --cri-socket to select one: %s", strings.Join(foundCRISockets, ", ")) + } +} + +// DetectCRISocket uses a list of known CRI sockets to detect one. If more than one or none is discovered, an error is returned. +func DetectCRISocket() (string, error) { + if goruntime.GOOS != "linux" { + return constants.DefaultDockerCRISocket, nil + } + + return detectCRISocketImpl(isExistingSocket) +} diff --git a/cmd/kubeadm/app/util/runtime/runtime_test.go b/cmd/kubeadm/app/util/runtime/runtime_test.go index 2056d99d96..dc01c41aa5 100644 --- a/cmd/kubeadm/app/util/runtime/runtime_test.go +++ b/cmd/kubeadm/app/util/runtime/runtime_test.go @@ -17,12 +17,16 @@ limitations under the License. package util import ( + "io/ioutil" + "net" + "os" "reflect" + "runtime" "testing" "github.com/pkg/errors" - kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/utils/exec" fakeexec "k8s.io/utils/exec/testing" ) @@ -41,7 +45,7 @@ func TestNewContainerRuntime(t *testing.T) { isDocker bool isError bool }{ - {"valid: default cri socket", execLookPathOK, kubeadmapiv1beta1.DefaultCRISocket, true, false}, + {"valid: default cri socket", execLookPathOK, constants.DefaultDockerCRISocket, true, false}, {"valid: cri-o socket url", execLookPathOK, "unix:///var/run/crio/crio.sock", false, false}, {"valid: cri-o socket path", execLookPathOK, "/var/run/crio/crio.sock", false, false}, {"invalid: no crictl", execLookPathErr, "unix:///var/run/crio/crio.sock", false, true}, @@ -105,8 +109,8 @@ func TestIsRunning(t *testing.T) { }{ {"valid: CRI-O is running", "unix:///var/run/crio/crio.sock", criExecer, false}, {"invalid: CRI-O is not running", "unix:///var/run/crio/crio.sock", criExecer, true}, - {"valid: docker is running", kubeadmapiv1beta1.DefaultCRISocket, dockerExecer, false}, - {"invalid: docker is not running", kubeadmapiv1beta1.DefaultCRISocket, dockerExecer, true}, + {"valid: docker is running", constants.DefaultDockerCRISocket, dockerExecer, false}, + {"invalid: docker is not running", constants.DefaultDockerCRISocket, dockerExecer, true}, } for _, tc := range cases { @@ -146,7 +150,7 @@ func TestListKubeContainers(t *testing.T) { }{ {"valid: list containers using CRI socket url", "unix:///var/run/crio/crio.sock", false}, {"invalid: list containers using CRI socket url", "unix:///var/run/crio/crio.sock", true}, - {"valid: list containers using docker", kubeadmapiv1beta1.DefaultCRISocket, false}, + {"valid: list containers using docker", constants.DefaultDockerCRISocket, false}, } for _, tc := range cases { @@ -199,8 +203,8 @@ func TestRemoveContainers(t *testing.T) { {"valid: remove containers using CRI", "unix:///var/run/crio/crio.sock", []string{"k8s_p1", "k8s_p2", "k8s_p3"}, false}, // Test case 1 {"invalid: CRI rmp failure", "unix:///var/run/crio/crio.sock", []string{"k8s_p1", "k8s_p2", "k8s_p3"}, true}, {"invalid: CRI stopp failure", "unix:///var/run/crio/crio.sock", []string{"k8s_p1", "k8s_p2", "k8s_p3"}, true}, - {"valid: remove containers using docker", kubeadmapiv1beta1.DefaultCRISocket, []string{"k8s_c1", "k8s_c2", "k8s_c3"}, false}, - {"invalid: remove containers using docker", kubeadmapiv1beta1.DefaultCRISocket, []string{"k8s_c1", "k8s_c2", "k8s_c3"}, true}, + {"valid: remove containers using docker", constants.DefaultDockerCRISocket, []string{"k8s_c1", "k8s_c2", "k8s_c3"}, false}, + {"invalid: remove containers using docker", constants.DefaultDockerCRISocket, []string{"k8s_c1", "k8s_c2", "k8s_c3"}, true}, } for _, tc := range cases { @@ -243,8 +247,8 @@ func TestPullImage(t *testing.T) { }{ {"valid: pull image using CRI", "unix:///var/run/crio/crio.sock", "image1", false}, {"invalid: CRI pull error", "unix:///var/run/crio/crio.sock", "image2", true}, - {"valid: pull image using docker", kubeadmapiv1beta1.DefaultCRISocket, "image1", false}, - {"invalide: docer pull error", kubeadmapiv1beta1.DefaultCRISocket, "image2", true}, + {"valid: pull image using docker", constants.DefaultDockerCRISocket, "image1", false}, + {"invalide: docer pull error", constants.DefaultDockerCRISocket, "image2", true}, } for _, tc := range cases { @@ -287,8 +291,8 @@ func TestImageExists(t *testing.T) { }{ {"valid: test if image exists using CRI", "unix:///var/run/crio/crio.sock", "image1", false}, {"invalid: CRI inspecti failure", "unix:///var/run/crio/crio.sock", "image2", true}, - {"valid: test if image exists using docker", kubeadmapiv1beta1.DefaultCRISocket, "image1", false}, - {"invalid: docker inspect failure", kubeadmapiv1beta1.DefaultCRISocket, "image2", true}, + {"valid: test if image exists using docker", constants.DefaultDockerCRISocket, "image1", false}, + {"invalid: docker inspect failure", constants.DefaultDockerCRISocket, "image2", true}, } for _, tc := range cases { @@ -305,3 +309,142 @@ func TestImageExists(t *testing.T) { }) } } + +func TestIsExistingSocket(t *testing.T) { + // this test is not expected to work on Windows + if runtime.GOOS == "windows" { + return + } + + const tempPrefix = "test.kubeadm.runtime.isExistingSocket." + tests := []struct { + name string + proc func(*testing.T) + }{ + { + name: "Valid domain socket is detected as such", + proc: func(t *testing.T) { + tmpFile, err := ioutil.TempFile("", tempPrefix) + if err != nil { + t.Fatalf("unexpected error by TempFile: %v", err) + } + theSocket := tmpFile.Name() + os.Remove(theSocket) + tmpFile.Close() + + con, err := net.Listen("unix", theSocket) + if err != nil { + t.Fatalf("unexpected error while dialing a socket: %v", err) + } + defer con.Close() + + if !isExistingSocket(theSocket) { + t.Fatalf("isExistingSocket(%q) gave unexpected result. Should have been true, instead of false", theSocket) + } + }, + }, + { + name: "Regular file is not a domain socket", + proc: func(t *testing.T) { + tmpFile, err := ioutil.TempFile("", tempPrefix) + if err != nil { + t.Fatalf("unexpected error by TempFile: %v", err) + } + theSocket := tmpFile.Name() + defer os.Remove(theSocket) + tmpFile.Close() + + if isExistingSocket(theSocket) { + t.Fatalf("isExistingSocket(%q) gave unexpected result. Should have been false, instead of true", theSocket) + } + }, + }, + { + name: "Non existent socket is not a domain socket", + proc: func(t *testing.T) { + const theSocket = "/non/existent/socket" + if isExistingSocket(theSocket) { + t.Fatalf("isExistingSocket(%q) gave unexpected result. Should have been false, instead of true", theSocket) + } + }, + }, + } + + for _, test := range tests { + t.Run(test.name, test.proc) + } +} + +func TestDetectCRISocketImpl(t *testing.T) { + tests := []struct { + name string + existingSockets []string + expectedError bool + expectedSocket string + }{ + { + name: "No existing sockets, use Docker", + existingSockets: []string{}, + expectedError: false, + expectedSocket: constants.DefaultDockerCRISocket, + }, + { + name: "One valid CRI socket leads to success", + existingSockets: []string{"/var/run/crio/crio.sock"}, + expectedError: false, + expectedSocket: "/var/run/crio/crio.sock", + }, + { + name: "Correct Docker CRI socket is returned", + existingSockets: []string{"/var/run/docker.sock"}, + expectedError: false, + expectedSocket: constants.DefaultDockerCRISocket, + }, + { + name: "CRI and Docker sockets lead to an error", + existingSockets: []string{ + "/var/run/docker.sock", + "/var/run/crio/crio.sock", + }, + expectedError: true, + }, + { + name: "Docker and containerd lead to Docker being used", + existingSockets: []string{ + "/var/run/docker.sock", + "/run/containerd/containerd.sock", + }, + expectedError: false, + expectedSocket: constants.DefaultDockerCRISocket, + }, + { + name: "A couple of CRI sockets lead to an error", + existingSockets: []string{ + "/var/run/crio/crio.sock", + "/run/containerd/containerd.sock", + }, + expectedError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + socket, err := detectCRISocketImpl(func(path string) bool { + for _, existing := range test.existingSockets { + if path == existing { + return true + } + } + + return false + }) + if (err != nil) != test.expectedError { + t.Fatalf("detectCRISocketImpl returned unexpected result\n\tExpected error: %t\n\tGot error: %t", test.expectedError, err != nil) + } + if !test.expectedError && socket != test.expectedSocket { + t.Fatalf("detectCRISocketImpl returned unexpected CRI socket\n\tExpected socket: %s\n\tReturned socket: %s", + test.expectedSocket, socket) + } + }) + } +}