Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
177 changes: 170 additions & 7 deletions pkg/apis/deployment/v1/server_group_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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 {
Expand Down Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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),
},
}
}
Expand Down Expand Up @@ -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
}
37 changes: 37 additions & 0 deletions pkg/apis/deployment/v1/server_group_volume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
47 changes: 47 additions & 0 deletions pkg/apis/deployment/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pkg/apis/deployment/v2alpha1/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ const (
// Rebalancer
ActionTypeRebalancerGenerate ActionType = "RebalancerGenerate"
ActionTypeRebalancerCheck ActionType = "RebalancerCheck"

// Resources
ActionTypeResourceSync ActionType = "ResourceSync"
)

const (
Expand Down
Loading