github.com/upcmd/up@v0.8.1-0.20230108151705-ad8b797bf04f/biz/impl/scope.go (about)

     1  // Ultimate Provisioner: UP cmd
     2  // Copyright (c) 2019 Stephen Cheng and contributors
     3  
     4  /* This Source Code Form is subject to the terms of the Mozilla Public
     5   * License, v. 2.0. If a copy of the MPL was not distributed with this
     6   * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
     7  
     8  package impl
     9  
    10  import (
    11  	"github.com/imdario/mergo"
    12  	ms "github.com/mitchellh/mapstructure"
    13  	"github.com/mohae/deepcopy"
    14  	"github.com/spf13/viper"
    15  	"github.com/upcmd/up/model/core"
    16  	u "github.com/upcmd/up/utils"
    17  	"io/ioutil"
    18  )
    19  
    20  type Scope struct {
    21  	Name    string
    22  	Ref     string
    23  	RefDir  string
    24  	Members []string
    25  	Vars    core.Cache
    26  	Dvars   Dvars
    27  }
    28  
    29  type Scopes []Scope
    30  
    31  type ExecProfile struct {
    32  	Name     string
    33  	Ref      string
    34  	RefDir   string
    35  	Instance string
    36  	Evars    EnvVars
    37  	//optional
    38  	Taskname string
    39  	Pure     bool
    40  	Verbose  string
    41  }
    42  
    43  type ExecProfiles []ExecProfile
    44  
    45  func DecryptAndRegister(securetag *u.SecureSetting, dvar *Dvar, contextVars *core.Cache, mergeTarget *core.Cache) {
    46  	s := securetag
    47  
    48  	if s == nil {
    49  		u.InvalidAndPanic("check secure setting", "secure setting has to be explicit in dvar secure node, or as a default setting in upconfig.yml")
    50  	}
    51  	var encryptionkey string
    52  	if s.KeyRef != "" {
    53  		data, err := ioutil.ReadFile(s.KeyRef)
    54  		u.LogErrorAndExit("load secure key from ref file", err, "please fix file loading problem")
    55  		encryptionkey = string(data)
    56  	}
    57  
    58  	if s.Key != "" {
    59  		//use vault as first priority
    60  		opt := GetVault().Get(s.Key)
    61  		if opt == nil {
    62  			opt = (*contextVars).Get(s.Key)
    63  		}
    64  		if opt != nil {
    65  			encryptionkey = opt.(string)
    66  		}
    67  	}
    68  
    69  	encrypted := dvar.Rendered
    70  	if encrypted != "" && encryptionkey != "" {
    71  		data := map[string]string{"enc_key": encryptionkey, "encrypted": encrypted}
    72  		decrypted := Render("{{ decryptAES .enc_key .encrypted}}", data)
    73  		secureName := u.Spf("%s_%s", "secure", dvar.Name)
    74  		(*mergeTarget).Put(secureName, decrypted)
    75  	} else {
    76  		u.InvalidAndPanic("dvar decrypt", u.Spf("please double check secure settings for [%s]\nyou might need to associate an instance id or an exec profile", dvar.Name))
    77  	}
    78  
    79  }
    80  
    81  func Decrypt(securetag *u.SecureSetting, dvar *Dvar, contextVars *core.Cache) string {
    82  	s := securetag
    83  	var decrypted string
    84  	if s == nil {
    85  		u.InvalidAndPanic("check secure setting", "secure setting has to be explicit in dvar secure node, or as a default setting in upconfig.yml")
    86  	}
    87  	var encryptionkey string
    88  	if s.KeyRef != "" {
    89  		data, err := ioutil.ReadFile(s.KeyRef)
    90  		u.LogErrorAndExit("load secure key from ref file", err, "please fix file loading problem")
    91  		encryptionkey = string(data)
    92  	}
    93  
    94  	if s.Key != "" {
    95  		encryptionkey = (*contextVars).Get(s.Key).(string)
    96  	}
    97  
    98  	encrypted := dvar.Rendered
    99  
   100  	if encrypted != "" && encryptionkey != "" {
   101  		data := map[string]string{"enc_key": encryptionkey, "encrypted": encrypted}
   102  		decrypted = Render("{{ decryptAES .enc_key .encrypted}}", data)
   103  	} else {
   104  		u.InvalidAndPanic("dvar decrypt", u.Spf("please double check secure settings for [%s]\nyou might need to associate an instance id or an exec profile", dvar.Name))
   105  	}
   106  	return decrypted
   107  }
   108  
   109  func GlobalVarsMergedWithDvars(scope *Scope) (vars *core.Cache) {
   110  	return VarsMergedWithDvars(scope.Name, &scope.Vars, &scope.Dvars, &(scope.Vars))
   111  }
   112  
   113  func ScopeVarsMergedWithDvars(scope *Scope, contextMergedVars *core.Cache) *core.Cache {
   114  	return VarsMergedWithDvars(scope.Name, &scope.Vars, &scope.Dvars, contextMergedVars)
   115  }
   116  
   117  //given vars as base vars space to expand from, expand dvars against contextVars
   118  func VarsMergedWithDvars(mark string, baseVars *core.Cache, dvars *Dvars, contextMergedVars *core.Cache) *core.Cache {
   119  	var mergedVars core.Cache
   120  	mergedVars = deepcopy.Copy(*baseVars).(core.Cache)
   121  
   122  	if dvars != nil {
   123  		expandedVars := dvars.Expand(mark, contextMergedVars)
   124  		mergo.Merge(&mergedVars, expandedVars, mergo.WithOverride)
   125  	}
   126  
   127  	u.Pfvvvvv("scope[%s] merged: %s", mark, u.Sppmsg(mergedVars))
   128  
   129  	return &mergedVars
   130  }
   131  
   132  func loadRefVars(yamlroot *viper.Viper) *core.Cache {
   133  	scopesData := yamlroot.Get("vars")
   134  	vars := core.Cache{}
   135  	err := ms.Decode(scopesData, &vars)
   136  	u.Dvvvvv(vars)
   137  	u.LogError("load ref vars", err)
   138  	return &vars
   139  }
   140  
   141  func loadRefEvars(yamlroot *viper.Viper) *EnvVars {
   142  	evarsData := yamlroot.Get("evars")
   143  	vars := EnvVars{}
   144  	err := ms.Decode(evarsData, &vars)
   145  	u.Dvvvvv(vars)
   146  	u.LogError("load ref vars", err)
   147  	return &vars
   148  }
   149  
   150  //get instance vars from scope definition, eg dev
   151  func (ss *Scopes) GetInstanceVars(instanceName string) *core.Cache {
   152  	for _, s := range *ss {
   153  		if s.Name == instanceName {
   154  			return &s.Vars
   155  		}
   156  	}
   157  
   158  	return nil
   159  }