| @@ -1,6 +1,9 @@ | ||||
| package initialize | ||||
|  | ||||
| import "encoding/json" | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"sort" | ||||
| ) | ||||
|  | ||||
| // ParseMetaData parses a JSON blob in the OpenStack metadata service format, and | ||||
| // converts it to a partially hydrated CloudConfig | ||||
| @@ -22,8 +25,8 @@ func ParseMetaData(contents string) (*CloudConfig, error) { | ||||
| 	var cfg CloudConfig | ||||
| 	if len(metadata.SSHAuthorizedKeyMap) > 0 { | ||||
| 		cfg.SSHAuthorizedKeys = make([]string, 0, len(metadata.SSHAuthorizedKeyMap)) | ||||
| 		for _, key := range metadata.SSHAuthorizedKeyMap { | ||||
| 			cfg.SSHAuthorizedKeys = append(cfg.SSHAuthorizedKeys, key) | ||||
| 		for _, name := range sortedKeys(metadata.SSHAuthorizedKeyMap) { | ||||
| 			cfg.SSHAuthorizedKeys = append(cfg.SSHAuthorizedKeys, metadata.SSHAuthorizedKeyMap[name]) | ||||
| 		} | ||||
| 	} | ||||
| 	cfg.Hostname = metadata.Hostname | ||||
| @@ -50,3 +53,11 @@ func ExtractIPsFromMetadata(contents []byte) (map[string]string, error) { | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func sortedKeys(m map[string]string) (keys []string) { | ||||
| 	for key := range m { | ||||
| 		keys = append(keys, key) | ||||
| 	} | ||||
| 	sort.Strings(keys) | ||||
| 	return | ||||
| } | ||||
|   | ||||
| @@ -14,7 +14,7 @@ func TestParseMetadata(t *testing.T) { | ||||
| 		{`{"foo": "bar"}`, &CloudConfig{}, false}, | ||||
| 		{`{"network_config": {"content_path": "asdf"}}`, &CloudConfig{NetworkConfigPath: "asdf"}, false}, | ||||
| 		{`{"hostname": "turkleton"}`, &CloudConfig{Hostname: "turkleton"}, false}, | ||||
| 		{`{"public_keys": {"jack": "jill", "bob": "alice"}}`, &CloudConfig{SSHAuthorizedKeys: []string{"jill", "alice"}}, false}, | ||||
| 		{`{"public_keys": {"jack": "jill", "bob": "alice"}}`, &CloudConfig{SSHAuthorizedKeys: []string{"alice", "jill"}}, false}, | ||||
| 		{`{"unknown": "thing", "hostname": "my_host", "public_keys": {"do": "re", "mi": "fa"}, "network_config": {"content_path": "/root", "blah": "zzz"}}`, &CloudConfig{SSHAuthorizedKeys: []string{"re", "fa"}, Hostname: "my_host", NetworkConfigPath: "/root"}, false}, | ||||
| 	} { | ||||
| 		got, err := ParseMetaData(tt.in) | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sort" | ||||
| ) | ||||
|  | ||||
| type InterfaceGenerator interface { | ||||
| @@ -115,8 +116,8 @@ func (b *bondInterface) Type() string { | ||||
|  | ||||
| func (b *bondInterface) ModprobeParams() string { | ||||
| 	params := "" | ||||
| 	for name, val := range b.options { | ||||
| 		params += fmt.Sprintf("%s=%s ", name, val) | ||||
| 	for _, name := range sortedKeys(b.options) { | ||||
| 		params += fmt.Sprintf("%s=%s ", name, b.options[name]) | ||||
| 	} | ||||
| 	params = strings.TrimSuffix(params, " ") | ||||
| 	return params | ||||
| @@ -158,8 +159,8 @@ func buildInterfaces(stanzas []*stanzaInterface) []InterfaceGenerator { | ||||
| 	markConfigDepths(interfaceMap) | ||||
|  | ||||
| 	interfaces := make([]InterfaceGenerator, 0, len(interfaceMap)) | ||||
| 	for _, iface := range interfaceMap { | ||||
| 		interfaces = append(interfaces, iface) | ||||
| 	for _, name := range sortedInterfaces(interfaceMap) { | ||||
| 		interfaces = append(interfaces, interfaceMap[name]) | ||||
| 	} | ||||
|  | ||||
| 	return interfaces | ||||
| @@ -239,7 +240,8 @@ func createInterfaces(stanzas []*stanzaInterface) map[string]networkInterface { | ||||
| } | ||||
|  | ||||
| func linkAncestors(interfaceMap map[string]networkInterface) { | ||||
| 	for _, iface := range interfaceMap { | ||||
| 	for _, name := range sortedInterfaces(interfaceMap) { | ||||
| 		iface := interfaceMap[name] | ||||
| 		switch i := iface.(type) { | ||||
| 		case *vlanInterface: | ||||
| 			if parent, ok := interfaceMap[i.rawDevice]; ok { | ||||
| @@ -291,3 +293,19 @@ func setDepth(iface networkInterface) int { | ||||
| 	iface.setConfigDepth(maxDepth) | ||||
| 	return (maxDepth + 1) | ||||
| } | ||||
|  | ||||
| func sortedKeys(m map[string]string) (keys []string) { | ||||
| 	for key := range m { | ||||
| 		keys = append(keys, key) | ||||
| 	} | ||||
| 	sort.Strings(keys) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func sortedInterfaces(m map[string]networkInterface) (keys []string) { | ||||
| 	for key := range m { | ||||
| 		keys = append(keys, key) | ||||
| 	} | ||||
| 	sort.Strings(keys) | ||||
| 	return | ||||
| } | ||||
|   | ||||
| @@ -469,7 +469,7 @@ func TestBuildInterfaces(t *testing.T) { | ||||
| 			configDepth: 2, | ||||
| 		}, | ||||
| 	} | ||||
| 	expect := []InterfaceGenerator{eth0, bond0, bond1, vlan0, vlan1} | ||||
| 	expect := []InterfaceGenerator{bond0, bond1, eth0, vlan0, vlan1} | ||||
| 	if !reflect.DeepEqual(interfaces, expect) { | ||||
| 		t.FailNow() | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user