datasource: replace metadata map with struct
The loosely-typed metadata map is a load of crap. Make it a struct and let the compiler help us out.
This commit is contained in:
@@ -24,6 +24,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/cloudsigma/cepgo"
|
||||
)
|
||||
|
||||
@@ -69,7 +71,7 @@ func (_ *serverContextService) Type() string {
|
||||
return "server-context"
|
||||
}
|
||||
|
||||
func (scs *serverContextService) FetchMetadata() ([]byte, error) {
|
||||
func (scs *serverContextService) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
var (
|
||||
inputMetadata struct {
|
||||
Name string `json:"name"`
|
||||
@@ -88,48 +90,41 @@ func (scs *serverContextService) FetchMetadata() ([]byte, error) {
|
||||
} `json:"vlan"`
|
||||
} `json:"nics"`
|
||||
}
|
||||
outputMetadata struct {
|
||||
Hostname string `json:"name"`
|
||||
PublicKeys map[string]string `json:"public_keys"`
|
||||
LocalIPv4 string `json:"local-ipv4"`
|
||||
PublicIPv4 string `json:"public-ipv4"`
|
||||
}
|
||||
rawMetadata []byte
|
||||
)
|
||||
|
||||
rawMetadata, err := scs.client.FetchRaw("")
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
if rawMetadata, err = scs.client.FetchRaw(""); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawMetadata, &inputMetadata)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
if err = json.Unmarshal(rawMetadata, &inputMetadata); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if inputMetadata.Name != "" {
|
||||
outputMetadata.Hostname = inputMetadata.Name
|
||||
metadata.Hostname = inputMetadata.Name
|
||||
} else {
|
||||
outputMetadata.Hostname = inputMetadata.UUID
|
||||
metadata.Hostname = inputMetadata.UUID
|
||||
}
|
||||
|
||||
metadata.SSHPublicKeys = map[string]string{}
|
||||
if key, ok := inputMetadata.Meta["ssh_public_key"]; ok {
|
||||
splitted := strings.Split(key, " ")
|
||||
outputMetadata.PublicKeys = make(map[string]string)
|
||||
outputMetadata.PublicKeys[splitted[len(splitted)-1]] = key
|
||||
metadata.SSHPublicKeys[splitted[len(splitted)-1]] = key
|
||||
}
|
||||
|
||||
for _, nic := range inputMetadata.Nics {
|
||||
if nic.IPv4Conf.IP.UUID != "" {
|
||||
outputMetadata.PublicIPv4 = nic.IPv4Conf.IP.UUID
|
||||
metadata.PublicIPv4 = net.ParseIP(nic.IPv4Conf.IP.UUID)
|
||||
}
|
||||
if nic.VLAN.UUID != "" {
|
||||
if localIP, err := scs.findLocalIP(nic.Mac); err == nil {
|
||||
outputMetadata.LocalIPv4 = localIP
|
||||
metadata.PrivateIPv4 = localIP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json.Marshal(outputMetadata)
|
||||
return
|
||||
}
|
||||
|
||||
func (scs *serverContextService) FetchUserdata() ([]byte, error) {
|
||||
@@ -154,14 +149,14 @@ func (scs *serverContextService) FetchNetworkConfig(a string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (scs *serverContextService) findLocalIP(mac string) (string, error) {
|
||||
func (scs *serverContextService) findLocalIP(mac string) (net.IP, error) {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
ifaceMac, err := net.ParseMAC(mac)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
if !bytes.Equal(iface.HardwareAddr, ifaceMac) {
|
||||
@@ -176,12 +171,12 @@ func (scs *serverContextService) findLocalIP(mac string) (string, error) {
|
||||
switch ip := addr.(type) {
|
||||
case *net.IPNet:
|
||||
if ip.IP.To4() != nil {
|
||||
return ip.IP.To4().String(), nil
|
||||
return ip.IP.To4(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", errors.New("Local IP not found")
|
||||
return nil, errors.New("Local IP not found")
|
||||
}
|
||||
|
||||
func isBase64Encoded(field string, userdata map[string]string) bool {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
package cloudsigma
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
@@ -44,12 +44,6 @@ func (f *fakeCepgoClient) FetchRaw(key string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func TestServerContextFetchMetadata(t *testing.T) {
|
||||
var metadata struct {
|
||||
Hostname string `json:"name"`
|
||||
PublicKeys map[string]string `json:"public_keys"`
|
||||
LocalIPv4 string `json:"local-ipv4"`
|
||||
PublicIPv4 string `json:"public-ipv4"`
|
||||
}
|
||||
client := new(fakeCepgoClient)
|
||||
scs := NewServerContextService()
|
||||
scs.client = client
|
||||
@@ -114,24 +108,20 @@ func TestServerContextFetchMetadata(t *testing.T) {
|
||||
"uuid": "20a0059b-041e-4d0c-bcc6-9b2852de48b3"
|
||||
}`)
|
||||
|
||||
metadataBytes, err := scs.FetchMetadata()
|
||||
metadata, err := scs.FetchMetadata()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(metadataBytes, &metadata); err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
if metadata.Hostname != "coreos" {
|
||||
t.Errorf("Hostname is not 'coreos' but %s instead", metadata.Hostname)
|
||||
}
|
||||
|
||||
if metadata.PublicKeys["john@doe"] != "ssh-rsa AAAAB3NzaC1yc2E.../hQ5D5 john@doe" {
|
||||
if metadata.SSHPublicKeys["john@doe"] != "ssh-rsa AAAAB3NzaC1yc2E.../hQ5D5 john@doe" {
|
||||
t.Error("Public SSH Keys are not being read properly")
|
||||
}
|
||||
|
||||
if metadata.PublicIPv4 != "31.171.251.74" {
|
||||
if !metadata.PublicIPv4.Equal(net.ParseIP("31.171.251.74")) {
|
||||
t.Errorf("Public IP is not 31.171.251.74 but %s instead", metadata.PublicIPv4)
|
||||
}
|
||||
}
|
||||
|
@@ -16,8 +16,10 @@ package digitalocean
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
)
|
||||
|
||||
@@ -68,45 +70,43 @@ func NewDatasource(root string) *metadataService {
|
||||
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath)}
|
||||
}
|
||||
|
||||
func (ms *metadataService) FetchMetadata() ([]byte, error) {
|
||||
data, err := ms.FetchData(ms.MetadataUrl())
|
||||
if err != nil || len(data) == 0 {
|
||||
return []byte{}, err
|
||||
func (ms *metadataService) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
var data []byte
|
||||
var m Metadata
|
||||
|
||||
if data, err = ms.FetchData(ms.MetadataUrl()); err != nil || len(data) == 0 {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &m); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var metadata Metadata
|
||||
if err := json.Unmarshal(data, &metadata); err != nil {
|
||||
return []byte{}, err
|
||||
ms.interfaces = m.Interfaces
|
||||
ms.dns = m.DNS
|
||||
|
||||
if len(m.Interfaces.Public) > 0 {
|
||||
if m.Interfaces.Public[0].IPv4 != nil {
|
||||
metadata.PublicIPv4 = net.ParseIP(m.Interfaces.Public[0].IPv4.IPAddress)
|
||||
}
|
||||
if m.Interfaces.Public[0].IPv6 != nil {
|
||||
metadata.PublicIPv6 = net.ParseIP(m.Interfaces.Public[0].IPv6.IPAddress)
|
||||
}
|
||||
}
|
||||
if len(m.Interfaces.Private) > 0 {
|
||||
if m.Interfaces.Private[0].IPv4 != nil {
|
||||
metadata.PrivateIPv4 = net.ParseIP(m.Interfaces.Private[0].IPv4.IPAddress)
|
||||
}
|
||||
if m.Interfaces.Private[0].IPv6 != nil {
|
||||
metadata.PrivateIPv6 = net.ParseIP(m.Interfaces.Private[0].IPv6.IPAddress)
|
||||
}
|
||||
}
|
||||
metadata.Hostname = m.Hostname
|
||||
metadata.SSHPublicKeys = map[string]string{}
|
||||
for i, key := range m.PublicKeys {
|
||||
metadata.SSHPublicKeys[strconv.Itoa(i)] = key
|
||||
}
|
||||
|
||||
ms.interfaces = metadata.Interfaces
|
||||
ms.dns = metadata.DNS
|
||||
|
||||
attrs := make(map[string]interface{})
|
||||
if len(metadata.Interfaces.Public) > 0 {
|
||||
if metadata.Interfaces.Public[0].IPv4 != nil {
|
||||
attrs["public-ipv4"] = metadata.Interfaces.Public[0].IPv4.IPAddress
|
||||
}
|
||||
if metadata.Interfaces.Public[0].IPv6 != nil {
|
||||
attrs["public-ipv6"] = metadata.Interfaces.Public[0].IPv6.IPAddress
|
||||
}
|
||||
}
|
||||
if len(metadata.Interfaces.Private) > 0 {
|
||||
if metadata.Interfaces.Private[0].IPv4 != nil {
|
||||
attrs["local-ipv4"] = metadata.Interfaces.Private[0].IPv4.IPAddress
|
||||
}
|
||||
if metadata.Interfaces.Private[0].IPv6 != nil {
|
||||
attrs["local-ipv6"] = metadata.Interfaces.Private[0].IPv6.IPAddress
|
||||
}
|
||||
}
|
||||
attrs["hostname"] = metadata.Hostname
|
||||
keys := make(map[string]string)
|
||||
for i, key := range metadata.PublicKeys {
|
||||
keys[strconv.Itoa(i)] = key
|
||||
}
|
||||
attrs["public_keys"] = keys
|
||||
|
||||
return json.Marshal(attrs)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms metadataService) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
|
@@ -15,10 +15,12 @@
|
||||
package digitalocean
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
@@ -36,7 +38,7 @@ func TestFetchMetadata(t *testing.T) {
|
||||
root string
|
||||
metadataPath string
|
||||
resources map[string]string
|
||||
expect []byte
|
||||
expect datasource.Metadata
|
||||
clientErr error
|
||||
expectErr error
|
||||
}{
|
||||
@@ -81,7 +83,14 @@ func TestFetchMetadata(t *testing.T) {
|
||||
}
|
||||
}`,
|
||||
},
|
||||
expect: []byte(`{"hostname":"","public-ipv4":"192.168.1.2","public-ipv6":"fe00::","public_keys":{"0":"publickey1","1":"publickey2"}}`),
|
||||
expect: datasource.Metadata{
|
||||
PublicIPv4: net.ParseIP("192.168.1.2"),
|
||||
PublicIPv6: net.ParseIP("fe00::"),
|
||||
SSHPublicKeys: map[string]string{
|
||||
"0": "publickey1",
|
||||
"1": "publickey2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
@@ -99,8 +108,8 @@ func TestFetchMetadata(t *testing.T) {
|
||||
if Error(err) != Error(tt.expectErr) {
|
||||
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
||||
}
|
||||
if !bytes.Equal(metadata, tt.expect) {
|
||||
t.Fatalf("bad fetch (%q): want %q, got %q", tt.resources, tt.expect, metadata)
|
||||
if !reflect.DeepEqual(tt.expect, metadata) {
|
||||
t.Fatalf("bad fetch (%q): want %#q, got %#q", tt.resources, tt.expect, metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,10 +17,11 @@ package ec2
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
)
|
||||
@@ -40,59 +41,57 @@ func NewDatasource(root string) *metadataService {
|
||||
return &metadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath)}
|
||||
}
|
||||
|
||||
func (ms metadataService) FetchMetadata() ([]byte, error) {
|
||||
attrs := make(map[string]interface{})
|
||||
func (ms metadataService) FetchMetadata() (datasource.Metadata, error) {
|
||||
metadata := datasource.Metadata{}
|
||||
|
||||
if keynames, err := ms.fetchAttributes(fmt.Sprintf("%s/public-keys", ms.MetadataUrl())); err == nil {
|
||||
keyIDs := make(map[string]string)
|
||||
for _, keyname := range keynames {
|
||||
tokens := strings.SplitN(keyname, "=", 2)
|
||||
if len(tokens) != 2 {
|
||||
return nil, fmt.Errorf("malformed public key: %q", keyname)
|
||||
return metadata, fmt.Errorf("malformed public key: %q", keyname)
|
||||
}
|
||||
keyIDs[tokens[1]] = tokens[0]
|
||||
}
|
||||
|
||||
keys := make(map[string]string)
|
||||
metadata.SSHPublicKeys = map[string]string{}
|
||||
for name, id := range keyIDs {
|
||||
sshkey, err := ms.fetchAttribute(fmt.Sprintf("%s/public-keys/%s/openssh-key", ms.MetadataUrl(), id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return metadata, err
|
||||
}
|
||||
keys[name] = sshkey
|
||||
metadata.SSHPublicKeys[name] = sshkey
|
||||
fmt.Printf("Found SSH key for %q\n", name)
|
||||
}
|
||||
attrs["public_keys"] = keys
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return nil, err
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
if hostname, err := ms.fetchAttribute(fmt.Sprintf("%s/hostname", ms.MetadataUrl())); err == nil {
|
||||
attrs["hostname"] = strings.Split(hostname, " ")[0]
|
||||
metadata.Hostname = strings.Split(hostname, " ")[0]
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return nil, err
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
if localAddr, err := ms.fetchAttribute(fmt.Sprintf("%s/local-ipv4", ms.MetadataUrl())); err == nil {
|
||||
attrs["local-ipv4"] = localAddr
|
||||
metadata.PrivateIPv4 = net.ParseIP(localAddr)
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return nil, err
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
if publicAddr, err := ms.fetchAttribute(fmt.Sprintf("%s/public-ipv4", ms.MetadataUrl())); err == nil {
|
||||
attrs["public-ipv4"] = publicAddr
|
||||
metadata.PublicIPv4 = net.ParseIP(publicAddr)
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return nil, err
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
if content_path, err := ms.fetchAttribute(fmt.Sprintf("%s/network_config/content_path", ms.MetadataUrl())); err == nil {
|
||||
attrs["network_config"] = map[string]string{
|
||||
"content_path": content_path,
|
||||
}
|
||||
if contentPath, err := ms.fetchAttribute(fmt.Sprintf("%s/network_config/content_path", ms.MetadataUrl())); err == nil {
|
||||
metadata.NetworkConfigPath = contentPath
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return nil, err
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
return json.Marshal(attrs)
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
func (ms metadataService) Type() string {
|
||||
|
@@ -15,11 +15,12 @@
|
||||
package ec2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
@@ -145,7 +146,7 @@ func TestFetchMetadata(t *testing.T) {
|
||||
root string
|
||||
metadataPath string
|
||||
resources map[string]string
|
||||
expect []byte
|
||||
expect datasource.Metadata
|
||||
clientErr error
|
||||
expectErr error
|
||||
}{
|
||||
@@ -169,7 +170,13 @@ func TestFetchMetadata(t *testing.T) {
|
||||
"/2009-04-04/meta-data/public-keys/0/openssh-key": "key",
|
||||
"/2009-04-04/meta-data/network_config/content_path": "path",
|
||||
},
|
||||
expect: []byte(`{"hostname":"host","local-ipv4":"1.2.3.4","network_config":{"content_path":"path"},"public-ipv4":"5.6.7.8","public_keys":{"test1":"key"}}`),
|
||||
expect: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
PrivateIPv4: net.ParseIP("1.2.3.4"),
|
||||
PublicIPv4: net.ParseIP("5.6.7.8"),
|
||||
SSHPublicKeys: map[string]string{"test1": "key"},
|
||||
NetworkConfigPath: "path",
|
||||
},
|
||||
},
|
||||
{
|
||||
root: "/",
|
||||
@@ -183,7 +190,13 @@ func TestFetchMetadata(t *testing.T) {
|
||||
"/2009-04-04/meta-data/public-keys/0/openssh-key": "key",
|
||||
"/2009-04-04/meta-data/network_config/content_path": "path",
|
||||
},
|
||||
expect: []byte(`{"hostname":"host","local-ipv4":"1.2.3.4","network_config":{"content_path":"path"},"public-ipv4":"5.6.7.8","public_keys":{"test1":"key"}}`),
|
||||
expect: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
PrivateIPv4: net.ParseIP("1.2.3.4"),
|
||||
PublicIPv4: net.ParseIP("5.6.7.8"),
|
||||
SSHPublicKeys: map[string]string{"test1": "key"},
|
||||
NetworkConfigPath: "path",
|
||||
},
|
||||
},
|
||||
{
|
||||
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
@@ -199,8 +212,8 @@ func TestFetchMetadata(t *testing.T) {
|
||||
if Error(err) != Error(tt.expectErr) {
|
||||
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
||||
}
|
||||
if !bytes.Equal(metadata, tt.expect) {
|
||||
t.Fatalf("bad fetch (%q): want %q, got %q", tt.resources, tt.expect, metadata)
|
||||
if !reflect.DeepEqual(tt.expect, metadata) {
|
||||
t.Fatalf("bad fetch (%q): want %#v, got %#v", tt.resources, tt.expect, metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user