diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f948e95f..caba253c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - (Feature) Add agency leader discovery - (Feature) Add `ACSDeploymentSynced` condition type and fix comparison of `SecretHashes` method - (Feature) Add agency leader service +- (Feature) Add HostPath and PVC Volume types and allow templating ## [1.2.12](https://github.com/arangodb/kube-arangodb/tree/1.2.12) (2022-05-10) - (Feature) Add CoreV1 Endpoints Inspector diff --git a/pkg/apis/deployment/v1/server_group_volume.go b/pkg/apis/deployment/v1/server_group_volume.go index 16ce7ff0e..8f7f143ef 100644 --- a/pkg/apis/deployment/v1/server_group_volume.go +++ b/pkg/apis/deployment/v1/server_group_volume.go @@ -29,6 +29,7 @@ import ( sharedv1 "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1" core "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( @@ -44,6 +45,14 @@ var ( } ) +const ( + ServerGroupSpecVolumeRenderParamDeploymentName = "DEPLOYMENT_NAME" + ServerGroupSpecVolumeRenderParamDeploymentNamespace = "DEPLOYMENT_NAMESPACE" + ServerGroupSpecVolumeRenderParamMemberID = "MEMBER_ID" + ServerGroupSpecVolumeRenderParamMemberRoleAbbr = "ROLE_ABBR" + ServerGroupSpecVolumeRenderParamMemberRole = "ROLE" +) + // IsRestrictedVolumeName check of volume name is restricted, for example for originally mounted volumes func IsRestrictedVolumeName(name string) bool { for _, restrictedVolumeName := range restrictedVolumeNames { @@ -91,6 +100,17 @@ func (s ServerGroupSpecVolumes) Validate() error { return shared.WithErrors(validationErrors...) } +// RenderVolumes render volumes +func (s ServerGroupSpecVolumes) RenderVolumes(depl meta.Object, group ServerGroup, member MemberStatus) []core.Volume { + volumes := make([]core.Volume, len(s)) + + for id, volume := range s { + volumes[id] = volume.RenderVolume(depl, group, member) + } + + return volumes +} + // Volumes create volumes func (s ServerGroupSpecVolumes) Volumes() []core.Volume { volumes := make([]core.Volume, len(s)) @@ -115,6 +135,12 @@ type ServerGroupSpecVolume struct { // EmptyDir EmptyDir *ServerGroupSpecVolumeEmptyDir `json:"emptyDir,omitempty"` + + // HostPath + HostPath *ServerGroupSpecVolumeHostPath `json:"hostPath,omitempty"` + + // PersistentVolumeClaim + PersistentVolumeClaim *ServerGroupSpecVolumePersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"` } // Validate if ServerGroupSpec volume is valid @@ -128,18 +154,36 @@ func (s *ServerGroupSpecVolume) Validate() error { shared.PrefixResourceErrors("secret", s.Secret.Validate()), shared.PrefixResourceErrors("configMap", s.ConfigMap.Validate()), shared.PrefixResourceErrors("emptyDir", s.EmptyDir.Validate()), + shared.PrefixResourceErrors("hostPath", s.HostPath.Validate()), + shared.PrefixResourceErrors("persistentVolumeClaim", s.PersistentVolumeClaim.Validate()), s.validate(), ) } +// RenderVolume create Pod Volume object with dynamic names +func (s ServerGroupSpecVolume) RenderVolume(depl meta.Object, group ServerGroup, member MemberStatus) core.Volume { + return core.Volume{ + Name: s.Name, + VolumeSource: core.VolumeSource{ + ConfigMap: s.ConfigMap.render(depl, group, member), + Secret: s.Secret.render(depl, group, member), + EmptyDir: s.EmptyDir.render(), + HostPath: s.HostPath.render(depl, group, member), + PersistentVolumeClaim: s.PersistentVolumeClaim.render(depl, group, member), + }, + } +} + // Volume create Pod Volume object func (s ServerGroupSpecVolume) Volume() core.Volume { return core.Volume{ Name: s.Name, VolumeSource: core.VolumeSource{ - ConfigMap: (*core.ConfigMapVolumeSource)(s.ConfigMap), - Secret: (*core.SecretVolumeSource)(s.Secret), - EmptyDir: (*core.EmptyDirVolumeSource)(s.EmptyDir), + ConfigMap: (*core.ConfigMapVolumeSource)(s.ConfigMap), + Secret: (*core.SecretVolumeSource)(s.Secret), + EmptyDir: (*core.EmptyDirVolumeSource)(s.EmptyDir), + HostPath: (*core.HostPathVolumeSource)(s.HostPath), + PersistentVolumeClaim: (*core.PersistentVolumeClaimVolumeSource)(s.PersistentVolumeClaim), }, } } @@ -173,35 +217,154 @@ func (s *ServerGroupSpecVolume) notNilFields() int { i++ } + if s.HostPath != nil { + i++ + } + + if s.PersistentVolumeClaim != nil { + i++ + } + return i } +func renderVolumeResourceName(in string, depl meta.Object, group ServerGroup, member MemberStatus) string { + return shared.RenderResourceName(in, map[string]string{ + ServerGroupSpecVolumeRenderParamDeploymentName: depl.GetName(), + ServerGroupSpecVolumeRenderParamDeploymentNamespace: depl.GetNamespace(), + ServerGroupSpecVolumeRenderParamMemberID: shared.StripArangodPrefix(member.ID), + ServerGroupSpecVolumeRenderParamMemberRole: group.AsRole(), + ServerGroupSpecVolumeRenderParamMemberRoleAbbr: group.AsRoleAbbreviated(), + }) +} + type ServerGroupSpecVolumeSecret core.SecretVolumeSource func (s *ServerGroupSpecVolumeSecret) Validate() error { - if s == nil { + q := s.render(&ArangoDeployment{ + ObjectMeta: meta.ObjectMeta{ + Name: "render", + Namespace: "render", + }, + }, ServerGroupSingle, MemberStatus{ + ID: "render", + }) + + if q == nil { return nil } return shared.WithErrors( - shared.PrefixResourceError("secretName", sharedv1.AsKubernetesResourceName(&s.SecretName).Validate()), + shared.PrefixResourceError("secretName", sharedv1.AsKubernetesResourceName(&q.SecretName).Validate()), ) } +func (s *ServerGroupSpecVolumeSecret) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.SecretVolumeSource { + if s == nil { + return nil + } + + var obj = core.SecretVolumeSource(*s) + + obj.SecretName = renderVolumeResourceName(obj.SecretName, depl, group, member) + + return &obj +} + type ServerGroupSpecVolumeConfigMap core.ConfigMapVolumeSource func (s *ServerGroupSpecVolumeConfigMap) Validate() error { - if s == nil { + q := s.render(&ArangoDeployment{ + ObjectMeta: meta.ObjectMeta{ + Name: "render", + Namespace: "render", + }, + }, ServerGroupSingle, MemberStatus{ + ID: "render", + }) + + if q == nil { return nil } return shared.WithErrors( - shared.PrefixResourceError("name", sharedv1.AsKubernetesResourceName(&s.Name).Validate()), + shared.PrefixResourceError("name", sharedv1.AsKubernetesResourceName(&q.Name).Validate()), ) } +func (s *ServerGroupSpecVolumeConfigMap) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.ConfigMapVolumeSource { + if s == nil { + return nil + } + + var obj = core.ConfigMapVolumeSource(*s) + + obj.Name = renderVolumeResourceName(obj.Name, depl, group, member) + + return &obj +} + type ServerGroupSpecVolumeEmptyDir core.EmptyDirVolumeSource func (s *ServerGroupSpecVolumeEmptyDir) Validate() error { return nil } + +func (s *ServerGroupSpecVolumeEmptyDir) render() *core.EmptyDirVolumeSource { + if s == nil { + return nil + } + + return (*core.EmptyDirVolumeSource)(s) +} + +type ServerGroupSpecVolumeHostPath core.HostPathVolumeSource + +func (s *ServerGroupSpecVolumeHostPath) Validate() error { + return nil +} + +func (s *ServerGroupSpecVolumeHostPath) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.HostPathVolumeSource { + if s == nil { + return nil + } + + var obj = core.HostPathVolumeSource(*s) + + obj.Path = renderVolumeResourceName(obj.Path, depl, group, member) + + return &obj +} + +type ServerGroupSpecVolumePersistentVolumeClaim core.PersistentVolumeClaimVolumeSource + +func (s *ServerGroupSpecVolumePersistentVolumeClaim) Validate() error { + q := s.render(&ArangoDeployment{ + ObjectMeta: meta.ObjectMeta{ + Name: "render", + Namespace: "render", + }, + }, ServerGroupSingle, MemberStatus{ + ID: "render", + }) + + if q == nil { + return nil + } + + return shared.WithErrors( + shared.PrefixResourceError("claimName", sharedv1.AsKubernetesResourceName(&q.ClaimName).Validate()), + ) +} + +func (s *ServerGroupSpecVolumePersistentVolumeClaim) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.PersistentVolumeClaimVolumeSource { + if s == nil { + return nil + } + + var obj = core.PersistentVolumeClaimVolumeSource(*s) + + obj.ClaimName = renderVolumeResourceName(obj.ClaimName, depl, group, member) + + return &obj +} diff --git a/pkg/apis/deployment/v1/server_group_volume_test.go b/pkg/apis/deployment/v1/server_group_volume_test.go index c2395ed4e..d64472c92 100644 --- a/pkg/apis/deployment/v1/server_group_volume_test.go +++ b/pkg/apis/deployment/v1/server_group_volume_test.go @@ -146,6 +146,43 @@ func Test_Volume_Validation(t *testing.T) { }, }, }, + { + name: "Templating", + volumes: []ServerGroupSpecVolume{ + { + Name: validName, + Secret: &ServerGroupSpecVolumeSecret{ + SecretName: fmt.Sprintf("${%s}-secret", ServerGroupSpecVolumeRenderParamDeploymentName), + }, + }, + }, + }, + { + name: "Invalid templating", + volumes: []ServerGroupSpecVolume{ + { + Name: validName, + Secret: &ServerGroupSpecVolumeSecret{ + SecretName: fmt.Sprintf("${%sRANDOM}-secret", ServerGroupSpecVolumeRenderParamDeploymentName), + }, + }, + }, + fail: true, + failedFields: map[string]string{ + "0.secret.secretName": labelValidationError, + }, + }, + { + name: "Templating with group name", + volumes: []ServerGroupSpecVolume{ + { + Name: validName, + Secret: &ServerGroupSpecVolumeSecret{ + SecretName: fmt.Sprintf("${%s}-${%s}-${%s}-cache", ServerGroupSpecVolumeRenderParamDeploymentName, ServerGroupSpecVolumeRenderParamMemberRole, ServerGroupSpecVolumeRenderParamMemberID), + }, + }, + }, + }, } for _, c := range cases { diff --git a/pkg/apis/deployment/v1/zz_generated.deepcopy.go b/pkg/apis/deployment/v1/zz_generated.deepcopy.go index 0920eaccb..de901a5ae 100644 --- a/pkg/apis/deployment/v1/zz_generated.deepcopy.go +++ b/pkg/apis/deployment/v1/zz_generated.deepcopy.go @@ -2430,6 +2430,16 @@ func (in *ServerGroupSpecVolume) DeepCopyInto(out *ServerGroupSpecVolume) { *out = new(ServerGroupSpecVolumeEmptyDir) (*in).DeepCopyInto(*out) } + if in.HostPath != nil { + in, out := &in.HostPath, &out.HostPath + *out = new(ServerGroupSpecVolumeHostPath) + (*in).DeepCopyInto(*out) + } + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(ServerGroupSpecVolumePersistentVolumeClaim) + **out = **in + } return } @@ -2498,6 +2508,27 @@ func (in *ServerGroupSpecVolumeEmptyDir) DeepCopy() *ServerGroupSpecVolumeEmptyD return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerGroupSpecVolumeHostPath) DeepCopyInto(out *ServerGroupSpecVolumeHostPath) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(corev1.HostPathType) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupSpecVolumeHostPath. +func (in *ServerGroupSpecVolumeHostPath) DeepCopy() *ServerGroupSpecVolumeHostPath { + if in == nil { + return nil + } + out := new(ServerGroupSpecVolumeHostPath) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerGroupSpecVolumeMount) DeepCopyInto(out *ServerGroupSpecVolumeMount) { *out = *in @@ -2541,6 +2572,22 @@ func (in ServerGroupSpecVolumeMounts) DeepCopy() ServerGroupSpecVolumeMounts { return *out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerGroupSpecVolumePersistentVolumeClaim) DeepCopyInto(out *ServerGroupSpecVolumePersistentVolumeClaim) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupSpecVolumePersistentVolumeClaim. +func (in *ServerGroupSpecVolumePersistentVolumeClaim) DeepCopy() *ServerGroupSpecVolumePersistentVolumeClaim { + if in == nil { + return nil + } + out := new(ServerGroupSpecVolumePersistentVolumeClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerGroupSpecVolumeSecret) DeepCopyInto(out *ServerGroupSpecVolumeSecret) { *out = *in diff --git a/pkg/apis/deployment/v2alpha1/plan.go b/pkg/apis/deployment/v2alpha1/plan.go index 215513dd4..e755ad663 100644 --- a/pkg/apis/deployment/v2alpha1/plan.go +++ b/pkg/apis/deployment/v2alpha1/plan.go @@ -192,6 +192,9 @@ const ( // Rebalancer ActionTypeRebalancerGenerate ActionType = "RebalancerGenerate" ActionTypeRebalancerCheck ActionType = "RebalancerCheck" + + // Resources + ActionTypeResourceSync ActionType = "ResourceSync" ) const ( diff --git a/pkg/apis/deployment/v2alpha1/server_group_volume.go b/pkg/apis/deployment/v2alpha1/server_group_volume.go index b7abab579..af27f1a36 100644 --- a/pkg/apis/deployment/v2alpha1/server_group_volume.go +++ b/pkg/apis/deployment/v2alpha1/server_group_volume.go @@ -29,6 +29,7 @@ import ( sharedv1 "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1" core "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( @@ -44,6 +45,14 @@ var ( } ) +const ( + ServerGroupSpecVolumeRenderParamDeploymentName = "DEPLOYMENT_NAME" + ServerGroupSpecVolumeRenderParamDeploymentNamespace = "DEPLOYMENT_NAMESPACE" + ServerGroupSpecVolumeRenderParamMemberID = "MEMBER_ID" + ServerGroupSpecVolumeRenderParamMemberRoleAbbr = "ROLE_ABBR" + ServerGroupSpecVolumeRenderParamMemberRole = "ROLE" +) + // IsRestrictedVolumeName check of volume name is restricted, for example for originally mounted volumes func IsRestrictedVolumeName(name string) bool { for _, restrictedVolumeName := range restrictedVolumeNames { @@ -91,6 +100,17 @@ func (s ServerGroupSpecVolumes) Validate() error { return shared.WithErrors(validationErrors...) } +// RenderVolumes render volumes +func (s ServerGroupSpecVolumes) RenderVolumes(depl meta.Object, group ServerGroup, member MemberStatus) []core.Volume { + volumes := make([]core.Volume, len(s)) + + for id, volume := range s { + volumes[id] = volume.RenderVolume(depl, group, member) + } + + return volumes +} + // Volumes create volumes func (s ServerGroupSpecVolumes) Volumes() []core.Volume { volumes := make([]core.Volume, len(s)) @@ -115,6 +135,12 @@ type ServerGroupSpecVolume struct { // EmptyDir EmptyDir *ServerGroupSpecVolumeEmptyDir `json:"emptyDir,omitempty"` + + // HostPath + HostPath *ServerGroupSpecVolumeHostPath `json:"hostPath,omitempty"` + + // PersistentVolumeClaim + PersistentVolumeClaim *ServerGroupSpecVolumePersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"` } // Validate if ServerGroupSpec volume is valid @@ -128,18 +154,36 @@ func (s *ServerGroupSpecVolume) Validate() error { shared.PrefixResourceErrors("secret", s.Secret.Validate()), shared.PrefixResourceErrors("configMap", s.ConfigMap.Validate()), shared.PrefixResourceErrors("emptyDir", s.EmptyDir.Validate()), + shared.PrefixResourceErrors("hostPath", s.HostPath.Validate()), + shared.PrefixResourceErrors("persistentVolumeClaim", s.PersistentVolumeClaim.Validate()), s.validate(), ) } +// RenderVolume create Pod Volume object with dynamic names +func (s ServerGroupSpecVolume) RenderVolume(depl meta.Object, group ServerGroup, member MemberStatus) core.Volume { + return core.Volume{ + Name: s.Name, + VolumeSource: core.VolumeSource{ + ConfigMap: s.ConfigMap.render(depl, group, member), + Secret: s.Secret.render(depl, group, member), + EmptyDir: s.EmptyDir.render(), + HostPath: s.HostPath.render(depl, group, member), + PersistentVolumeClaim: s.PersistentVolumeClaim.render(depl, group, member), + }, + } +} + // Volume create Pod Volume object func (s ServerGroupSpecVolume) Volume() core.Volume { return core.Volume{ Name: s.Name, VolumeSource: core.VolumeSource{ - ConfigMap: (*core.ConfigMapVolumeSource)(s.ConfigMap), - Secret: (*core.SecretVolumeSource)(s.Secret), - EmptyDir: (*core.EmptyDirVolumeSource)(s.EmptyDir), + ConfigMap: (*core.ConfigMapVolumeSource)(s.ConfigMap), + Secret: (*core.SecretVolumeSource)(s.Secret), + EmptyDir: (*core.EmptyDirVolumeSource)(s.EmptyDir), + HostPath: (*core.HostPathVolumeSource)(s.HostPath), + PersistentVolumeClaim: (*core.PersistentVolumeClaimVolumeSource)(s.PersistentVolumeClaim), }, } } @@ -173,35 +217,154 @@ func (s *ServerGroupSpecVolume) notNilFields() int { i++ } + if s.HostPath != nil { + i++ + } + + if s.PersistentVolumeClaim != nil { + i++ + } + return i } +func renderVolumeResourceName(in string, depl meta.Object, group ServerGroup, member MemberStatus) string { + return shared.RenderResourceName(in, map[string]string{ + ServerGroupSpecVolumeRenderParamDeploymentName: depl.GetName(), + ServerGroupSpecVolumeRenderParamDeploymentNamespace: depl.GetNamespace(), + ServerGroupSpecVolumeRenderParamMemberID: shared.StripArangodPrefix(member.ID), + ServerGroupSpecVolumeRenderParamMemberRole: group.AsRole(), + ServerGroupSpecVolumeRenderParamMemberRoleAbbr: group.AsRoleAbbreviated(), + }) +} + type ServerGroupSpecVolumeSecret core.SecretVolumeSource func (s *ServerGroupSpecVolumeSecret) Validate() error { - if s == nil { + q := s.render(&ArangoDeployment{ + ObjectMeta: meta.ObjectMeta{ + Name: "render", + Namespace: "render", + }, + }, ServerGroupSingle, MemberStatus{ + ID: "render", + }) + + if q == nil { return nil } return shared.WithErrors( - shared.PrefixResourceError("secretName", sharedv1.AsKubernetesResourceName(&s.SecretName).Validate()), + shared.PrefixResourceError("secretName", sharedv1.AsKubernetesResourceName(&q.SecretName).Validate()), ) } +func (s *ServerGroupSpecVolumeSecret) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.SecretVolumeSource { + if s == nil { + return nil + } + + var obj = core.SecretVolumeSource(*s) + + obj.SecretName = renderVolumeResourceName(obj.SecretName, depl, group, member) + + return &obj +} + type ServerGroupSpecVolumeConfigMap core.ConfigMapVolumeSource func (s *ServerGroupSpecVolumeConfigMap) Validate() error { - if s == nil { + q := s.render(&ArangoDeployment{ + ObjectMeta: meta.ObjectMeta{ + Name: "render", + Namespace: "render", + }, + }, ServerGroupSingle, MemberStatus{ + ID: "render", + }) + + if q == nil { return nil } return shared.WithErrors( - shared.PrefixResourceError("name", sharedv1.AsKubernetesResourceName(&s.Name).Validate()), + shared.PrefixResourceError("name", sharedv1.AsKubernetesResourceName(&q.Name).Validate()), ) } +func (s *ServerGroupSpecVolumeConfigMap) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.ConfigMapVolumeSource { + if s == nil { + return nil + } + + var obj = core.ConfigMapVolumeSource(*s) + + obj.Name = renderVolumeResourceName(obj.Name, depl, group, member) + + return &obj +} + type ServerGroupSpecVolumeEmptyDir core.EmptyDirVolumeSource func (s *ServerGroupSpecVolumeEmptyDir) Validate() error { return nil } + +func (s *ServerGroupSpecVolumeEmptyDir) render() *core.EmptyDirVolumeSource { + if s == nil { + return nil + } + + return (*core.EmptyDirVolumeSource)(s) +} + +type ServerGroupSpecVolumeHostPath core.HostPathVolumeSource + +func (s *ServerGroupSpecVolumeHostPath) Validate() error { + return nil +} + +func (s *ServerGroupSpecVolumeHostPath) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.HostPathVolumeSource { + if s == nil { + return nil + } + + var obj = core.HostPathVolumeSource(*s) + + obj.Path = renderVolumeResourceName(obj.Path, depl, group, member) + + return &obj +} + +type ServerGroupSpecVolumePersistentVolumeClaim core.PersistentVolumeClaimVolumeSource + +func (s *ServerGroupSpecVolumePersistentVolumeClaim) Validate() error { + q := s.render(&ArangoDeployment{ + ObjectMeta: meta.ObjectMeta{ + Name: "render", + Namespace: "render", + }, + }, ServerGroupSingle, MemberStatus{ + ID: "render", + }) + + if q == nil { + return nil + } + + return shared.WithErrors( + shared.PrefixResourceError("claimName", sharedv1.AsKubernetesResourceName(&q.ClaimName).Validate()), + ) +} + +func (s *ServerGroupSpecVolumePersistentVolumeClaim) render(depl meta.Object, group ServerGroup, member MemberStatus) *core.PersistentVolumeClaimVolumeSource { + if s == nil { + return nil + } + + var obj = core.PersistentVolumeClaimVolumeSource(*s) + + obj.ClaimName = renderVolumeResourceName(obj.ClaimName, depl, group, member) + + return &obj +} diff --git a/pkg/apis/deployment/v2alpha1/server_group_volume_test.go b/pkg/apis/deployment/v2alpha1/server_group_volume_test.go index e2d82b7cd..f08a75f1b 100644 --- a/pkg/apis/deployment/v2alpha1/server_group_volume_test.go +++ b/pkg/apis/deployment/v2alpha1/server_group_volume_test.go @@ -146,6 +146,43 @@ func Test_Volume_Validation(t *testing.T) { }, }, }, + { + name: "Templating", + volumes: []ServerGroupSpecVolume{ + { + Name: validName, + Secret: &ServerGroupSpecVolumeSecret{ + SecretName: fmt.Sprintf("${%s}-secret", ServerGroupSpecVolumeRenderParamDeploymentName), + }, + }, + }, + }, + { + name: "Invalid templating", + volumes: []ServerGroupSpecVolume{ + { + Name: validName, + Secret: &ServerGroupSpecVolumeSecret{ + SecretName: fmt.Sprintf("${%sRANDOM}-secret", ServerGroupSpecVolumeRenderParamDeploymentName), + }, + }, + }, + fail: true, + failedFields: map[string]string{ + "0.secret.secretName": labelValidationError, + }, + }, + { + name: "Templating with group name", + volumes: []ServerGroupSpecVolume{ + { + Name: validName, + Secret: &ServerGroupSpecVolumeSecret{ + SecretName: fmt.Sprintf("${%s}-${%s}-${%s}-cache", ServerGroupSpecVolumeRenderParamDeploymentName, ServerGroupSpecVolumeRenderParamMemberRole, ServerGroupSpecVolumeRenderParamMemberID), + }, + }, + }, + }, } for _, c := range cases { diff --git a/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go b/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go index 582762d6d..e2ac79bf7 100644 --- a/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go @@ -2430,6 +2430,16 @@ func (in *ServerGroupSpecVolume) DeepCopyInto(out *ServerGroupSpecVolume) { *out = new(ServerGroupSpecVolumeEmptyDir) (*in).DeepCopyInto(*out) } + if in.HostPath != nil { + in, out := &in.HostPath, &out.HostPath + *out = new(ServerGroupSpecVolumeHostPath) + (*in).DeepCopyInto(*out) + } + if in.PersistentVolumeClaim != nil { + in, out := &in.PersistentVolumeClaim, &out.PersistentVolumeClaim + *out = new(ServerGroupSpecVolumePersistentVolumeClaim) + **out = **in + } return } @@ -2498,6 +2508,27 @@ func (in *ServerGroupSpecVolumeEmptyDir) DeepCopy() *ServerGroupSpecVolumeEmptyD return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerGroupSpecVolumeHostPath) DeepCopyInto(out *ServerGroupSpecVolumeHostPath) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(v1.HostPathType) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupSpecVolumeHostPath. +func (in *ServerGroupSpecVolumeHostPath) DeepCopy() *ServerGroupSpecVolumeHostPath { + if in == nil { + return nil + } + out := new(ServerGroupSpecVolumeHostPath) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerGroupSpecVolumeMount) DeepCopyInto(out *ServerGroupSpecVolumeMount) { *out = *in @@ -2541,6 +2572,22 @@ func (in ServerGroupSpecVolumeMounts) DeepCopy() ServerGroupSpecVolumeMounts { return *out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerGroupSpecVolumePersistentVolumeClaim) DeepCopyInto(out *ServerGroupSpecVolumePersistentVolumeClaim) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerGroupSpecVolumePersistentVolumeClaim. +func (in *ServerGroupSpecVolumePersistentVolumeClaim) DeepCopy() *ServerGroupSpecVolumePersistentVolumeClaim { + if in == nil { + return nil + } + out := new(ServerGroupSpecVolumePersistentVolumeClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerGroupSpecVolumeSecret) DeepCopyInto(out *ServerGroupSpecVolumeSecret) { *out = *in diff --git a/pkg/apis/shared/names.go b/pkg/apis/shared/names.go index 7d9837429..127da2230 100644 --- a/pkg/apis/shared/names.go +++ b/pkg/apis/shared/names.go @@ -31,8 +31,8 @@ var ( arangodPrefixes = []string{"CRDN-", "PRMR-", "AGNT-", "SNGL-"} ) -// stripArangodPrefix removes well know arangod ID prefixes from the given id. -func stripArangodPrefix(id string) string { +// StripArangodPrefix removes well know arangod ID prefixes from the given id. +func StripArangodPrefix(id string) string { for _, prefix := range arangodPrefixes { if strings.HasPrefix(id, prefix) { return id[len(prefix):] @@ -75,11 +75,19 @@ func FixupResourceName(name string) string { // CreatePodHostName returns the hostname of the pod for a member with // a given id in a deployment with a given name. func CreatePodHostName(deploymentName, role, id string) string { - return deploymentName + "-" + role + "-" + stripArangodPrefix(id) + return deploymentName + "-" + role + "-" + StripArangodPrefix(id) } // CreatePersistentVolumeClaimName returns the name of the persistent volume claim for a member with // a given id in a deployment with a given name. func CreatePersistentVolumeClaimName(deploymentName, role, id string) string { - return deploymentName + "-" + role + "-" + stripArangodPrefix(id) + return deploymentName + "-" + role + "-" + StripArangodPrefix(id) +} + +func RenderResourceName(in string, keys map[string]string) string { + for k, v := range keys { + in = strings.ReplaceAll(in, fmt.Sprintf("${%s}", k), v) + } + + return in } diff --git a/pkg/deployment/resources/pod_creator_arangod.go b/pkg/deployment/resources/pod_creator_arangod.go index 424baf521..bcc735197 100644 --- a/pkg/deployment/resources/pod_creator_arangod.go +++ b/pkg/deployment/resources/pod_creator_arangod.go @@ -589,7 +589,7 @@ func CreateArangoDVolumes(status api.MemberStatus, input pod.Input, spec api.Dep volumes.Append(pod.SNI(), input) if len(groupSpec.Volumes) > 0 { - volumes.AddVolume(groupSpec.Volumes.Volumes()...) + volumes.AddVolume(groupSpec.Volumes.RenderVolumes(input.ApiObject, input.Group, status)...) } if len(groupSpec.VolumeMounts) > 0 {