github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/client/taskenv/services_test.go (about)

     1  package taskenv
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/hashicorp/nomad/helper"
     8  	"github.com/hashicorp/nomad/nomad/structs"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  // TestInterpolateServices asserts that all service
    13  // and check fields are properly interpolated.
    14  func TestInterpolateServices(t *testing.T) {
    15  	t.Parallel()
    16  
    17  	services := []*structs.Service{
    18  		{
    19  			Name:      "${name}",
    20  			PortLabel: "${portlabel}",
    21  			Tags:      []string{"${tags}"},
    22  			Meta: map[string]string{
    23  				"meta-key": "${meta}",
    24  			},
    25  			CanaryMeta: map[string]string{
    26  				"canarymeta-key": "${canarymeta}",
    27  			},
    28  			Checks: []*structs.ServiceCheck{
    29  				{
    30  					Name:          "${checkname}",
    31  					Type:          "${checktype}",
    32  					Command:       "${checkcmd}",
    33  					Args:          []string{"${checkarg}"},
    34  					Path:          "${checkstr}",
    35  					Protocol:      "${checkproto}",
    36  					PortLabel:     "${checklabel}",
    37  					InitialStatus: "${checkstatus}",
    38  					Method:        "${checkmethod}",
    39  					Header: map[string][]string{
    40  						"${checkheaderk}": {"${checkheaderv}"},
    41  					},
    42  				},
    43  			},
    44  		},
    45  	}
    46  
    47  	env := &TaskEnv{
    48  		EnvMap: map[string]string{
    49  			"name":         "name",
    50  			"portlabel":    "portlabel",
    51  			"tags":         "tags",
    52  			"meta":         "meta-value",
    53  			"canarymeta":   "canarymeta-value",
    54  			"checkname":    "checkname",
    55  			"checktype":    "checktype",
    56  			"checkcmd":     "checkcmd",
    57  			"checkarg":     "checkarg",
    58  			"checkstr":     "checkstr",
    59  			"checkpath":    "checkpath",
    60  			"checkproto":   "checkproto",
    61  			"checklabel":   "checklabel",
    62  			"checkstatus":  "checkstatus",
    63  			"checkmethod":  "checkmethod",
    64  			"checkheaderk": "checkheaderk",
    65  			"checkheaderv": "checkheaderv",
    66  		},
    67  	}
    68  
    69  	interpolated := InterpolateServices(env, services)
    70  
    71  	exp := []*structs.Service{
    72  		{
    73  			Name:      "name",
    74  			PortLabel: "portlabel",
    75  			Tags:      []string{"tags"},
    76  			Meta: map[string]string{
    77  				"meta-key": "meta-value",
    78  			},
    79  			CanaryMeta: map[string]string{
    80  				"canarymeta-key": "canarymeta-value",
    81  			},
    82  			Checks: []*structs.ServiceCheck{
    83  				{
    84  					Name:          "checkname",
    85  					Type:          "checktype",
    86  					Command:       "checkcmd",
    87  					Args:          []string{"checkarg"},
    88  					Path:          "checkstr",
    89  					Protocol:      "checkproto",
    90  					PortLabel:     "checklabel",
    91  					InitialStatus: "checkstatus",
    92  					Method:        "checkmethod",
    93  					Header: map[string][]string{
    94  						"checkheaderk": {"checkheaderv"},
    95  					},
    96  				},
    97  			},
    98  		},
    99  	}
   100  
   101  	require.Equal(t, exp, interpolated)
   102  }
   103  
   104  var testEnv = NewTaskEnv(
   105  	map[string]string{"foo": "bar", "baz": "blah"},
   106  	map[string]string{"foo": "bar", "baz": "blah"},
   107  	nil, nil, "", "")
   108  
   109  func TestInterpolate_interpolateMapStringSliceString(t *testing.T) {
   110  	t.Parallel()
   111  
   112  	t.Run("nil", func(t *testing.T) {
   113  		require.Nil(t, interpolateMapStringSliceString(testEnv, nil))
   114  	})
   115  
   116  	t.Run("not nil", func(t *testing.T) {
   117  		require.Equal(t, map[string][]string{
   118  			"a":   {"b"},
   119  			"bar": {"blah", "c"},
   120  		}, interpolateMapStringSliceString(testEnv, map[string][]string{
   121  			"a":      {"b"},
   122  			"${foo}": {"${baz}", "c"},
   123  		}))
   124  	})
   125  }
   126  
   127  func TestInterpolate_interpolateMapStringString(t *testing.T) {
   128  	t.Parallel()
   129  
   130  	t.Run("nil", func(t *testing.T) {
   131  		require.Nil(t, interpolateMapStringString(testEnv, nil))
   132  	})
   133  
   134  	t.Run("not nil", func(t *testing.T) {
   135  		require.Equal(t, map[string]string{
   136  			"a":   "b",
   137  			"bar": "blah",
   138  		}, interpolateMapStringString(testEnv, map[string]string{
   139  			"a":      "b",
   140  			"${foo}": "${baz}",
   141  		}))
   142  	})
   143  }
   144  
   145  func TestInterpolate_interpolateMapStringInterface(t *testing.T) {
   146  	t.Parallel()
   147  
   148  	t.Run("nil", func(t *testing.T) {
   149  		require.Nil(t, interpolateMapStringInterface(testEnv, nil))
   150  	})
   151  
   152  	t.Run("not nil", func(t *testing.T) {
   153  		require.Equal(t, map[string]interface{}{
   154  			"a":   1,
   155  			"bar": 2,
   156  		}, interpolateMapStringInterface(testEnv, map[string]interface{}{
   157  			"a":      1,
   158  			"${foo}": 2,
   159  		}))
   160  	})
   161  }
   162  
   163  func TestInterpolate_interpolateConnect(t *testing.T) {
   164  	t.Parallel()
   165  
   166  	e := map[string]string{
   167  		"tag1":              "_tag1",
   168  		"port1":             "12345",
   169  		"address1":          "1.2.3.4",
   170  		"destination1":      "_dest1",
   171  		"datacenter1":       "_datacenter1",
   172  		"localbindaddress1": "127.0.0.2",
   173  		"path1":             "_path1",
   174  		"protocol1":         "_protocol1",
   175  		"port2":             "_port2",
   176  		"config1":           "_config1",
   177  		"driver1":           "_driver1",
   178  		"user1":             "_user1",
   179  		"config2":           "_config2",
   180  		"env1":              "_env1",
   181  		"env2":              "_env2",
   182  		"mode1":             "_mode1",
   183  		"device1":           "_device1",
   184  		"cidr1":             "10.0.0.0/64",
   185  		"ip1":               "1.1.1.1",
   186  		"server1":           "10.0.0.1",
   187  		"search1":           "10.0.0.2",
   188  		"option1":           "10.0.0.3",
   189  		"port3":             "_port3",
   190  		"network1":          "_network1",
   191  		"port4":             "_port4",
   192  		"network2":          "_network2",
   193  		"resource1":         "_resource1",
   194  		"meta1":             "_meta1",
   195  		"meta2":             "_meta2",
   196  		"signal1":           "_signal1",
   197  		"bind1":             "_bind1",
   198  		"address2":          "10.0.0.4",
   199  		"config3":           "_config3",
   200  		"protocol2":         "_protocol2",
   201  		"service1":          "_service1",
   202  		"host1":             "_host1",
   203  	}
   204  	env := NewTaskEnv(e, e, nil, nil, "", "")
   205  
   206  	connect := &structs.ConsulConnect{
   207  		Native: false,
   208  		SidecarService: &structs.ConsulSidecarService{
   209  			Tags: []string{"${tag1}", "tag2"},
   210  			Port: "${port1}",
   211  			Proxy: &structs.ConsulProxy{
   212  				LocalServiceAddress: "${address1}",
   213  				LocalServicePort:    10000,
   214  				Upstreams: []structs.ConsulUpstream{{
   215  					DestinationName:  "${destination1}",
   216  					Datacenter:       "${datacenter1}",
   217  					LocalBindPort:    10001,
   218  					LocalBindAddress: "${localbindaddress1}",
   219  				}},
   220  				Expose: &structs.ConsulExposeConfig{
   221  					Paths: []structs.ConsulExposePath{{
   222  						Path:          "${path1}",
   223  						Protocol:      "${protocol1}",
   224  						ListenerPort:  "${port2}",
   225  						LocalPathPort: 10002,
   226  					}},
   227  				},
   228  				Config: map[string]interface{}{
   229  					"${config1}": 1,
   230  				},
   231  			},
   232  		},
   233  		SidecarTask: &structs.SidecarTask{
   234  			Name:   "name", // not interpolated by taskenv
   235  			Driver: "${driver1}",
   236  			User:   "${user1}",
   237  			Config: map[string]interface{}{"${config2}": 2},
   238  			Env:    map[string]string{"${env1}": "${env2}"},
   239  			Resources: &structs.Resources{
   240  				CPU:      1,
   241  				MemoryMB: 2,
   242  				DiskMB:   3,
   243  				IOPS:     4,
   244  				Networks: structs.Networks{{
   245  					Mode:   "${mode1}",
   246  					Device: "${device1}",
   247  					CIDR:   "${cidr1}",
   248  					IP:     "${ip1}",
   249  					MBits:  1,
   250  					DNS: &structs.DNSConfig{
   251  						Servers:  []string{"${server1}"},
   252  						Searches: []string{"${search1}"},
   253  						Options:  []string{"${option1}"},
   254  					},
   255  					ReservedPorts: []structs.Port{{
   256  						Label:       "${port3}",
   257  						Value:       9000,
   258  						To:          9000,
   259  						HostNetwork: "${network1}",
   260  					}},
   261  					DynamicPorts: []structs.Port{{
   262  						Label:       "${port4}",
   263  						Value:       9001,
   264  						To:          9001,
   265  						HostNetwork: "${network2}",
   266  					}},
   267  				}},
   268  				Devices: structs.ResourceDevices{{
   269  					Name: "${resource1}",
   270  				}},
   271  			},
   272  			Meta:        map[string]string{"${meta1}": "${meta2}"},
   273  			KillTimeout: helper.TimeToPtr(1 * time.Second),
   274  			LogConfig: &structs.LogConfig{
   275  				MaxFiles:      1,
   276  				MaxFileSizeMB: 2,
   277  			},
   278  			ShutdownDelay: helper.TimeToPtr(2 * time.Second),
   279  			KillSignal:    "${signal1}",
   280  		},
   281  		Gateway: &structs.ConsulGateway{
   282  			Proxy: &structs.ConsulGatewayProxy{
   283  				ConnectTimeout:                  helper.TimeToPtr(3 * time.Second),
   284  				EnvoyGatewayBindTaggedAddresses: true,
   285  				EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
   286  					"${bind1}": {
   287  						Address: "${address2}",
   288  						Port:    8000,
   289  					},
   290  				},
   291  				EnvoyGatewayNoDefaultBind: true,
   292  				Config: map[string]interface{}{
   293  					"${config3}": 4,
   294  				},
   295  			},
   296  			Ingress: &structs.ConsulIngressConfigEntry{
   297  				TLS: &structs.ConsulGatewayTLSConfig{
   298  					Enabled: true,
   299  				},
   300  				Listeners: []*structs.ConsulIngressListener{{
   301  					Protocol: "${protocol2}",
   302  					Port:     8001,
   303  					Services: []*structs.ConsulIngressService{{
   304  						Name:  "${service1}",
   305  						Hosts: []string{"${host1}", "host2"},
   306  					}},
   307  				}},
   308  			},
   309  		},
   310  	}
   311  
   312  	interpolateConnect(env, connect)
   313  
   314  	require.Equal(t, &structs.ConsulConnect{
   315  		Native: false,
   316  		SidecarService: &structs.ConsulSidecarService{
   317  			Tags: []string{"_tag1", "tag2"},
   318  			Port: "12345",
   319  			Proxy: &structs.ConsulProxy{
   320  				LocalServiceAddress: "1.2.3.4",
   321  				LocalServicePort:    10000,
   322  				Upstreams: []structs.ConsulUpstream{{
   323  					DestinationName:  "_dest1",
   324  					Datacenter:       "_datacenter1",
   325  					LocalBindPort:    10001,
   326  					LocalBindAddress: "127.0.0.2",
   327  				}},
   328  				Expose: &structs.ConsulExposeConfig{
   329  					Paths: []structs.ConsulExposePath{{
   330  						Path:          "_path1",
   331  						Protocol:      "_protocol1",
   332  						ListenerPort:  "_port2",
   333  						LocalPathPort: 10002,
   334  					}},
   335  				},
   336  				Config: map[string]interface{}{
   337  					"_config1": 1,
   338  				},
   339  			},
   340  		},
   341  		SidecarTask: &structs.SidecarTask{
   342  			Name:   "name", // not interpolated by InterpolateServices
   343  			Driver: "_driver1",
   344  			User:   "_user1",
   345  			Config: map[string]interface{}{"_config2": 2},
   346  			Env:    map[string]string{"_env1": "_env2"},
   347  			Resources: &structs.Resources{
   348  				CPU:      1,
   349  				MemoryMB: 2,
   350  				DiskMB:   3,
   351  				IOPS:     4,
   352  				Networks: structs.Networks{{
   353  					Mode:   "_mode1",
   354  					Device: "_device1",
   355  					CIDR:   "10.0.0.0/64",
   356  					IP:     "1.1.1.1",
   357  					MBits:  1,
   358  					DNS: &structs.DNSConfig{
   359  						Servers:  []string{"10.0.0.1"},
   360  						Searches: []string{"10.0.0.2"},
   361  						Options:  []string{"10.0.0.3"},
   362  					},
   363  					ReservedPorts: []structs.Port{{
   364  						Label:       "_port3",
   365  						Value:       9000,
   366  						To:          9000,
   367  						HostNetwork: "_network1",
   368  					}},
   369  					DynamicPorts: []structs.Port{{
   370  						Label:       "_port4",
   371  						Value:       9001,
   372  						To:          9001,
   373  						HostNetwork: "_network2",
   374  					}},
   375  				}},
   376  				Devices: structs.ResourceDevices{{
   377  					Name: "_resource1",
   378  				}},
   379  			},
   380  			Meta:        map[string]string{"_meta1": "_meta2"},
   381  			KillTimeout: helper.TimeToPtr(1 * time.Second),
   382  			LogConfig: &structs.LogConfig{
   383  				MaxFiles:      1,
   384  				MaxFileSizeMB: 2,
   385  			},
   386  			ShutdownDelay: helper.TimeToPtr(2 * time.Second),
   387  			KillSignal:    "_signal1",
   388  		},
   389  		Gateway: &structs.ConsulGateway{
   390  			Proxy: &structs.ConsulGatewayProxy{
   391  				ConnectTimeout:                  helper.TimeToPtr(3 * time.Second),
   392  				EnvoyGatewayBindTaggedAddresses: true,
   393  				EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
   394  					"_bind1": {
   395  						Address: "10.0.0.4",
   396  						Port:    8000,
   397  					},
   398  				},
   399  				EnvoyGatewayNoDefaultBind: true,
   400  				Config: map[string]interface{}{
   401  					"_config3": 4,
   402  				},
   403  			},
   404  			Ingress: &structs.ConsulIngressConfigEntry{
   405  				TLS: &structs.ConsulGatewayTLSConfig{
   406  					Enabled: true,
   407  				},
   408  				Listeners: []*structs.ConsulIngressListener{{
   409  					Protocol: "_protocol2",
   410  					Port:     8001,
   411  					Services: []*structs.ConsulIngressService{{
   412  						Name:  "_service1",
   413  						Hosts: []string{"_host1", "host2"},
   414  					}},
   415  				}},
   416  			},
   417  		},
   418  	}, connect)
   419  }