diff --git a/cmd/kubectl-directpv/install.go b/cmd/kubectl-directpv/install.go index b684505b6..7321bba73 100644 --- a/cmd/kubectl-directpv/install.go +++ b/cmd/kubectl-directpv/install.go @@ -280,6 +280,11 @@ func installMain(ctx context.Context) { os.Exit(1) } + pluginVersion := "dev" + if Version != "" { + pluginVersion = Version + } + args.Registry = registry args.Org = org args.ImagePullSecrets = imagePullSecrets @@ -290,6 +295,7 @@ func installMain(ctx context.Context) { args.Quiet = quietFlag args.KubeVersion = kubeVersion args.Legacy = legacyFlag + args.PluginVersion = pluginVersion if file != nil { args.ObjectWriter = file } diff --git a/pkg/apis/directpv.min.io/types/label.go b/pkg/apis/directpv.min.io/types/label.go index c4388b5ff..43d7e24d7 100644 --- a/pkg/apis/directpv.min.io/types/label.go +++ b/pkg/apis/directpv.min.io/types/label.go @@ -88,6 +88,12 @@ const ( // ClaimIDLabelKey label key to denote the claim id of the volumes ClaimIDLabelKey LabelKey = consts.GroupName + "/claim-id" + + // ImageTagLabelKey denotes the tag of the directpv container image + ImageTagLabelKey LabelKey = consts.GroupName + "/image-tag" + + // PluginVersionLabelKey denotes the plugin version + PluginVersionLabelKey LabelKey = consts.GroupName + "/plugin-version" ) // LabelValue is a type definition for label value diff --git a/pkg/installer/args.go b/pkg/installer/args.go index fde3c5f82..31bde4590 100644 --- a/pkg/installer/args.go +++ b/pkg/installer/args.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "path" + "regexp" "github.com/minio/directpv/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -71,16 +72,25 @@ type Args struct { ObjectMarshaler func(runtime.Object) ([]byte, error) ProgressCh chan<- Message ForceUninstall bool + PluginVersion string podSecurityAdmission bool csiProvisionerImage string nodeDriverRegistrarImage string livenessProbeImage string csiResizerImage string + imageTag string } +var imageTagRegex = regexp.MustCompile(`:([^/]+)$`) + // NewArgs creates arguments for DirectPV installation. func NewArgs(image string) *Args { + imageTag := "dev" + matchIndex := imageTagRegex.FindStringSubmatchIndex(image) + if len(matchIndex) > 0 && len(image) > matchIndex[0]+1 { + imageTag = image[matchIndex[0]+1:] + } return &Args{ image: image, Registry: "quay.io", @@ -90,6 +100,7 @@ func NewArgs(image string) *Args { nodeDriverRegistrarImage: nodeDriverRegistrarImage, livenessProbeImage: livenessProbeImage, csiResizerImage: csiResizerImage, + imageTag: imageTag, } } diff --git a/pkg/installer/csidriver.go b/pkg/installer/csidriver.go index 1966417dd..ba888cddd 100644 --- a/pkg/installer/csidriver.go +++ b/pkg/installer/csidriver.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" + directpvtypes "github.com/minio/directpv/pkg/apis/directpv.min.io/types" "github.com/minio/directpv/pkg/consts" "github.com/minio/directpv/pkg/k8s" legacyclient "github.com/minio/directpv/pkg/legacy/client" @@ -90,10 +91,12 @@ func doCreateCSIDriver(ctx context.Context, args *Args, version string, legacy b Kind: "CSIDriver", }, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: name, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Spec: storagev1.CSIDriverSpec{ PodInfoOnMount: &podInfoOnMount, @@ -121,10 +124,12 @@ func doCreateCSIDriver(ctx context.Context, args *Args, version string, legacy b Kind: "CSIDriver", }, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: name, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Spec: storagev1beta1.CSIDriverSpec{ PodInfoOnMount: &podInfoOnMount, diff --git a/pkg/installer/daemonset.go b/pkg/installer/daemonset.go index 8e0677114..f3fd048a9 100644 --- a/pkg/installer/daemonset.go +++ b/pkg/installer/daemonset.go @@ -20,6 +20,7 @@ import ( "context" "fmt" + directpvtypes "github.com/minio/directpv/pkg/apis/directpv.min.io/types" "github.com/minio/directpv/pkg/consts" "github.com/minio/directpv/pkg/k8s" legacyclient "github.com/minio/directpv/pkg/legacy/client" @@ -203,12 +204,12 @@ func livenessProbeContainer(image string) corev1.Container { } } -func newDaemonset(podSpec corev1.PodSpec, name, selectorValue, appArmorProfile string) *appsv1.DaemonSet { +func newDaemonset(podSpec corev1.PodSpec, name, selectorValue string, args *Args) *appsv1.DaemonSet { annotations := map[string]string{createdByLabel: pluginName} - if appArmorProfile != "" { + if args.AppArmorProfile != "" { // AppArmor profiles need to be specified per-container for _, container := range podSpec.Containers { - annotations["container.apparmor.security.beta.kubernetes.io/"+container.Name] = "localhost/" + appArmorProfile + annotations["container.apparmor.security.beta.kubernetes.io/"+container.Name] = "localhost/" + args.AppArmorProfile } } @@ -218,10 +219,13 @@ func newDaemonset(podSpec corev1.PodSpec, name, selectorValue, appArmorProfile s Kind: "DaemonSet", }, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: name, + Namespace: namespace, + Annotations: map[string]string{ + string(directpvtypes.ImageTagLabelKey): args.imageTag, + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Spec: appsv1.DaemonSetSpec{ Selector: metav1.AddLabelToSelector(&metav1.LabelSelector{}, selectorKey, selectorValue), @@ -302,7 +306,7 @@ func doCreateDaemonset(ctx context.Context, args *Args) (err error) { selectorValue = fmt.Sprintf("%v-%v", consts.Identity, getRandSuffix()) } - daemonset := newDaemonset(podSpec, consts.NodeServerName, selectorValue, args.AppArmorProfile) + daemonset := newDaemonset(podSpec, consts.NodeServerName, selectorValue, args) if !args.DryRun && !args.Declarative { _, err = k8s.KubeClient().AppsV1().DaemonSets(namespace).Create( @@ -365,7 +369,7 @@ func doCreateLegacyDaemonset(ctx context.Context, args *Args) (err error) { selectorValue = fmt.Sprintf("%v-%v", consts.Identity, getRandSuffix()) } - daemonset := newDaemonset(podSpec, consts.LegacyNodeServerName, selectorValue, args.AppArmorProfile) + daemonset := newDaemonset(podSpec, consts.LegacyNodeServerName, selectorValue, args) if !args.DryRun && !args.Declarative { _, err = k8s.KubeClient().AppsV1().DaemonSets(namespace).Create( diff --git a/pkg/installer/deployment.go b/pkg/installer/deployment.go index af1b8aea7..2229e9c8a 100644 --- a/pkg/installer/deployment.go +++ b/pkg/installer/deployment.go @@ -20,6 +20,7 @@ import ( "context" "fmt" + directpvtypes "github.com/minio/directpv/pkg/apis/directpv.min.io/types" "github.com/minio/directpv/pkg/consts" "github.com/minio/directpv/pkg/k8s" appsv1 "k8s.io/api/apps/v1" @@ -201,10 +202,13 @@ func doCreateDeployment(ctx context.Context, args *Args, legacy bool, step int) Kind: "Deployment", }, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: name, + Namespace: namespace, + Annotations: map[string]string{ + string(directpvtypes.ImageTagLabelKey): args.imageTag, + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Spec: appsv1.DeploymentSpec{ Replicas: &replicas, diff --git a/pkg/installer/namespace.go b/pkg/installer/namespace.go index e0e81a051..feeb624dd 100644 --- a/pkg/installer/namespace.go +++ b/pkg/installer/namespace.go @@ -19,6 +19,7 @@ package installer import ( "context" + directpvtypes "github.com/minio/directpv/pkg/apis/directpv.min.io/types" "github.com/minio/directpv/pkg/k8s" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -87,11 +88,13 @@ func createNamespace(ctx context.Context, args *Args) (err error) { Kind: "Namespace", }, ObjectMeta: metav1.ObjectMeta{ - Name: namespace, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: labels, - Finalizers: []string{metav1.FinalizerDeleteDependents}, + Name: namespace, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: labels, + Finalizers: []string{metav1.FinalizerDeleteDependents}, }, } diff --git a/pkg/installer/psp.go b/pkg/installer/psp.go index 430009819..9af06d566 100644 --- a/pkg/installer/psp.go +++ b/pkg/installer/psp.go @@ -20,6 +20,7 @@ import ( "context" "errors" + directpvtypes "github.com/minio/directpv/pkg/apis/directpv.min.io/types" "github.com/minio/directpv/pkg/consts" "github.com/minio/directpv/pkg/k8s" corev1 "k8s.io/api/core/v1" @@ -87,10 +88,12 @@ func createPSPClusterRoleBinding(ctx context.Context, args *Args) (err error) { Kind: "ClusterRoleBinding", }, ObjectMeta: metav1.ObjectMeta{ - Name: pspClusterRoleBindingName, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: pspClusterRoleBindingName, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Subjects: []rbac.Subject{ { @@ -133,10 +136,12 @@ func createPodSecurityPolicy(ctx context.Context, args *Args) (err error) { Kind: "PodSecurityPolicy", }, ObjectMeta: metav1.ObjectMeta{ - Name: consts.Identity, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: consts.Identity, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Spec: policy.PodSecurityPolicySpec{ Privileged: true, diff --git a/pkg/installer/rbac.go b/pkg/installer/rbac.go index ea34ff3e9..190b653c3 100644 --- a/pkg/installer/rbac.go +++ b/pkg/installer/rbac.go @@ -19,6 +19,7 @@ package installer import ( "context" + directpvtypes "github.com/minio/directpv/pkg/apis/directpv.min.io/types" "github.com/minio/directpv/pkg/consts" "github.com/minio/directpv/pkg/k8s" corev1 "k8s.io/api/core/v1" @@ -94,10 +95,12 @@ func createServiceAccount(ctx context.Context, args *Args) (err error) { Kind: "ServiceAccount", }, ObjectMeta: metav1.ObjectMeta{ - Name: consts.Identity, - Namespace: namespace, - Annotations: map[string]string{}, - Labels: defaultLabels, + Name: consts.Identity, + Namespace: namespace, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, }, Secrets: []corev1.ObjectReference{}, ImagePullSecrets: []corev1.LocalObjectReference{}, @@ -137,6 +140,7 @@ func createClusterRole(ctx context.Context, args *Args) (err error) { Namespace: metav1.NamespaceNone, Annotations: map[string]string{ "rbac.authorization.kubernetes.io/autoupdate": "true", + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, }, Labels: defaultLabels, }, @@ -203,6 +207,7 @@ func createClusterRoleBinding(ctx context.Context, args *Args) (err error) { Namespace: metav1.NamespaceNone, Annotations: map[string]string{ "rbac.authorization.kubernetes.io/autoupdate": "true", + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, }, Labels: defaultLabels, }, @@ -253,6 +258,7 @@ func createRole(ctx context.Context, args *Args) (err error) { Namespace: namespace, Annotations: map[string]string{ "rbac.authorization.kubernetes.io/autoupdate": "true", + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, }, Labels: defaultLabels, }, @@ -294,6 +300,7 @@ func createRoleBinding(ctx context.Context, args *Args) (err error) { Namespace: namespace, Annotations: map[string]string{ "rbac.authorization.kubernetes.io/autoupdate": "true", + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, }, Labels: defaultLabels, }, diff --git a/pkg/installer/storageclass.go b/pkg/installer/storageclass.go index f69e414c4..d25bf6001 100644 --- a/pkg/installer/storageclass.go +++ b/pkg/installer/storageclass.go @@ -99,11 +99,13 @@ func doCreateStorageClass(ctx context.Context, args *Args, version string, legac storageClass := &storagev1.StorageClass{ TypeMeta: metav1.TypeMeta{APIVersion: "storage.k8s.io/v1", Kind: "StorageClass"}, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: defaultLabels, - Finalizers: []string{metav1.FinalizerDeleteDependents}, + Name: name, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, + Finalizers: []string{metav1.FinalizerDeleteDependents}, }, Provisioner: consts.Identity, AllowVolumeExpansion: &allowExpansion, @@ -131,11 +133,13 @@ func doCreateStorageClass(ctx context.Context, args *Args, version string, legac storageClass := &storagev1beta1.StorageClass{ TypeMeta: metav1.TypeMeta{APIVersion: "storage.k8s.io/v1beta1", Kind: "StorageClass"}, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: metav1.NamespaceNone, - Annotations: map[string]string{}, - Labels: defaultLabels, - Finalizers: []string{metav1.FinalizerDeleteDependents}, + Name: name, + Namespace: metav1.NamespaceNone, + Annotations: map[string]string{ + string(directpvtypes.PluginVersionLabelKey): args.PluginVersion, + }, + Labels: defaultLabels, + Finalizers: []string{metav1.FinalizerDeleteDependents}, }, Provisioner: consts.Identity, AllowVolumeExpansion: &allowExpansion,