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 }