...

Source file src/github.com/redhat-developer/odo/pkg/configAutomount/kubernetes.go

Documentation: github.com/redhat-developer/odo/pkg/configAutomount

     1  package configAutomount
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"sort"
     7  	"strconv"
     8  
     9  	"github.com/redhat-developer/odo/pkg/kclient"
    10  )
    11  
    12  const (
    13  	labelMountName  = "devfile.io/auto-mount"
    14  	labelMountValue = "true"
    15  
    16  	annotationMountPathName   = "devfile.io/mount-path"
    17  	annotationMountAsName     = "devfile.io/mount-as"
    18  	annotationReadOnlyName    = "devfile.io/read-only"
    19  	annotationMountAccessMode = "devfile.io/mount-access-mode"
    20  )
    21  
    22  type KubernetesClient struct {
    23  	kubeClient kclient.ClientInterface
    24  }
    25  
    26  func NewKubernetesClient(kubeClient kclient.ClientInterface) KubernetesClient {
    27  	return KubernetesClient{
    28  		kubeClient: kubeClient,
    29  	}
    30  }
    31  
    32  func (o KubernetesClient) GetAutomountingVolumes() ([]AutomountInfo, error) {
    33  	var result []AutomountInfo
    34  
    35  	pvcs, err := o.getAutomountingPVCs()
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	result = append(result, pvcs...)
    40  
    41  	secrets, err := o.getAutomountingSecrets()
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	result = append(result, secrets...)
    46  
    47  	cms, err := o.getAutomountingConfigmaps()
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	result = append(result, cms...)
    52  
    53  	return result, nil
    54  }
    55  
    56  func (o KubernetesClient) getAutomountingPVCs() ([]AutomountInfo, error) {
    57  	pvcs, err := o.kubeClient.ListPVCs(labelMountName + "=" + labelMountValue)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	var result []AutomountInfo
    63  	for _, pvc := range pvcs {
    64  		mountPath := filepath.ToSlash(filepath.Join("/", "tmp", pvc.Name))
    65  		if val, found := getMountPathFromAnnotation(pvc.Annotations); found {
    66  			mountPath = val
    67  		}
    68  		result = append(result, AutomountInfo{
    69  			VolumeType: VolumeTypePVC,
    70  			VolumeName: pvc.Name,
    71  			MountPath:  mountPath,
    72  			MountAs:    MountAsFile,
    73  			ReadOnly:   pvc.Annotations[annotationReadOnlyName] == "true",
    74  		})
    75  	}
    76  	return result, nil
    77  }
    78  
    79  func (o KubernetesClient) getAutomountingSecrets() ([]AutomountInfo, error) {
    80  	secrets, err := o.kubeClient.ListSecrets(labelMountName + "=" + labelMountValue)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	var result []AutomountInfo
    86  	for _, secret := range secrets {
    87  		mountAs := getMountAsFromAnnotation(secret.Annotations)
    88  		mountPath := filepath.ToSlash(filepath.Join("/", "etc", "secret", secret.Name))
    89  		var keys []string
    90  		if val, found := getMountPathFromAnnotation(secret.Annotations); found {
    91  			mountPath = val
    92  		}
    93  		if mountAs == MountAsEnv {
    94  			mountPath = ""
    95  		}
    96  		if mountAs == MountAsSubpath {
    97  			for k := range secret.Data {
    98  				keys = append(keys, k)
    99  			}
   100  			sort.Strings(keys)
   101  		}
   102  
   103  		mountAccessMode, err := getMountAccessModeFromAnnotation(secret.Annotations)
   104  		if err != nil {
   105  			return nil, err
   106  		}
   107  
   108  		result = append(result, AutomountInfo{
   109  			VolumeType:      VolumeTypeSecret,
   110  			VolumeName:      secret.Name,
   111  			MountPath:       mountPath,
   112  			MountAs:         mountAs,
   113  			ReadOnly:        secret.Annotations[annotationReadOnlyName] == "true",
   114  			Keys:            keys,
   115  			MountAccessMode: mountAccessMode,
   116  		})
   117  	}
   118  	return result, nil
   119  }
   120  
   121  func (o KubernetesClient) getAutomountingConfigmaps() ([]AutomountInfo, error) {
   122  	cms, err := o.kubeClient.ListConfigMaps(labelMountName + "=" + labelMountValue)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	var result []AutomountInfo
   128  	for _, cm := range cms {
   129  		mountAs := getMountAsFromAnnotation(cm.Annotations)
   130  		mountPath := filepath.ToSlash(filepath.Join("/", "etc", "config", cm.Name))
   131  		var keys []string
   132  		if val, found := getMountPathFromAnnotation(cm.Annotations); found {
   133  			mountPath = val
   134  		}
   135  		if mountAs == MountAsEnv {
   136  			mountPath = ""
   137  		}
   138  		if mountAs == MountAsSubpath {
   139  			for k := range cm.Data {
   140  				keys = append(keys, k)
   141  			}
   142  			sort.Strings(keys)
   143  		}
   144  
   145  		mountAccessMode, err := getMountAccessModeFromAnnotation(cm.Annotations)
   146  		if err != nil {
   147  			return nil, err
   148  		}
   149  
   150  		result = append(result, AutomountInfo{
   151  			VolumeType:      VolumeTypeConfigmap,
   152  			VolumeName:      cm.Name,
   153  			MountPath:       mountPath,
   154  			MountAs:         mountAs,
   155  			ReadOnly:        cm.Annotations[annotationReadOnlyName] == "true",
   156  			Keys:            keys,
   157  			MountAccessMode: mountAccessMode,
   158  		})
   159  	}
   160  	return result, nil
   161  }
   162  
   163  func getMountPathFromAnnotation(annotations map[string]string) (string, bool) {
   164  	val, found := annotations[annotationMountPathName]
   165  	return val, found
   166  }
   167  
   168  func getMountAsFromAnnotation(annotations map[string]string) MountAs {
   169  	switch annotations[annotationMountAsName] {
   170  	case "subpath":
   171  		return MountAsSubpath
   172  	case "env":
   173  		return MountAsEnv
   174  	default:
   175  		return MountAsFile
   176  	}
   177  }
   178  
   179  func getMountAccessModeFromAnnotation(annotations map[string]string) (*int32, error) {
   180  	accessModeStr, found := annotations[annotationMountAccessMode]
   181  	if !found {
   182  		return nil, nil
   183  	}
   184  	accessMode64, err := strconv.ParseInt(accessModeStr, 0, 32)
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	if accessMode64 < 0 || accessMode64 > 0777 {
   190  		return nil, fmt.Errorf("invalid access mode annotation: value '%s' parsed to %o (octal). Must be in range 0000-0777", accessModeStr, accessMode64)
   191  	}
   192  
   193  	accessMode32 := int32(accessMode64)
   194  	return &accessMode32, nil
   195  }
   196  

View as plain text