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 configs/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ base: &base
cert_manager_cluster_issuer: ${CERT_MANAGER_CLUSTER_ISSUER:-}
sandbox_enabled: ${SANDBOX_ENABLED}
ingress_default_port: 443
pvc_storage_class_name: uffizzi-standard
service_checks:
ip_ping_timeout: 1800s
availability_timeout: 1800s
Expand Down
129 changes: 108 additions & 21 deletions internal/clients/kuber/deployment_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,63 @@ func prepareContainerSecrets(container domainTypes.Container, secret *corev1.Sec

func prepareDeploymentVolumes(containerList domainTypes.ContainerList) []corev1.Volume {
volumes := []corev1.Volume{}
configFileVolumes := prepareDeploymentConfigFileVolumes(containerList)
volumes = append(volumes, configFileVolumes...)
pvcVolumes := prepareDeploymentPvcVolumes(containerList)
volumes = append(volumes, pvcVolumes...)

return volumes
}

func prepareContainerVolumeMounts(container domainTypes.Container) []corev1.VolumeMount {
volumeMounts := []corev1.VolumeMount{}
configVolumeMounts := prepareContainerConfigFileVolumeMounts(container)
volumeMounts = append(volumeMounts, configVolumeMounts...)

namedVolumeMounts := prepareContainerNamedVolumeMounts(container)
volumeMounts = append(volumeMounts, namedVolumeMounts...)

anonymousVolumeMounts := prepareContainerAnonymousVolumeMounts(container)
volumeMounts = append(volumeMounts, anonymousVolumeMounts...)

return volumeMounts
}

func prepareConfigFileMountPath(containerConfigFile *domainTypes.ContainerConfigFile) (string, string) {
mountPath := containerConfigFile.MountPath

if len(mountPath) == 0 {
mountPath = "/"
}

if mountPath[0] != '/' {
mountPath = fmt.Sprintf("/%v", containerConfigFile.MountPath)
}

if mountPath == "/" {
mountPath = fmt.Sprintf("/%v", containerConfigFile.ConfigFile.Filename)
}

mountPathParts := strings.Split(mountPath, "/")
mountFileName := mountPathParts[len(mountPathParts)-1]

return mountPath, mountFileName
}

func prepareCredentialsDeployment(credentials []domainTypes.Credential) []corev1.LocalObjectReference {
references := []corev1.LocalObjectReference{}

for _, credential := range credentials {
credentialName := global.Settings.ResourceName.Credential(credential.ID)

references = append(references, corev1.LocalObjectReference{Name: credentialName})
}

return references
}

func prepareDeploymentConfigFileVolumes(containerList domainTypes.ContainerList) []corev1.Volume {
volumes := []corev1.Volume{}

for _, container := range containerList.Items {
for _, containerConfigFile := range container.ContainerConfigFiles {
Expand Down Expand Up @@ -93,7 +150,28 @@ func prepareDeploymentVolumes(containerList domainTypes.ContainerList) []corev1.
return volumes
}

func prepareContainerVolumeMounts(container domainTypes.Container) []corev1.VolumeMount {
func prepareDeploymentPvcVolumes(containerList domainTypes.ContainerList) []corev1.Volume {
volumes := []corev1.Volume{}
pvcVolumes := containerList.GetUniqNamedVolumes()
pvcVolumes = append(pvcVolumes, containerList.GetUniqAnonymousVolumes()...)

for _, pvcVolume := range pvcVolumes {
volume := corev1.Volume{
Name: global.Settings.ResourceName.VolumeName(pvcVolume.UniqName),
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: global.Settings.ResourceName.PvcName(pvcVolume.UniqName),
},
},
}

volumes = append(volumes, volume)
}

return volumes
}

func prepareContainerConfigFileVolumeMounts(container domainTypes.Container) []corev1.VolumeMount {
volumeMounts := []corev1.VolumeMount{}

for _, containerConfigFile := range container.ContainerConfigFiles {
Expand All @@ -116,37 +194,46 @@ func prepareContainerVolumeMounts(container domainTypes.Container) []corev1.Volu
return volumeMounts
}

func prepareConfigFileMountPath(containerConfigFile *domainTypes.ContainerConfigFile) (string, string) {
mountPath := containerConfigFile.MountPath
func prepareContainerNamedVolumeMounts(container domainTypes.Container) []corev1.VolumeMount {
volumeMounts := []corev1.VolumeMount{}

if len(mountPath) == 0 {
mountPath = "/"
}
for _, containerVolume := range container.ContainerVolumes {
if !containerVolume.IsNamedType() {
continue
}

if mountPath[0] != '/' {
mountPath = fmt.Sprintf("/%v", containerConfigFile.MountPath)
}
name := containerVolume.BuildUniqName(&container)
volumeMount := corev1.VolumeMount{
Name: global.Settings.ResourceName.VolumeName(name),
MountPath: containerVolume.Target,
ReadOnly: containerVolume.ReadOnly,
}

if mountPath == "/" {
mountPath = fmt.Sprintf("/%v", containerConfigFile.ConfigFile.Filename)
volumeMounts = append(volumeMounts, volumeMount)
}

mountPathParts := strings.Split(mountPath, "/")
mountFileName := mountPathParts[len(mountPathParts)-1]

return mountPath, mountFileName
return volumeMounts
}

func prepareCredentialsDeployment(credentials []domainTypes.Credential) []corev1.LocalObjectReference {
references := []corev1.LocalObjectReference{}
func prepareContainerAnonymousVolumeMounts(container domainTypes.Container) []corev1.VolumeMount {
volumeMounts := []corev1.VolumeMount{}

for _, credential := range credentials {
credentialName := global.Settings.ResourceName.Credential(credential.ID)
for _, containerVolume := range container.ContainerVolumes {
if !containerVolume.IsAnonymousType() {
continue
}

references = append(references, corev1.LocalObjectReference{Name: credentialName})
name := containerVolume.BuildUniqName(&container)
volumeMount := corev1.VolumeMount{
Name: global.Settings.ResourceName.VolumeName(name),
MountPath: containerVolume.Source,
ReadOnly: containerVolume.ReadOnly,
}

volumeMounts = append(volumeMounts, volumeMount)
}

return references
return volumeMounts
}

func prepareContainerHealthcheck(container domainTypes.Container) *corev1.Probe {
Expand Down
97 changes: 97 additions & 0 deletions internal/clients/kuber/persistent_volume_claim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package kuber

import (
"fmt"

"gitlab.com/dualbootpartners/idyl/uffizzi_controller/internal/global"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (client Client) FindOrInitializePersistentVolumeClaim(
namespace, name string) (*corev1.PersistentVolumeClaim, error) {
persistentVolumeClaim, err := client.GetPersistentVolumeClaim(namespace, name)
if err != nil && !errors.IsNotFound(err) {
return persistentVolumeClaim, err
}

if persistentVolumeClaim != nil && len(persistentVolumeClaim.UID) > 0 {
return persistentVolumeClaim, nil
}

var storageClassName string = global.Settings.PvcStorageClassName

persistentVolumeClaimDraft := &corev1.PersistentVolumeClaim{
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &storageClassName,
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse("1Gi"),
},
},
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{
"app.kubernetes.io/managed-by": global.Settings.ManagedApplication,
},
},
}

return persistentVolumeClaimDraft, nil
}

func (client *Client) GetPersistentVolumeClaim(namespace, name string) (*corev1.PersistentVolumeClaim, error) {
persistentVolumeClaimClient := client.clientset.CoreV1().PersistentVolumeClaims(namespace)

persistentVolumeClaim, err := persistentVolumeClaimClient.Get(client.context, name, metav1.GetOptions{})
if err != nil {
return nil, err
}

return persistentVolumeClaim, nil
}

func (client *Client) GetPersistentVolumeClaims(namespace string) ([]corev1.PersistentVolumeClaim, error) {
persistentVolumeClaimClient := client.clientset.CoreV1().PersistentVolumeClaims(namespace)

persistentVolumeClaimList, err := persistentVolumeClaimClient.List(client.context, metav1.ListOptions{
LabelSelector: fmt.Sprintf("app.kubernetes.io/managed-by=%v", global.Settings.ManagedApplication),
})
if err != nil {
return nil, err
}

return persistentVolumeClaimList.Items, nil
}

func (client *Client) CreatePersistentVolumeClaim(
namespace string,
persistentVolumeClaimDraft *corev1.PersistentVolumeClaim,
) (*corev1.PersistentVolumeClaim, error) {
persistentVolumeClaimClient := client.clientset.CoreV1().PersistentVolumeClaims(namespace)

persistentVolumeClaim, err := persistentVolumeClaimClient.Create(
client.context, persistentVolumeClaimDraft, metav1.CreateOptions{})

if err != nil {
return nil, err
}

return persistentVolumeClaim, nil
}

func (client *Client) DeletePersistentVolumeClaim(namespace, name string) error {
persistentVolumeClaimClient := client.clientset.CoreV1().PersistentVolumeClaims(namespace)

err := persistentVolumeClaimClient.Delete(client.context, name, metav1.DeleteOptions{})
if err != nil {
return nil
}

return nil
}
1 change: 1 addition & 0 deletions internal/config/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Settings struct {
CertManagerClusterIssuer string `yaml:"cert_manager_cluster_issuer"`
EphemeralStorageCoefficient float64 `yaml:"ephemeral_storage_coefficient"`
IngressDefaultPort int `yaml:"ingress_default_port"`
PvcStorageClassName string `yaml:"pvc_storage_class_name"`
}

type ServiceChecksSettings struct {
Expand Down
74 changes: 74 additions & 0 deletions internal/domain_logic/containers.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package domain

import (
"log"
"time"

"gitlab.com/dualbootpartners/idyl/uffizzi_controller/internal/global"
"gitlab.com/dualbootpartners/idyl/uffizzi_controller/internal/pkg/string_utils"
domainTypes "gitlab.com/dualbootpartners/idyl/uffizzi_controller/internal/types/domain"
)

Expand Down Expand Up @@ -58,3 +60,75 @@ func (l *Logic) ApplyContainerSecrets(namespace string, containerList domainType

return nil
}

func (l *Logic) ApplyContainersNamedVolumes(namespace string, containerList domainTypes.ContainerList) error {
for _, volume := range containerList.GetUniqNamedVolumes() {
pvcName := global.Settings.ResourceName.PvcName(volume.UniqName)
pvc, err := l.KuberClient.FindOrInitializePersistentVolumeClaim(namespace, pvcName)

if err != nil {
return err
}

if len(pvc.UID) == 0 {
_, err = l.KuberClient.CreatePersistentVolumeClaim(namespace, pvc)
}

if err != nil {
return err
}
}

return nil
}

func (l *Logic) ApplyContainersAnonymousVolumes(namespace string, containerList domainTypes.ContainerList) error {
for _, volume := range containerList.GetUniqAnonymousVolumes() {
pvcName := global.Settings.ResourceName.PvcName(volume.UniqName)
pvc, err := l.KuberClient.FindOrInitializePersistentVolumeClaim(namespace, pvcName)

if err != nil {
return err
}

if len(pvc.UID) == 0 {
_, err = l.KuberClient.CreatePersistentVolumeClaim(namespace, pvc)
}

if err != nil {
return err
}
}

return nil
}

func (l *Logic) RemoveUnusedContainersVolumes(namespace string, containerList domainTypes.ContainerList) error {
uniqVolumes := containerList.GetUniqNamedVolumes()
uniqVolumes = append(uniqVolumes, containerList.GetUniqAnonymousVolumes()...)
newPersistentVolumeClaimNames := []string{}

for _, volume := range uniqVolumes {
newPersistentVolumeClaimNames = append(newPersistentVolumeClaimNames, global.Settings.ResourceName.PvcName(volume.UniqName))
}

existsPersistentVolumeClaims, err := l.KuberClient.GetPersistentVolumeClaims(namespace)
if err != nil {
return err
}

for _, existsPersistentVolumeClaim := range existsPersistentVolumeClaims {
if string_utils.Contains(newPersistentVolumeClaimNames, existsPersistentVolumeClaim.Name) {
continue
}

err := l.KuberClient.DeletePersistentVolumeClaim(namespace, existsPersistentVolumeClaim.Name)
if err != nil {
return nil
}

log.Printf("%v/pvc %v was deleted\n", namespace, existsPersistentVolumeClaim.Name)
}

return nil
}
15 changes: 15 additions & 0 deletions internal/domain_logic/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,26 @@ func (l *Logic) ApplyContainers(
return err
}

err = l.RemoveUnusedContainersVolumes(namespaceName, containerList)
if err != nil {
return err
}

err = l.ApplyContainerSecrets(namespaceName, containerList)
if err != nil {
return err
}

err = l.ApplyContainersNamedVolumes(namespaceName, containerList)
if err != nil {
return err
}

err = l.ApplyContainersAnonymousVolumes(namespaceName, containerList)
if err != nil {
return err
}

if containerList.IsEmpty() {
return l.CleaningNamespaceForEmptyContainers(namespace)
}
Expand Down
Loading