github.com/connyay/libcompose@v0.4.0/config/interpolation_test.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"gopkg.in/yaml.v2"
    10  )
    11  
    12  func testInterpolatedLine(t *testing.T, expectedLine, interpolatedLine string, envVariables map[string]string) {
    13  	interpolatedLine, _ = parseLine(interpolatedLine, func(s string) string {
    14  		return envVariables[s]
    15  	})
    16  
    17  	assert.Equal(t, expectedLine, interpolatedLine)
    18  }
    19  
    20  func testInvalidInterpolatedLine(t *testing.T, line string) {
    21  	_, success := parseLine(line, func(string) string {
    22  		return ""
    23  	})
    24  
    25  	assert.Equal(t, false, success)
    26  }
    27  
    28  func TestParseLine(t *testing.T) {
    29  	variables := map[string]string{
    30  		"A":           "ABC",
    31  		"X":           "XYZ",
    32  		"E":           "",
    33  		"lower":       "WORKED",
    34  		"MiXeD":       "WORKED",
    35  		"split_VaLue": "WORKED",
    36  		"9aNumber":    "WORKED",
    37  		"a9Number":    "WORKED",
    38  	}
    39  
    40  	testInterpolatedLine(t, "WORKED", "$lower", variables)
    41  	testInterpolatedLine(t, "WORKED", "${MiXeD}", variables)
    42  	testInterpolatedLine(t, "WORKED", "${split_VaLue}", variables)
    43  	// Starting with a number isn't valid
    44  	testInterpolatedLine(t, "", "$9aNumber", variables)
    45  	testInterpolatedLine(t, "WORKED", "$a9Number", variables)
    46  
    47  	testInterpolatedLine(t, "ABC", "$A", variables)
    48  	testInterpolatedLine(t, "ABC", "${A}", variables)
    49  
    50  	testInterpolatedLine(t, "ABC DE", "$A DE", variables)
    51  	testInterpolatedLine(t, "ABCDE", "${A}DE", variables)
    52  
    53  	testInterpolatedLine(t, "$A", "$$A", variables)
    54  	testInterpolatedLine(t, "${A}", "$${A}", variables)
    55  
    56  	testInterpolatedLine(t, "$ABC", "$$${A}", variables)
    57  	testInterpolatedLine(t, "$ABC", "$$$A", variables)
    58  
    59  	testInterpolatedLine(t, "ABC XYZ", "$A $X", variables)
    60  	testInterpolatedLine(t, "ABCXYZ", "$A$X", variables)
    61  	testInterpolatedLine(t, "ABCXYZ", "${A}${X}", variables)
    62  
    63  	testInterpolatedLine(t, "", "$B", variables)
    64  	testInterpolatedLine(t, "", "${B}", variables)
    65  	testInterpolatedLine(t, "", "$ADE", variables)
    66  
    67  	testInterpolatedLine(t, "", "$E", variables)
    68  	testInterpolatedLine(t, "", "${E}", variables)
    69  
    70  	testInvalidInterpolatedLine(t, "${")
    71  	testInvalidInterpolatedLine(t, "$}")
    72  	testInvalidInterpolatedLine(t, "${}")
    73  	testInvalidInterpolatedLine(t, "${ }")
    74  	testInvalidInterpolatedLine(t, "${A }")
    75  	testInvalidInterpolatedLine(t, "${ A}")
    76  	testInvalidInterpolatedLine(t, "${A!}")
    77  	testInvalidInterpolatedLine(t, "$!")
    78  }
    79  
    80  type MockEnvironmentLookup struct {
    81  	Variables map[string]string
    82  }
    83  
    84  func (m MockEnvironmentLookup) Lookup(key string, config *ServiceConfig) []string {
    85  	return []string{fmt.Sprintf("%s=%s", key, m.Variables[key])}
    86  }
    87  
    88  func testInterpolatedConfig(t *testing.T, expectedConfig, interpolatedConfig string, envVariables map[string]string) {
    89  	for k, v := range envVariables {
    90  		os.Setenv(k, v)
    91  	}
    92  
    93  	expectedConfigBytes := []byte(expectedConfig)
    94  	interpolatedConfigBytes := []byte(interpolatedConfig)
    95  
    96  	expectedData := make(RawServiceMap)
    97  	interpolatedData := make(RawServiceMap)
    98  
    99  	yaml.Unmarshal(expectedConfigBytes, &expectedData)
   100  	yaml.Unmarshal(interpolatedConfigBytes, &interpolatedData)
   101  
   102  	_ = InterpolateRawServiceMap(&interpolatedData, MockEnvironmentLookup{envVariables})
   103  
   104  	for k := range envVariables {
   105  		os.Unsetenv(k)
   106  	}
   107  
   108  	assert.Equal(t, expectedData, interpolatedData)
   109  }
   110  
   111  func testInvalidInterpolatedConfig(t *testing.T, interpolatedConfig string) {
   112  	interpolatedConfigBytes := []byte(interpolatedConfig)
   113  	interpolatedData := make(RawServiceMap)
   114  	yaml.Unmarshal(interpolatedConfigBytes, &interpolatedData)
   115  
   116  	err := InterpolateRawServiceMap(&interpolatedData, new(MockEnvironmentLookup))
   117  	assert.NotNil(t, err)
   118  }
   119  
   120  func TestInterpolate(t *testing.T) {
   121  	testInterpolatedConfig(t,
   122  		`web:
   123    # unbracketed name
   124    image: busybox
   125  
   126    # array element
   127    ports:
   128      - "80:8000"
   129  
   130    # dictionary item value
   131    labels:
   132      mylabel: "myvalue"
   133  
   134    # unset value
   135    hostname: "host-"
   136  
   137    # escaped interpolation
   138    command: "${ESCAPED}"`,
   139  		`web:
   140    # unbracketed name
   141    image: $IMAGE
   142  
   143    # array element
   144    ports:
   145      - "${HOST_PORT}:8000"
   146  
   147    # dictionary item value
   148    labels:
   149      mylabel: "${LABEL_VALUE}"
   150  
   151    # unset value
   152    hostname: "host-${UNSET_VALUE}"
   153  
   154    # escaped interpolation
   155    command: "$${ESCAPED}"`, map[string]string{
   156  			"IMAGE":       "busybox",
   157  			"HOST_PORT":   "80",
   158  			"LABEL_VALUE": "myvalue",
   159  		})
   160  
   161  	// Same as above, but testing with equal signs in variables
   162  	testInterpolatedConfig(t,
   163  		`web:
   164    # unbracketed name
   165    image: =busybox
   166  
   167    # array element
   168    ports:
   169      - "=:8000"
   170  
   171    # dictionary item value
   172    labels:
   173      mylabel: "myvalue=="
   174  
   175    # unset value
   176    hostname: "host-"
   177  
   178    # escaped interpolation
   179    command: "${ESCAPED}"`,
   180  		`web:
   181    # unbracketed name
   182    image: $IMAGE
   183  
   184    # array element
   185    ports:
   186      - "${HOST_PORT}:8000"
   187  
   188    # dictionary item value
   189    labels:
   190      mylabel: "${LABEL_VALUE}"
   191  
   192    # unset value
   193    hostname: "host-${UNSET_VALUE}"
   194  
   195    # escaped interpolation
   196    command: "$${ESCAPED}"`, map[string]string{
   197  			"IMAGE":       "=busybox",
   198  			"HOST_PORT":   "=",
   199  			"LABEL_VALUE": "myvalue==",
   200  		})
   201  
   202  	testInvalidInterpolatedConfig(t,
   203  		`web:
   204    image: "${"`)
   205  
   206  	testInvalidInterpolatedConfig(t,
   207  		`web:
   208    image: busybox
   209  
   210    # array element
   211    ports:
   212      - "${}:8000"`)
   213  
   214  	testInvalidInterpolatedConfig(t,
   215  		`web:
   216    image: busybox
   217  
   218    # array element
   219    ports:
   220      - "80:8000"
   221  
   222    # dictionary item value
   223    labels:
   224      mylabel: "${ LABEL_VALUE}"`)
   225  }