github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/client/driver/env/env.go (about)

     1  package env
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	hargs "github.com/hashicorp/nomad/helper/args"
     9  	"github.com/hashicorp/nomad/nomad/structs"
    10  )
    11  
    12  // A set of environment variables that are exported by each driver.
    13  const (
    14  	// The path to the alloc directory that is shared across tasks within a task
    15  	// group.
    16  	AllocDir = "NOMAD_ALLOC_DIR"
    17  
    18  	// The path to the tasks local directory where it can store data that is
    19  	// persisted to the alloc is removed.
    20  	TaskLocalDir = "NOMAD_TASK_DIR"
    21  
    22  	// The tasks memory limit in MBs.
    23  	MemLimit = "NOMAD_MEMORY_LIMIT"
    24  
    25  	// The tasks limit in MHz.
    26  	CpuLimit = "NOMAD_CPU_LIMIT"
    27  
    28  	// Prefix for passing both dynamic and static port allocations to
    29  	// tasks.
    30  	// E.g. $NOMAD_IP_1=127.0.0.1:1 or $NOMAD_IP_http=127.0.0.1:80
    31  	AddrPrefix = "NOMAD_ADDR_"
    32  
    33  	// Prefix for passing the host port when a portmap is specified.
    34  	HostPortPrefix = "NOMAD_HOST_PORT_"
    35  
    36  	// Prefix for passing task meta data.
    37  	MetaPrefix = "NOMAD_META_"
    38  )
    39  
    40  // The node values that can be interpreted.
    41  const (
    42  	nodeIdKey    = "node.unique.id"
    43  	nodeDcKey    = "node.datacenter"
    44  	nodeNameKey  = "node.unique.name"
    45  	nodeClassKey = "node.class"
    46  
    47  	// Prefixes used for lookups.
    48  	nodeAttributePrefix = "attr."
    49  	nodeMetaPrefix      = "meta."
    50  )
    51  
    52  // TaskEnvironment is used to expose information to a task via environment
    53  // variables and provide interpolation of Nomad variables.
    54  type TaskEnvironment struct {
    55  	Env      map[string]string
    56  	Meta     map[string]string
    57  	AllocDir string
    58  	TaskDir  string
    59  	CpuLimit int
    60  	MemLimit int
    61  	Node     *structs.Node
    62  	Networks []*structs.NetworkResource
    63  	PortMap  map[string]int
    64  
    65  	// taskEnv is the variables that will be set in the tasks environment
    66  	TaskEnv map[string]string
    67  
    68  	// nodeValues is the values that are allowed for interprolation from the
    69  	// node.
    70  	NodeValues map[string]string
    71  }
    72  
    73  func NewTaskEnvironment(node *structs.Node) *TaskEnvironment {
    74  	return &TaskEnvironment{Node: node}
    75  }
    76  
    77  // ParseAndReplace takes the user supplied args replaces any instance of an
    78  // environment variable or nomad variable in the args with the actual value.
    79  func (t *TaskEnvironment) ParseAndReplace(args []string) []string {
    80  	replaced := make([]string, len(args))
    81  	for i, arg := range args {
    82  		replaced[i] = hargs.ReplaceEnv(arg, t.TaskEnv, t.NodeValues)
    83  	}
    84  
    85  	return replaced
    86  }
    87  
    88  // ReplaceEnv takes an arg and replaces all occurences of environment variables
    89  // and nomad variables.  If the variable is found in the passed map it is
    90  // replaced, otherwise the original string is returned.
    91  func (t *TaskEnvironment) ReplaceEnv(arg string) string {
    92  	return hargs.ReplaceEnv(arg, t.TaskEnv, t.NodeValues)
    93  }
    94  
    95  // Build must be called after all the tasks environment values have been set.
    96  func (t *TaskEnvironment) Build() *TaskEnvironment {
    97  	t.NodeValues = make(map[string]string)
    98  	t.TaskEnv = make(map[string]string)
    99  
   100  	// Build the task metadata
   101  	for k, v := range t.Meta {
   102  		t.TaskEnv[fmt.Sprintf("%s%s", MetaPrefix, strings.ToUpper(k))] = v
   103  	}
   104  
   105  	// Build the ports
   106  	for _, network := range t.Networks {
   107  		for label, value := range network.MapLabelToValues(t.PortMap) {
   108  			IPPort := fmt.Sprintf("%s:%d", network.IP, value)
   109  			t.TaskEnv[fmt.Sprintf("%s%s", AddrPrefix, label)] = IPPort
   110  
   111  			// Pass an explicit port mapping to the environment
   112  			if port, ok := t.PortMap[label]; ok {
   113  				t.TaskEnv[fmt.Sprintf("%s%s", HostPortPrefix, label)] = strconv.Itoa(port)
   114  			}
   115  		}
   116  	}
   117  
   118  	// Build the directories
   119  	if t.AllocDir != "" {
   120  		t.TaskEnv[AllocDir] = t.AllocDir
   121  	}
   122  	if t.TaskDir != "" {
   123  		t.TaskEnv[TaskLocalDir] = t.TaskDir
   124  	}
   125  
   126  	// Build the resource limits
   127  	if t.MemLimit != 0 {
   128  		t.TaskEnv[MemLimit] = strconv.Itoa(t.MemLimit)
   129  	}
   130  	if t.CpuLimit != 0 {
   131  		t.TaskEnv[CpuLimit] = strconv.Itoa(t.CpuLimit)
   132  	}
   133  
   134  	// Build the node
   135  	if t.Node != nil {
   136  		// Set up the node values.
   137  		t.NodeValues[nodeIdKey] = t.Node.ID
   138  		t.NodeValues[nodeDcKey] = t.Node.Datacenter
   139  		t.NodeValues[nodeNameKey] = t.Node.Name
   140  		t.NodeValues[nodeClassKey] = t.Node.NodeClass
   141  
   142  		// Set up the attributes.
   143  		for k, v := range t.Node.Attributes {
   144  			t.NodeValues[fmt.Sprintf("%s%s", nodeAttributePrefix, k)] = v
   145  		}
   146  
   147  		// Set up the meta.
   148  		for k, v := range t.Node.Meta {
   149  			t.NodeValues[fmt.Sprintf("%s%s", nodeMetaPrefix, k)] = v
   150  		}
   151  	}
   152  
   153  	// Interpret the environment variables
   154  	interpreted := make(map[string]string, len(t.Env))
   155  	for k, v := range t.Env {
   156  		interpreted[k] = hargs.ReplaceEnv(v, t.NodeValues, t.TaskEnv)
   157  	}
   158  
   159  	for k, v := range interpreted {
   160  		t.TaskEnv[k] = v
   161  	}
   162  
   163  	return t
   164  }
   165  
   166  // EnvList returns a list of strings with NAME=value pairs.
   167  func (t *TaskEnvironment) EnvList() []string {
   168  	env := []string{}
   169  	for k, v := range t.TaskEnv {
   170  		env = append(env, fmt.Sprintf("%s=%s", k, v))
   171  	}
   172  
   173  	return env
   174  }
   175  
   176  // EnvMap returns a copy of the tasks environment variables.
   177  func (t *TaskEnvironment) EnvMap() map[string]string {
   178  	m := make(map[string]string, len(t.TaskEnv))
   179  	for k, v := range t.TaskEnv {
   180  		m[k] = v
   181  	}
   182  
   183  	return m
   184  }
   185  
   186  // Builder methods to build the TaskEnvironment
   187  func (t *TaskEnvironment) SetAllocDir(dir string) *TaskEnvironment {
   188  	t.AllocDir = dir
   189  	return t
   190  }
   191  
   192  func (t *TaskEnvironment) ClearAllocDir() *TaskEnvironment {
   193  	t.AllocDir = ""
   194  	return t
   195  }
   196  
   197  func (t *TaskEnvironment) SetTaskLocalDir(dir string) *TaskEnvironment {
   198  	t.TaskDir = dir
   199  	return t
   200  }
   201  
   202  func (t *TaskEnvironment) ClearTaskLocalDir() *TaskEnvironment {
   203  	t.TaskDir = ""
   204  	return t
   205  }
   206  
   207  func (t *TaskEnvironment) SetMemLimit(limit int) *TaskEnvironment {
   208  	t.MemLimit = limit
   209  	return t
   210  }
   211  
   212  func (t *TaskEnvironment) ClearMemLimit() *TaskEnvironment {
   213  	t.MemLimit = 0
   214  	return t
   215  }
   216  
   217  func (t *TaskEnvironment) SetCpuLimit(limit int) *TaskEnvironment {
   218  	t.CpuLimit = limit
   219  	return t
   220  }
   221  
   222  func (t *TaskEnvironment) ClearCpuLimit() *TaskEnvironment {
   223  	t.CpuLimit = 0
   224  	return t
   225  }
   226  
   227  func (t *TaskEnvironment) SetNetworks(networks []*structs.NetworkResource) *TaskEnvironment {
   228  	t.Networks = networks
   229  	return t
   230  }
   231  
   232  func (t *TaskEnvironment) clearNetworks() *TaskEnvironment {
   233  	t.Networks = nil
   234  	return t
   235  }
   236  
   237  func (t *TaskEnvironment) SetPortMap(portMap map[string]int) *TaskEnvironment {
   238  	t.PortMap = portMap
   239  	return t
   240  }
   241  
   242  func (t *TaskEnvironment) clearPortMap() *TaskEnvironment {
   243  	t.PortMap = nil
   244  	return t
   245  }
   246  
   247  // Takes a map of meta values to be passed to the task. The keys are capatilized
   248  // when the environent variable is set.
   249  func (t *TaskEnvironment) SetMeta(m map[string]string) *TaskEnvironment {
   250  	t.Meta = m
   251  	return t
   252  }
   253  
   254  func (t *TaskEnvironment) ClearMeta() *TaskEnvironment {
   255  	t.Meta = nil
   256  	return t
   257  }
   258  
   259  func (t *TaskEnvironment) SetEnvvars(m map[string]string) *TaskEnvironment {
   260  	t.Env = m
   261  	return t
   262  }
   263  
   264  // Appends the given environment variables.
   265  func (t *TaskEnvironment) AppendEnvvars(m map[string]string) *TaskEnvironment {
   266  	if t.Env == nil {
   267  		t.Env = make(map[string]string, len(m))
   268  	}
   269  
   270  	for k, v := range m {
   271  		t.Env[k] = v
   272  	}
   273  	return t
   274  }
   275  
   276  func (t *TaskEnvironment) ClearEnvvars() *TaskEnvironment {
   277  	t.Env = nil
   278  	return t
   279  }