github.com/profzone/eden-framework@v1.0.10/internal/project/deployment.go (about)

     1  package project
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"github.com/fatih/color"
     9  	"github.com/profzone/eden-framework/internal/k8s"
    10  	"github.com/sirupsen/logrus"
    11  	"gopkg.in/yaml.v2"
    12  	"io/ioutil"
    13  	apiv1 "k8s.io/api/core/v1"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"k8s.io/apimachinery/pkg/types"
    16  	"k8s.io/client-go/kubernetes"
    17  	"k8s.io/client-go/tools/clientcmd"
    18  	"strings"
    19  )
    20  
    21  func ProcessDeployment(p *Project, env, kubeConfig, deployConfig, serviceConfig string) error {
    22  	if env == "" {
    23  		return errors.New("deployment must specify a environment name")
    24  	}
    25  	envVars := LoadEnv(env, p.Feature)
    26  
    27  	ctx, _ := context.WithCancel(context.Background())
    28  	config, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
    29  	if err != nil {
    30  		return err
    31  	}
    32  	clientSet, err := kubernetes.NewForConfig(config)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	// Get Deployment
    38  	deployment, patch, err := k8s.MakeDeployment(deployConfig)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	for key, val := range envVars {
    44  		deployment.Spec.Template.Spec.Containers[0].Env = append(deployment.Spec.Template.Spec.Containers[0].Env, apiv1.EnvVar{
    45  			Name:  key,
    46  			Value: val,
    47  		})
    48  	}
    49  	patch = patchEnvVars(patch, envVars)
    50  
    51  	deploymentsClient := clientSet.AppsV1().Deployments(deployment.Namespace)
    52  	_, err = deploymentsClient.Get(ctx, deployment.Name, metav1.GetOptions{})
    53  	if err != nil {
    54  		// Create Deployment
    55  		fmt.Println("Creating deployment...")
    56  		deployment, err = deploymentsClient.Create(ctx, deployment, metav1.CreateOptions{})
    57  		if err != nil {
    58  			return err
    59  		}
    60  		fmt.Printf("Created deployment %s.\n", deployment.GetObjectMeta().GetName())
    61  	} else {
    62  		// Patch Deployment
    63  		fmt.Println("Updating deployment...")
    64  		data, err := json.Marshal(patch)
    65  		if err != nil {
    66  			return err
    67  		}
    68  		deployment, err = deploymentsClient.Patch(ctx, deployment.Name, types.StrategicMergePatchType, data, metav1.PatchOptions{})
    69  		if err != nil {
    70  			return err
    71  		}
    72  		fmt.Printf("Updated deployment %s.\n", deployment.GetObjectMeta().GetName())
    73  	}
    74  
    75  	SetEnv(EnvKeyDeploymentUID, string(deployment.UID))
    76  
    77  	// Get Service
    78  	service, patch, err := k8s.MakeService(serviceConfig)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	servicesClient := clientSet.CoreV1().Services(service.Namespace)
    83  	_, err = servicesClient.Get(ctx, service.Name, metav1.GetOptions{})
    84  	if err != nil {
    85  		// Create Service
    86  		fmt.Println("Creating service...")
    87  		service, err = servicesClient.Create(ctx, service, metav1.CreateOptions{})
    88  		if err != nil {
    89  			return err
    90  		}
    91  		fmt.Printf("Created service %s.\n", service.GetObjectMeta().GetName())
    92  	} else {
    93  		// Patch Service
    94  		fmt.Println("Updating service...")
    95  		data, err := json.Marshal(patch)
    96  		if err != nil {
    97  			return err
    98  		}
    99  		service, err = servicesClient.Patch(ctx, service.Name, types.StrategicMergePatchType, data, metav1.PatchOptions{})
   100  		if err != nil {
   101  			return err
   102  		}
   103  		fmt.Printf("Updated service %s.\n", service.GetObjectMeta().GetName())
   104  	}
   105  	return nil
   106  }
   107  
   108  func LoadEnv(envName string, feature string) map[string]string {
   109  	defaultEnv := loadEnvFromFiles("default", feature)
   110  	if envName != "" {
   111  		extendEnv := loadEnvFromFiles(envName, feature)
   112  		defaultEnv = mergeEnvVars(defaultEnv, extendEnv)
   113  	}
   114  
   115  	return defaultEnv
   116  }
   117  
   118  func loadEnvFromFiles(envName string, feature string) map[string]string {
   119  	defaultEnv := loadEnvFromFile(envName)
   120  	if feature != "" {
   121  		extendEnv := loadEnvFromFile(envName + "-" + feature)
   122  		defaultEnv = mergeEnvVars(defaultEnv, extendEnv)
   123  	}
   124  
   125  	return defaultEnv
   126  }
   127  
   128  func loadEnvFromFile(envName string) map[string]string {
   129  	filename := "build/configs/" + strings.ToLower(envName) + ".yml"
   130  	logrus.Infof("try to load env vars from %s ...\n", color.GreenString(filename))
   131  	envFileContent, err := ioutil.ReadFile(filename)
   132  	if err != nil {
   133  		return nil
   134  	}
   135  
   136  	var envVars map[string]string
   137  	err = yaml.Unmarshal(envFileContent, &envVars)
   138  	if err != nil {
   139  		panic(err)
   140  	}
   141  	for key, value := range envVars {
   142  		SetEnv(key, value)
   143  	}
   144  	return envVars
   145  }
   146  
   147  func mergeEnvVars(self map[string]string, source map[string]string) map[string]string {
   148  	for key, val := range source {
   149  		self[key] = val
   150  	}
   151  	return self
   152  }
   153  
   154  func patchEnvVars(patch map[string]interface{}, envVars map[string]string) map[string]interface{} {
   155  	envs := make([]map[string]string, 0)
   156  	for key, val := range envVars {
   157  		envs = append(envs, map[string]string{
   158  			"name":  key,
   159  			"value": val,
   160  		})
   161  	}
   162  	patch["spec"].(map[string]interface{})["template"].(map[string]interface{})["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["env"] = envs
   163  
   164  	return patch
   165  }