github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/network/netplan/netplan_internal_test.go (about)

     1  // Copyright 2021 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package netplan
     5  
     6  import (
     7  	jc "github.com/juju/testing/checkers"
     8  	gc "gopkg.in/check.v1"
     9  	goyaml "gopkg.in/yaml.v2"
    10  )
    11  
    12  type NetplanConfigurationMergeSuite struct {
    13  }
    14  
    15  var _ = gc.Suite(&NetplanConfigurationMergeSuite{})
    16  
    17  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsWithEmptyBaseFile(c *gc.C) {
    18  	base := ``
    19  
    20  	src := `
    21  network:
    22    version: 314
    23    renderer: whateverd
    24    ethernets:
    25      enp5s0:
    26        dhcp4: false
    27  `[1:]
    28  
    29  	s.assertMergeResult(c, base, src, src)
    30  }
    31  
    32  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsWithEmptySourceFile(c *gc.C) {
    33  	base := `
    34  network:
    35    renderer: networkd
    36    version: 2
    37    ethernets:
    38      enp5s0:
    39        dhcp4: true
    40        optional: true
    41  `[1:]
    42  
    43  	src := ``
    44  
    45  	s.assertMergeResult(c, base, src, base)
    46  }
    47  
    48  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsScalarValuOverwrite(c *gc.C) {
    49  	base := `
    50  network:
    51    renderer: networkd
    52    version: 2
    53    ethernets:
    54      enp5s0:
    55        dhcp4: true
    56        optional: true
    57  `[1:]
    58  
    59  	src := `
    60  network:
    61    version: 314        # Overwrite numeric value
    62    renderer: whateverd # Overwrite string value
    63    ethernets:
    64      enp5s0:
    65        dhcp4: false    # Overwrite bool value
    66  `[1:]
    67  
    68  	exp := `
    69  network:
    70    version: 314
    71    renderer: whateverd
    72    ethernets:
    73      enp5s0:
    74        dhcp4: false
    75        optional: true
    76  `[1:]
    77  
    78  	s.assertMergeResult(c, base, src, exp)
    79  }
    80  
    81  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsMergeMapValues(c *gc.C) {
    82  	base := `
    83  network:
    84    renderer: networkd
    85    version: 2
    86    ethernets:
    87      enp5s0:
    88        dhcp4: true
    89        optional: true
    90        nameservers:
    91          addresses:
    92          - 1.1.1.1
    93          - 8.8.8.8
    94  `[1:]
    95  
    96  	src := `
    97  network:
    98    ethernets:
    99      newnic0:            # Add a new key to the map
   100        dhcp4: true
   101      enp5s0:
   102        dhcp4: false      # Overwrite value of existing key
   103        optional: true
   104        nameservers:
   105          search: [foo.local, baz.local] # Add new key to nested, existing map
   106  `[1:]
   107  
   108  	exp := `
   109  network:
   110    renderer: networkd
   111    version: 2
   112    ethernets:
   113      enp5s0:
   114        dhcp4: false
   115        optional: true
   116        nameservers:
   117          addresses:
   118          - 1.1.1.1
   119          - 8.8.8.8
   120          search:
   121          - foo.local
   122          - baz.local
   123      newnic0:
   124        dhcp4: true
   125  `[1:]
   126  
   127  	s.assertMergeResult(c, base, src, exp)
   128  }
   129  
   130  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsSliceConcatenation(c *gc.C) {
   131  	base := `
   132  network:
   133    ethernets:
   134      enp5s0:
   135        nameservers:
   136          addresses:
   137          - 1.1.1.1
   138          - 8.8.8.8
   139  `[1:]
   140  
   141  	src := `
   142  network:
   143    ethernets:
   144      enp5s0:
   145        nameservers:
   146          addresses:
   147          - 8.8.8.8     # Value already exists in base sequence and should be skipped
   148          - 42.42.42.42 # Value does not exist in base sequence and should be added
   149          - 1.1.1.1     # Value already exists in base sequence and should be skipped
   150  `[1:]
   151  
   152  	exp := `
   153  network:
   154    ethernets:
   155      enp5s0:
   156        nameservers:
   157          addresses:
   158          - 1.1.1.1
   159          - 8.8.8.8
   160          - 42.42.42.42
   161  `[1:]
   162  
   163  	s.assertMergeResult(c, base, src, exp)
   164  }
   165  
   166  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsErrorsWhenMergingMaps(c *gc.C) {
   167  	base := `
   168  network:
   169    ethernets:
   170      enp5s0:
   171        nameservers:
   172          addresses:
   173          - 1.1.1.1
   174          - 8.8.8.8
   175  `[1:]
   176  
   177  	src := `
   178  network:
   179    ethernets: "this is not the map you are looking for"
   180  `[1:]
   181  
   182  	s.assertMergeError(c, base, src, `merging configuration key "network": merging configuration key "ethernets": configuration values have different types \(destination: map.*, src: string\)`)
   183  }
   184  
   185  func (s *NetplanConfigurationMergeSuite) TestMergeNetplanConfigsErrorsWhenMergingSlices(c *gc.C) {
   186  	base := `
   187  network:
   188    ethernets:
   189      enp5s0:
   190        nameservers:
   191          addresses:
   192          - 1.1.1.1
   193          - 8.8.8.8
   194  `[1:]
   195  
   196  	src := `
   197  network:
   198    ethernets:
   199      enp5s0:
   200        nameservers:
   201          addresses: "this is not the slice you are looking for"
   202  `[1:]
   203  
   204  	s.assertMergeError(c, base, src, `merging configuration key "network": merging configuration key "ethernets": merging configuration key "enp5s0": merging configuration key "nameservers": merging configuration key "addresses": configuration values have different types \(destination: \[\].*, src: string\)`)
   205  }
   206  
   207  func (s *NetplanConfigurationMergeSuite) assertMergeResult(c *gc.C, base, src, exp string) {
   208  	var (
   209  		baseMap, srcMap, expMap map[interface{}]interface{}
   210  	)
   211  
   212  	c.Assert(goyaml.Unmarshal([]byte(base), &baseMap), jc.ErrorIsNil)
   213  	c.Assert(goyaml.Unmarshal([]byte(src), &srcMap), jc.ErrorIsNil)
   214  	c.Assert(goyaml.Unmarshal([]byte(exp), &expMap), jc.ErrorIsNil)
   215  
   216  	mergeRes, err := mergeNetplanConfigs(baseMap, srcMap)
   217  	c.Assert(err, jc.ErrorIsNil)
   218  
   219  	mergeResMap, ok := mergeRes.(map[interface{}]interface{})
   220  	c.Assert(ok, jc.IsTrue, gc.Commentf("expected merge result to be a map[interface{}]interface{}; got %T", mergeRes))
   221  	c.Assert(mergeResMap, gc.DeepEquals, expMap)
   222  }
   223  
   224  func (s *NetplanConfigurationMergeSuite) assertMergeError(c *gc.C, base, src, expErr string) {
   225  	var (
   226  		baseMap, srcMap map[interface{}]interface{}
   227  	)
   228  
   229  	c.Assert(goyaml.Unmarshal([]byte(base), &baseMap), jc.ErrorIsNil)
   230  	c.Assert(goyaml.Unmarshal([]byte(src), &srcMap), jc.ErrorIsNil)
   231  
   232  	_, err := mergeNetplanConfigs(baseMap, srcMap)
   233  	c.Assert(err, gc.ErrorMatches, expErr)
   234  }