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:
parent
d4c617fc23
commit
3e47c09b41
@ -176,21 +176,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
|
fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
|
||||||
metadataBytes, err := ds.FetchMetadata()
|
metadata, err := ds.FetchMetadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
|
fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract IPv4 addresses from metadata if possible
|
// Extract IPv4 addresses from metadata
|
||||||
var subs map[string]string
|
subs := initialize.ExtractIPsFromMetadata(metadata)
|
||||||
if len(metadataBytes) > 0 {
|
|
||||||
subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply environment to user-data
|
// Apply environment to user-data
|
||||||
env := initialize.NewEnvironment("/", ds.ConfigRoot(), flags.workspace, flags.convertNetconf, flags.sshKeyName, subs)
|
env := initialize.NewEnvironment("/", ds.ConfigRoot(), flags.workspace, flags.convertNetconf, flags.sshKeyName, subs)
|
||||||
@ -198,10 +191,7 @@ func main() {
|
|||||||
|
|
||||||
var ccm, ccu *config.CloudConfig
|
var ccm, ccu *config.CloudConfig
|
||||||
var script *config.Script
|
var script *config.Script
|
||||||
if ccm, err = initialize.ParseMetaData(string(metadataBytes)); err != nil {
|
ccm = initialize.ParseMetaData(metadata)
|
||||||
fmt.Printf("Failed to parse meta-data: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ccm != nil && flags.convertNetconf != "" {
|
if ccm != nil && flags.convertNetconf != "" {
|
||||||
fmt.Printf("Fetching network config from datasource of type %q\n", ds.Type())
|
fmt.Printf("Fetching network config from datasource of type %q\n", ds.Type())
|
||||||
|
@ -15,10 +15,13 @@
|
|||||||
package configdrive
|
package configdrive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -47,8 +50,28 @@ func (cd *configDrive) ConfigRoot() string {
|
|||||||
return cd.openstackRoot()
|
return cd.openstackRoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd *configDrive) FetchMetadata() ([]byte, error) {
|
func (cd *configDrive) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||||
return cd.tryReadFile(path.Join(cd.openstackVersionRoot(), "meta_data.json"))
|
var data []byte
|
||||||
|
var m struct {
|
||||||
|
SSHAuthorizedKeyMap map[string]string `json:"public_keys"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
NetworkConfig struct {
|
||||||
|
ContentPath string `json:"content_path"`
|
||||||
|
} `json:"network_config"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if data, err = cd.tryReadFile(path.Join(cd.openstackVersionRoot(), "meta_data.json")); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal([]byte(data), &m); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.SSHPublicKeys = m.SSHAuthorizedKeyMap
|
||||||
|
metadata.Hostname = m.Hostname
|
||||||
|
metadata.NetworkConfigPath = m.NetworkConfig.ContentPath
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd *configDrive) FetchUserdata() ([]byte, error) {
|
func (cd *configDrive) FetchUserdata() ([]byte, error) {
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
package configdrive
|
package configdrive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/test"
|
"github.com/coreos/coreos-cloudinit/datasource/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,22 +27,28 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
root string
|
root string
|
||||||
files test.MockFilesystem
|
files test.MockFilesystem
|
||||||
|
|
||||||
metadata string
|
metadata datasource.Metadata
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"/",
|
root: "/",
|
||||||
test.MockFilesystem{},
|
files: test.MockFilesystem{"/openstack/latest/meta_data.json": `{"ignore": "me"}`},
|
||||||
"",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/",
|
root: "/",
|
||||||
test.MockFilesystem{"/openstack/latest/meta_data.json": "metadata"},
|
files: test.MockFilesystem{"/openstack/latest/meta_data.json": `{"hostname": "host"}`},
|
||||||
"metadata",
|
metadata: datasource.Metadata{Hostname: "host"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/media/configdrive",
|
root: "/media/configdrive",
|
||||||
test.MockFilesystem{"/media/configdrive/openstack/latest/meta_data.json": "metadata"},
|
files: test.MockFilesystem{"/media/configdrive/openstack/latest/meta_data.json": `{"hostname": "host", "network_config": {"content_path": "path"}, "public_keys":{"1": "key1", "2": "key2"}}`},
|
||||||
"metadata",
|
metadata: datasource.Metadata{
|
||||||
|
Hostname: "host",
|
||||||
|
NetworkConfigPath: "path",
|
||||||
|
SSHPublicKeys: map[string]string{
|
||||||
|
"1": "key1",
|
||||||
|
"2": "key2",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
cd := configDrive{tt.root, tt.files.ReadFile}
|
cd := configDrive{tt.root, tt.files.ReadFile}
|
||||||
@ -48,8 +56,8 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
||||||
}
|
}
|
||||||
if string(metadata) != tt.metadata {
|
if !reflect.DeepEqual(tt.metadata, metadata) {
|
||||||
t.Fatalf("bad path for %q: want %q, got %q", tt, tt.metadata, metadata)
|
t.Fatalf("bad metadata for %q: want %#v, got %#v", tt, tt.metadata, metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,7 +91,7 @@ func TestFetchUserdata(t *testing.T) {
|
|||||||
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
||||||
}
|
}
|
||||||
if string(userdata) != tt.userdata {
|
if string(userdata) != tt.userdata {
|
||||||
t.Fatalf("bad path for %q: want %q, got %q", tt, tt.userdata, userdata)
|
t.Fatalf("bad userdata for %q: want %q, got %q", tt, tt.userdata, userdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,26 @@
|
|||||||
|
|
||||||
package datasource
|
package datasource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
type Datasource interface {
|
type Datasource interface {
|
||||||
IsAvailable() bool
|
IsAvailable() bool
|
||||||
AvailabilityChanges() bool
|
AvailabilityChanges() bool
|
||||||
ConfigRoot() string
|
ConfigRoot() string
|
||||||
FetchMetadata() ([]byte, error)
|
FetchMetadata() (Metadata, error)
|
||||||
FetchUserdata() ([]byte, error)
|
FetchUserdata() ([]byte, error)
|
||||||
FetchNetworkConfig(string) ([]byte, error)
|
FetchNetworkConfig(string) ([]byte, error)
|
||||||
Type() string
|
Type() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Metadata struct {
|
||||||
|
PublicIPv4 net.IP
|
||||||
|
PublicIPv6 net.IP
|
||||||
|
PrivateIPv4 net.IP
|
||||||
|
PrivateIPv6 net.IP
|
||||||
|
Hostname string
|
||||||
|
SSHPublicKeys map[string]string
|
||||||
|
NetworkConfigPath string
|
||||||
|
}
|
||||||
|
@ -17,6 +17,8 @@ package file
|
|||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
)
|
)
|
||||||
|
|
||||||
type localFile struct {
|
type localFile struct {
|
||||||
@ -40,8 +42,8 @@ func (f *localFile) ConfigRoot() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *localFile) FetchMetadata() ([]byte, error) {
|
func (f *localFile) FetchMetadata() (datasource.Metadata, error) {
|
||||||
return []byte{}, nil
|
return datasource.Metadata{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *localFile) FetchUserdata() ([]byte, error) {
|
func (f *localFile) FetchUserdata() ([]byte, error) {
|
||||||
|
@ -24,6 +24,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
|
|
||||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/cloudsigma/cepgo"
|
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/cloudsigma/cepgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ func (_ *serverContextService) Type() string {
|
|||||||
return "server-context"
|
return "server-context"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scs *serverContextService) FetchMetadata() ([]byte, error) {
|
func (scs *serverContextService) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||||
var (
|
var (
|
||||||
inputMetadata struct {
|
inputMetadata struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -88,48 +90,41 @@ func (scs *serverContextService) FetchMetadata() ([]byte, error) {
|
|||||||
} `json:"vlan"`
|
} `json:"vlan"`
|
||||||
} `json:"nics"`
|
} `json:"nics"`
|
||||||
}
|
}
|
||||||
outputMetadata struct {
|
rawMetadata []byte
|
||||||
Hostname string `json:"name"`
|
|
||||||
PublicKeys map[string]string `json:"public_keys"`
|
|
||||||
LocalIPv4 string `json:"local-ipv4"`
|
|
||||||
PublicIPv4 string `json:"public-ipv4"`
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
rawMetadata, err := scs.client.FetchRaw("")
|
if rawMetadata, err = scs.client.FetchRaw(""); err != nil {
|
||||||
if err != nil {
|
return
|
||||||
return []byte{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(rawMetadata, &inputMetadata)
|
if err = json.Unmarshal(rawMetadata, &inputMetadata); err != nil {
|
||||||
if err != nil {
|
return
|
||||||
return []byte{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if inputMetadata.Name != "" {
|
if inputMetadata.Name != "" {
|
||||||
outputMetadata.Hostname = inputMetadata.Name
|
metadata.Hostname = inputMetadata.Name
|
||||||
} else {
|
} else {
|
||||||
outputMetadata.Hostname = inputMetadata.UUID
|
metadata.Hostname = inputMetadata.UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metadata.SSHPublicKeys = map[string]string{}
|
||||||
if key, ok := inputMetadata.Meta["ssh_public_key"]; ok {
|
if key, ok := inputMetadata.Meta["ssh_public_key"]; ok {
|
||||||
splitted := strings.Split(key, " ")
|
splitted := strings.Split(key, " ")
|
||||||
outputMetadata.PublicKeys = make(map[string]string)
|
metadata.SSHPublicKeys[splitted[len(splitted)-1]] = key
|
||||||
outputMetadata.PublicKeys[splitted[len(splitted)-1]] = key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nic := range inputMetadata.Nics {
|
for _, nic := range inputMetadata.Nics {
|
||||||
if nic.IPv4Conf.IP.UUID != "" {
|
if nic.IPv4Conf.IP.UUID != "" {
|
||||||
outputMetadata.PublicIPv4 = nic.IPv4Conf.IP.UUID
|
metadata.PublicIPv4 = net.ParseIP(nic.IPv4Conf.IP.UUID)
|
||||||
}
|
}
|
||||||
if nic.VLAN.UUID != "" {
|
if nic.VLAN.UUID != "" {
|
||||||
if localIP, err := scs.findLocalIP(nic.Mac); err == nil {
|
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) {
|
func (scs *serverContextService) FetchUserdata() ([]byte, error) {
|
||||||
@ -154,14 +149,14 @@ func (scs *serverContextService) FetchNetworkConfig(a string) ([]byte, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scs *serverContextService) findLocalIP(mac string) (string, error) {
|
func (scs *serverContextService) findLocalIP(mac string) (net.IP, error) {
|
||||||
ifaces, err := net.Interfaces()
|
ifaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifaceMac, err := net.ParseMAC(mac)
|
ifaceMac, err := net.ParseMAC(mac)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, iface := range ifaces {
|
for _, iface := range ifaces {
|
||||||
if !bytes.Equal(iface.HardwareAddr, ifaceMac) {
|
if !bytes.Equal(iface.HardwareAddr, ifaceMac) {
|
||||||
@ -176,12 +171,12 @@ func (scs *serverContextService) findLocalIP(mac string) (string, error) {
|
|||||||
switch ip := addr.(type) {
|
switch ip := addr.(type) {
|
||||||
case *net.IPNet:
|
case *net.IPNet:
|
||||||
if ip.IP.To4() != nil {
|
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 {
|
func isBase64Encoded(field string, userdata map[string]string) bool {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
package cloudsigma
|
package cloudsigma
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -44,12 +44,6 @@ func (f *fakeCepgoClient) FetchRaw(key string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServerContextFetchMetadata(t *testing.T) {
|
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)
|
client := new(fakeCepgoClient)
|
||||||
scs := NewServerContextService()
|
scs := NewServerContextService()
|
||||||
scs.client = client
|
scs.client = client
|
||||||
@ -114,24 +108,20 @@ func TestServerContextFetchMetadata(t *testing.T) {
|
|||||||
"uuid": "20a0059b-041e-4d0c-bcc6-9b2852de48b3"
|
"uuid": "20a0059b-041e-4d0c-bcc6-9b2852de48b3"
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
metadataBytes, err := scs.FetchMetadata()
|
metadata, err := scs.FetchMetadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err.Error())
|
t.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(metadataBytes, &metadata); err != nil {
|
|
||||||
t.Error(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if metadata.Hostname != "coreos" {
|
if metadata.Hostname != "coreos" {
|
||||||
t.Errorf("Hostname is not 'coreos' but %s instead", metadata.Hostname)
|
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")
|
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)
|
t.Errorf("Public IP is not 31.171.251.74 but %s instead", metadata.PublicIPv4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,10 @@ package digitalocean
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
"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)}
|
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *metadataService) FetchMetadata() ([]byte, error) {
|
func (ms *metadataService) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||||
data, err := ms.FetchData(ms.MetadataUrl())
|
var data []byte
|
||||||
if err != nil || len(data) == 0 {
|
var m Metadata
|
||||||
return []byte{}, err
|
|
||||||
|
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
|
ms.interfaces = m.Interfaces
|
||||||
if err := json.Unmarshal(data, &metadata); err != nil {
|
ms.dns = m.DNS
|
||||||
return []byte{}, err
|
|
||||||
|
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
|
return
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms metadataService) FetchNetworkConfig(filename string) ([]byte, error) {
|
func (ms metadataService) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||||
|
@ -15,10 +15,12 @@
|
|||||||
package digitalocean
|
package digitalocean
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
||||||
"github.com/coreos/coreos-cloudinit/pkg"
|
"github.com/coreos/coreos-cloudinit/pkg"
|
||||||
@ -36,7 +38,7 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
root string
|
root string
|
||||||
metadataPath string
|
metadataPath string
|
||||||
resources map[string]string
|
resources map[string]string
|
||||||
expect []byte
|
expect datasource.Metadata
|
||||||
clientErr error
|
clientErr error
|
||||||
expectErr 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")},
|
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||||
@ -99,8 +108,8 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
if Error(err) != Error(tt.expectErr) {
|
if Error(err) != Error(tt.expectErr) {
|
||||||
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(metadata, tt.expect) {
|
if !reflect.DeepEqual(tt.expect, metadata) {
|
||||||
t.Fatalf("bad fetch (%q): want %q, got %q", tt.resources, tt.expect, metadata)
|
t.Fatalf("bad fetch (%q): want %#q, got %#q", tt.resources, tt.expect, metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,11 @@ package ec2
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||||
"github.com/coreos/coreos-cloudinit/pkg"
|
"github.com/coreos/coreos-cloudinit/pkg"
|
||||||
)
|
)
|
||||||
@ -40,59 +41,57 @@ func NewDatasource(root string) *metadataService {
|
|||||||
return &metadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath)}
|
return &metadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms metadataService) FetchMetadata() ([]byte, error) {
|
func (ms metadataService) FetchMetadata() (datasource.Metadata, error) {
|
||||||
attrs := make(map[string]interface{})
|
metadata := datasource.Metadata{}
|
||||||
|
|
||||||
if keynames, err := ms.fetchAttributes(fmt.Sprintf("%s/public-keys", ms.MetadataUrl())); err == nil {
|
if keynames, err := ms.fetchAttributes(fmt.Sprintf("%s/public-keys", ms.MetadataUrl())); err == nil {
|
||||||
keyIDs := make(map[string]string)
|
keyIDs := make(map[string]string)
|
||||||
for _, keyname := range keynames {
|
for _, keyname := range keynames {
|
||||||
tokens := strings.SplitN(keyname, "=", 2)
|
tokens := strings.SplitN(keyname, "=", 2)
|
||||||
if len(tokens) != 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]
|
keyIDs[tokens[1]] = tokens[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := make(map[string]string)
|
metadata.SSHPublicKeys = map[string]string{}
|
||||||
for name, id := range keyIDs {
|
for name, id := range keyIDs {
|
||||||
sshkey, err := ms.fetchAttribute(fmt.Sprintf("%s/public-keys/%s/openssh-key", ms.MetadataUrl(), id))
|
sshkey, err := ms.fetchAttribute(fmt.Sprintf("%s/public-keys/%s/openssh-key", ms.MetadataUrl(), id))
|
||||||
if err != nil {
|
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)
|
fmt.Printf("Found SSH key for %q\n", name)
|
||||||
}
|
}
|
||||||
attrs["public_keys"] = keys
|
|
||||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
} 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 {
|
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 {
|
} 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 {
|
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 {
|
} 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 {
|
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 {
|
} 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 {
|
if contentPath, err := ms.fetchAttribute(fmt.Sprintf("%s/network_config/content_path", ms.MetadataUrl())); err == nil {
|
||||||
attrs["network_config"] = map[string]string{
|
metadata.NetworkConfigPath = contentPath
|
||||||
"content_path": content_path,
|
|
||||||
}
|
|
||||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
} 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 {
|
func (ms metadataService) Type() string {
|
||||||
|
@ -15,11 +15,12 @@
|
|||||||
package ec2
|
package ec2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
||||||
"github.com/coreos/coreos-cloudinit/pkg"
|
"github.com/coreos/coreos-cloudinit/pkg"
|
||||||
@ -145,7 +146,7 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
root string
|
root string
|
||||||
metadataPath string
|
metadataPath string
|
||||||
resources map[string]string
|
resources map[string]string
|
||||||
expect []byte
|
expect datasource.Metadata
|
||||||
clientErr error
|
clientErr error
|
||||||
expectErr 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/public-keys/0/openssh-key": "key",
|
||||||
"/2009-04-04/meta-data/network_config/content_path": "path",
|
"/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: "/",
|
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/public-keys/0/openssh-key": "key",
|
||||||
"/2009-04-04/meta-data/network_config/content_path": "path",
|
"/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")},
|
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||||
@ -199,8 +212,8 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
if Error(err) != Error(tt.expectErr) {
|
if Error(err) != Error(tt.expectErr) {
|
||||||
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(metadata, tt.expect) {
|
if !reflect.DeepEqual(tt.expect, metadata) {
|
||||||
t.Fatalf("bad fetch (%q): want %q, got %q", tt.resources, tt.expect, metadata)
|
t.Fatalf("bad fetch (%q): want %#v, got %#v", tt.resources, tt.expect, metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/pkg"
|
"github.com/coreos/coreos-cloudinit/pkg"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,8 +56,8 @@ func (c *procCmdline) ConfigRoot() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *procCmdline) FetchMetadata() ([]byte, error) {
|
func (c *procCmdline) FetchMetadata() (datasource.Metadata, error) {
|
||||||
return []byte{}, nil
|
return datasource.Metadata{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *procCmdline) FetchUserdata() ([]byte, error) {
|
func (c *procCmdline) FetchUserdata() ([]byte, error) {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package url
|
package url
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/pkg"
|
"github.com/coreos/coreos-cloudinit/pkg"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,8 +41,8 @@ func (f *remoteFile) ConfigRoot() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *remoteFile) FetchMetadata() ([]byte, error) {
|
func (f *remoteFile) FetchMetadata() (datasource.Metadata, error) {
|
||||||
return []byte{}, nil
|
return datasource.Metadata{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *remoteFile) FetchUserdata() ([]byte, error) {
|
func (f *remoteFile) FetchUserdata() ([]byte, error) {
|
||||||
|
@ -15,13 +15,14 @@
|
|||||||
package waagent
|
package waagent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
)
|
)
|
||||||
|
|
||||||
type waagent struct {
|
type waagent struct {
|
||||||
@ -46,13 +47,13 @@ func (a *waagent) ConfigRoot() string {
|
|||||||
return a.root
|
return a.root
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *waagent) FetchMetadata() ([]byte, error) {
|
func (a *waagent) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||||
metadataBytes, err := a.tryReadFile(path.Join(a.root, "SharedConfig.xml"))
|
var metadataBytes []byte
|
||||||
if err != nil {
|
if metadataBytes, err = a.tryReadFile(path.Join(a.root, "SharedConfig.xml")); err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
if len(metadataBytes) == 0 {
|
if len(metadataBytes) == 0 {
|
||||||
return metadataBytes, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
@ -74,30 +75,28 @@ func (a *waagent) FetchMetadata() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadata SharedConfig
|
var m SharedConfig
|
||||||
if err := xml.Unmarshal(metadataBytes, &metadata); err != nil {
|
if err = xml.Unmarshal(metadataBytes, &m); err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance Instance
|
var instance Instance
|
||||||
for _, i := range metadata.Instances.Instances {
|
for _, i := range m.Instances.Instances {
|
||||||
if i.Id == metadata.Incarnation.Instance {
|
if i.Id == m.Incarnation.Instance {
|
||||||
instance = i
|
instance = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs := map[string]string{
|
metadata.PrivateIPv4 = net.ParseIP(instance.Address)
|
||||||
"local-ipv4": instance.Address,
|
|
||||||
}
|
|
||||||
for _, e := range instance.InputEndpoints.Endpoints {
|
for _, e := range instance.InputEndpoints.Endpoints {
|
||||||
host, _, err := net.SplitHostPort(e.LoadBalancedPublicAddress)
|
host, _, err := net.SplitHostPort(e.LoadBalancedPublicAddress)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
attrs["public-ipv4"] = host
|
metadata.PublicIPv4 = net.ParseIP(host)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return json.Marshal(attrs)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *waagent) FetchUserdata() ([]byte, error) {
|
func (a *waagent) FetchUserdata() ([]byte, error) {
|
||||||
|
@ -15,10 +15,11 @@
|
|||||||
package waagent
|
package waagent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
"github.com/coreos/coreos-cloudinit/datasource/test"
|
"github.com/coreos/coreos-cloudinit/datasource/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,26 +27,23 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
root string
|
root string
|
||||||
files test.MockFilesystem
|
files test.MockFilesystem
|
||||||
metadata map[string]string
|
metadata datasource.Metadata
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"/",
|
root: "/",
|
||||||
test.MockFilesystem{},
|
files: test.MockFilesystem{},
|
||||||
nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/",
|
root: "/",
|
||||||
test.MockFilesystem{"/SharedConfig.xml": ""},
|
files: test.MockFilesystem{"/SharedConfig.xml": ""},
|
||||||
nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/var/lib/waagent",
|
root: "/var/lib/waagent",
|
||||||
test.MockFilesystem{"/var/lib/waagent/SharedConfig.xml": ""},
|
files: test.MockFilesystem{"/var/lib/waagent/SharedConfig.xml": ""},
|
||||||
nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/var/lib/waagent",
|
root: "/var/lib/waagent",
|
||||||
test.MockFilesystem{"/var/lib/waagent/SharedConfig.xml": `<?xml version="1.0" encoding="utf-8"?>
|
files: test.MockFilesystem{"/var/lib/waagent/SharedConfig.xml": `<?xml version="1.0" encoding="utf-8"?>
|
||||||
<SharedConfig version="1.0.0.0" goalStateIncarnation="1">
|
<SharedConfig version="1.0.0.0" goalStateIncarnation="1">
|
||||||
<Deployment name="c8f9e4c9c18948e1bebf57c5685da756" guid="{1d10394f-c741-4a1a-a6bb-278f213c5a5e}" incarnation="0" isNonCancellableTopologyChangeEnabled="false">
|
<Deployment name="c8f9e4c9c18948e1bebf57c5685da756" guid="{1d10394f-c741-4a1a-a6bb-278f213c5a5e}" incarnation="0" isNonCancellableTopologyChangeEnabled="false">
|
||||||
<Service name="core-test-1" guid="{00000000-0000-0000-0000-000000000000}" />
|
<Service name="core-test-1" guid="{00000000-0000-0000-0000-000000000000}" />
|
||||||
@ -82,25 +80,19 @@ func TestFetchMetadata(t *testing.T) {
|
|||||||
</Instance>
|
</Instance>
|
||||||
</Instances>
|
</Instances>
|
||||||
</SharedConfig>`},
|
</SharedConfig>`},
|
||||||
map[string]string{
|
metadata: datasource.Metadata{
|
||||||
"local-ipv4": "100.73.202.64",
|
PrivateIPv4: net.ParseIP("100.73.202.64"),
|
||||||
"public-ipv4": "191.239.39.77",
|
PublicIPv4: net.ParseIP("191.239.39.77"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
a := waagent{tt.root, tt.files.ReadFile}
|
a := waagent{tt.root, tt.files.ReadFile}
|
||||||
metadataBytes, err := a.FetchMetadata()
|
metadata, err := a.FetchMetadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
||||||
}
|
}
|
||||||
var metadata map[string]string
|
|
||||||
if len(metadataBytes) > 0 {
|
|
||||||
if err := json.Unmarshal(metadataBytes, &metadata); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(tt.metadata, metadata) {
|
if !reflect.DeepEqual(tt.metadata, metadata) {
|
||||||
t.Fatalf("bad metadata for %q: want %q, got %q", tt, tt.metadata, metadata)
|
t.Fatalf("bad metadata for %q: want %#v, got %#v", tt, tt.metadata, metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,68 +15,46 @@
|
|||||||
package initialize
|
package initialize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/coreos/coreos-cloudinit/config"
|
"github.com/coreos/coreos-cloudinit/config"
|
||||||
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseMetaData parses a JSON blob in the OpenStack metadata service format,
|
// ParseMetaData parses a JSON blob in the OpenStack metadata service format,
|
||||||
// and converts it to a partially hydrated CloudConfig.
|
// and converts it to a partially hydrated CloudConfig.
|
||||||
func ParseMetaData(contents string) (*config.CloudConfig, error) {
|
func ParseMetaData(metadata datasource.Metadata) *config.CloudConfig {
|
||||||
if len(contents) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
var metadata struct {
|
|
||||||
SSHAuthorizedKeyMap map[string]string `json:"public_keys"`
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
NetworkConfig struct {
|
|
||||||
ContentPath string `json:"content_path"`
|
|
||||||
} `json:"network_config"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal([]byte(contents), &metadata); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfg config.CloudConfig
|
var cfg config.CloudConfig
|
||||||
if len(metadata.SSHAuthorizedKeyMap) > 0 {
|
if len(metadata.SSHPublicKeys) > 0 {
|
||||||
cfg.SSHAuthorizedKeys = make([]string, 0, len(metadata.SSHAuthorizedKeyMap))
|
cfg.SSHAuthorizedKeys = make([]string, 0, len(metadata.SSHPublicKeys))
|
||||||
for _, name := range sortedKeys(metadata.SSHAuthorizedKeyMap) {
|
for _, name := range sortedKeys(metadata.SSHPublicKeys) {
|
||||||
cfg.SSHAuthorizedKeys = append(cfg.SSHAuthorizedKeys, metadata.SSHAuthorizedKeyMap[name])
|
cfg.SSHAuthorizedKeys = append(cfg.SSHAuthorizedKeys, metadata.SSHPublicKeys[name])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.Hostname = metadata.Hostname
|
cfg.Hostname = metadata.Hostname
|
||||||
cfg.NetworkConfigPath = metadata.NetworkConfig.ContentPath
|
cfg.NetworkConfigPath = metadata.NetworkConfigPath
|
||||||
return &cfg, nil
|
return &cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractIPsFromMetaData parses a JSON blob in the OpenStack metadata service
|
// ExtractIPsFromMetaData parses a JSON blob in the OpenStack metadata service
|
||||||
// format and returns a substitution map possibly containing private_ipv4,
|
// format and returns a substitution map possibly containing private_ipv4,
|
||||||
// public_ipv4, private_ipv6, and public_ipv6 addresses.
|
// public_ipv4, private_ipv6, and public_ipv6 addresses.
|
||||||
func ExtractIPsFromMetadata(contents []byte) (map[string]string, error) {
|
func ExtractIPsFromMetadata(metadata datasource.Metadata) map[string]string {
|
||||||
var ips struct {
|
subs := map[string]string{}
|
||||||
PublicIPv4 string `json:"public-ipv4"`
|
if metadata.PrivateIPv4 != nil {
|
||||||
PrivateIPv4 string `json:"local-ipv4"`
|
subs["$private_ipv4"] = metadata.PrivateIPv4.String()
|
||||||
PublicIPv6 string `json:"public-ipv6"`
|
|
||||||
PrivateIPv6 string `json:"local-ipv6"`
|
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(contents, &ips); err != nil {
|
if metadata.PublicIPv4 != nil {
|
||||||
return nil, err
|
subs["$public_ipv4"] = metadata.PublicIPv4.String()
|
||||||
}
|
}
|
||||||
m := make(map[string]string)
|
if metadata.PrivateIPv6 != nil {
|
||||||
if ips.PrivateIPv4 != "" {
|
subs["$private_ipv6"] = metadata.PrivateIPv6.String()
|
||||||
m["$private_ipv4"] = ips.PrivateIPv4
|
|
||||||
}
|
}
|
||||||
if ips.PublicIPv4 != "" {
|
if metadata.PublicIPv6 != nil {
|
||||||
m["$public_ipv4"] = ips.PublicIPv4
|
subs["$public_ipv6"] = metadata.PublicIPv6.String()
|
||||||
}
|
}
|
||||||
if ips.PrivateIPv6 != "" {
|
|
||||||
m["$private_ipv6"] = ips.PrivateIPv6
|
return subs
|
||||||
}
|
|
||||||
if ips.PublicIPv6 != "" {
|
|
||||||
m["$public_ipv6"] = ips.PublicIPv6
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortedKeys(m map[string]string) (keys []string) {
|
func sortedKeys(m map[string]string) (keys []string) {
|
||||||
|
@ -15,71 +15,29 @@
|
|||||||
package initialize
|
package initialize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coreos/coreos-cloudinit/config"
|
"github.com/coreos/coreos-cloudinit/datasource"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseMetadata(t *testing.T) {
|
|
||||||
for i, tt := range []struct {
|
|
||||||
in string
|
|
||||||
want *config.CloudConfig
|
|
||||||
err bool
|
|
||||||
}{
|
|
||||||
{"", nil, false},
|
|
||||||
{`garbage, invalid json`, nil, true},
|
|
||||||
{`{"foo": "bar"}`, &config.CloudConfig{}, false},
|
|
||||||
{`{"network_config": {"content_path": "asdf"}}`, &config.CloudConfig{NetworkConfigPath: "asdf"}, false},
|
|
||||||
{`{"hostname": "turkleton"}`, &config.CloudConfig{Hostname: "turkleton"}, false},
|
|
||||||
{`{"public_keys": {"jack": "jill", "bob": "alice"}}`, &config.CloudConfig{SSHAuthorizedKeys: []string{"alice", "jill"}}, false},
|
|
||||||
{`{"unknown": "thing", "hostname": "my_host", "public_keys": {"do": "re", "mi": "fa"}, "network_config": {"content_path": "/root", "blah": "zzz"}}`, &config.CloudConfig{SSHAuthorizedKeys: []string{"re", "fa"}, Hostname: "my_host", NetworkConfigPath: "/root"}, false},
|
|
||||||
} {
|
|
||||||
got, err := ParseMetaData(tt.in)
|
|
||||||
if tt.err != (err != nil) {
|
|
||||||
t.Errorf("case #%d: bad error state: got %t, want %t (err=%v)", i, (err != nil), tt.err, err)
|
|
||||||
}
|
|
||||||
if got == nil {
|
|
||||||
if tt.want != nil {
|
|
||||||
t.Errorf("case #%d: unexpected nil output", i)
|
|
||||||
}
|
|
||||||
} else if tt.want == nil {
|
|
||||||
t.Errorf("case #%d: unexpected non-nil output", i)
|
|
||||||
} else {
|
|
||||||
if !reflect.DeepEqual(*got, *tt.want) {
|
|
||||||
t.Errorf("case #%d: bad output:\ngot\n%v\nwant\n%v", i, *got, *tt.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractIPsFromMetadata(t *testing.T) {
|
func TestExtractIPsFromMetadata(t *testing.T) {
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
in []byte
|
in datasource.Metadata
|
||||||
err bool
|
|
||||||
out map[string]string
|
out map[string]string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
[]byte(`{"public-ipv4": "12.34.56.78", "local-ipv4": "1.2.3.4", "public-ipv6": "1234::", "local-ipv6": "5678::"}`),
|
datasource.Metadata{
|
||||||
false,
|
PublicIPv4: net.ParseIP("12.34.56.78"),
|
||||||
|
PrivateIPv4: net.ParseIP("1.2.3.4"),
|
||||||
|
PublicIPv6: net.ParseIP("1234::"),
|
||||||
|
PrivateIPv6: net.ParseIP("5678::"),
|
||||||
|
},
|
||||||
map[string]string{"$public_ipv4": "12.34.56.78", "$private_ipv4": "1.2.3.4", "$public_ipv6": "1234::", "$private_ipv6": "5678::"},
|
map[string]string{"$public_ipv4": "12.34.56.78", "$private_ipv4": "1.2.3.4", "$public_ipv6": "1234::", "$private_ipv6": "5678::"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
[]byte(`{"local-ipv4": "127.0.0.1", "something_else": "don't care"}`),
|
|
||||||
false,
|
|
||||||
map[string]string{"$private_ipv4": "127.0.0.1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[]byte(`garbage`),
|
|
||||||
true,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
} {
|
} {
|
||||||
got, err := ExtractIPsFromMetadata(tt.in)
|
got := ExtractIPsFromMetadata(tt.in)
|
||||||
if (err != nil) != tt.err {
|
|
||||||
t.Errorf("bad error state (got %t, want %t)", err != nil, tt.err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.out) {
|
if !reflect.DeepEqual(got, tt.out) {
|
||||||
t.Errorf("case %d: got %s, want %s", i, got, tt.out)
|
t.Errorf("case %d: got %s, want %s", i, got, tt.out)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user