configdrive: Use the EC2 metadata over OpenStack
Standardize on specific EC2 and OpenStack versions and add tests.
This commit is contained in:
parent
f2b342c8be
commit
4eedca26e9
@ -8,10 +8,11 @@ import (
|
|||||||
|
|
||||||
type configDrive struct {
|
type configDrive struct {
|
||||||
root string
|
root string
|
||||||
|
readFile func(filename string) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfigDrive(root string) *configDrive {
|
func NewConfigDrive(root string) *configDrive {
|
||||||
return &configDrive{path.Join(root, "openstack")}
|
return &configDrive{root, ioutil.ReadFile}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd *configDrive) IsAvailable() bool {
|
func (cd *configDrive) IsAvailable() bool {
|
||||||
@ -24,23 +25,38 @@ func (cd *configDrive) AvailabilityChanges() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cd *configDrive) ConfigRoot() string {
|
func (cd *configDrive) ConfigRoot() string {
|
||||||
return cd.root
|
return cd.openstackRoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchMetadata attempts to retrieve metadata from ec2/2009-04-04/meta_data.json.
|
||||||
func (cd *configDrive) FetchMetadata() ([]byte, error) {
|
func (cd *configDrive) FetchMetadata() ([]byte, error) {
|
||||||
return cd.readFile("meta_data.json")
|
return cd.tryReadFile(path.Join(cd.ec2Root(), "meta_data.json"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchUserdata attempts to retrieve the userdata from ec2/2009-04-04/user_data.
|
||||||
|
// If no data is found, it will attempt to read from openstack/latest/user_data.
|
||||||
func (cd *configDrive) FetchUserdata() ([]byte, error) {
|
func (cd *configDrive) FetchUserdata() ([]byte, error) {
|
||||||
return cd.readFile("user_data")
|
bytes, err := cd.tryReadFile(path.Join(cd.ec2Root(), "user_data"))
|
||||||
|
if bytes == nil && err == nil {
|
||||||
|
bytes, err = cd.tryReadFile(path.Join(cd.openstackRoot(), "user_data"))
|
||||||
|
}
|
||||||
|
return bytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd *configDrive) Type() string {
|
func (cd *configDrive) Type() string {
|
||||||
return "cloud-drive"
|
return "cloud-drive"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd *configDrive) readFile(filename string) ([]byte, error) {
|
func (cd *configDrive) ec2Root() string {
|
||||||
data, err := ioutil.ReadFile(path.Join(cd.root, "latest", filename))
|
return path.Join(cd.root, "ec2", Ec2ApiVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cd *configDrive) openstackRoot() string {
|
||||||
|
return path.Join(cd.root, "openstack", "latest")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cd *configDrive) tryReadFile(filename string) ([]byte, error) {
|
||||||
|
data, err := cd.readFile(filename)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
114
datasource/configdrive_test.go
Normal file
114
datasource/configdrive_test.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package datasource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockFilesystem []string
|
||||||
|
|
||||||
|
func (m mockFilesystem) readFile(filename string) ([]byte, error) {
|
||||||
|
for _, file := range m {
|
||||||
|
if file == filename {
|
||||||
|
return []byte(filename), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, os.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCDFetchMetadata(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
root string
|
||||||
|
filename string
|
||||||
|
files mockFilesystem
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"",
|
||||||
|
mockFilesystem{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"/ec2/2009-04-04/meta_data.json",
|
||||||
|
mockFilesystem([]string{"/ec2/2009-04-04/meta_data.json"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/media/configdrive",
|
||||||
|
"/media/configdrive/ec2/2009-04-04/meta_data.json",
|
||||||
|
mockFilesystem([]string{"/media/configdrive/ec2/2009-04-04/meta_data.json"}),
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
cd := configDrive{tt.root, tt.files.readFile}
|
||||||
|
filename, err := cd.FetchMetadata()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad error for %q: want %q, got %q", tt, nil, err)
|
||||||
|
}
|
||||||
|
if string(filename) != tt.filename {
|
||||||
|
t.Fatalf("bad path for %q: want %q, got %q", tt, tt.filename, filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCDFetchUserdata(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
root string
|
||||||
|
filename string
|
||||||
|
files mockFilesystem
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"",
|
||||||
|
mockFilesystem{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"/ec2/2009-04-04/user_data",
|
||||||
|
mockFilesystem([]string{"/ec2/2009-04-04/user_data"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"/openstack/latest/user_data",
|
||||||
|
mockFilesystem([]string{"/openstack/latest/user_data"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"/ec2/2009-04-04/user_data",
|
||||||
|
mockFilesystem([]string{"/openstack/latest/user_data", "/ec2/2009-04-04/user_data"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/media/configdrive",
|
||||||
|
"/media/configdrive/ec2/2009-04-04/user_data",
|
||||||
|
mockFilesystem([]string{"/media/configdrive/ec2/2009-04-04/user_data"}),
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
cd := configDrive{tt.root, tt.files.readFile}
|
||||||
|
filename, err := cd.FetchUserdata()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad error for %q: want %q, got %q", tt, nil, err)
|
||||||
|
}
|
||||||
|
if string(filename) != tt.filename {
|
||||||
|
t.Fatalf("bad path for %q: want %q, got %q", tt, tt.filename, filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCDConfigRoot(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
root string
|
||||||
|
configRoot string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"/",
|
||||||
|
"/openstack/latest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/media/configdrive",
|
||||||
|
"/media/configdrive/openstack/latest",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
cd := configDrive{tt.root, nil}
|
||||||
|
if configRoot := cd.ConfigRoot(); configRoot != tt.configRoot {
|
||||||
|
t.Fatalf("bad config root for %q: want %q, got %q", tt, tt.configRoot, configRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,10 @@
|
|||||||
package datasource
|
package datasource
|
||||||
|
|
||||||
|
const (
|
||||||
|
Ec2ApiVersion = "2009-04-04"
|
||||||
|
OpenstackApiVersion = "2012-08-10"
|
||||||
|
)
|
||||||
|
|
||||||
type Datasource interface {
|
type Datasource interface {
|
||||||
IsAvailable() bool
|
IsAvailable() bool
|
||||||
AvailabilityChanges() bool
|
AvailabilityChanges() bool
|
||||||
|
@ -22,11 +22,9 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
BaseUrl = "http://169.254.169.254/"
|
BaseUrl = "http://169.254.169.254/"
|
||||||
Ec2ApiVersion = "2009-04-04"
|
|
||||||
Ec2UserdataUrl = BaseUrl + Ec2ApiVersion + "/user-data"
|
Ec2UserdataUrl = BaseUrl + Ec2ApiVersion + "/user-data"
|
||||||
Ec2MetadataUrl = BaseUrl + Ec2ApiVersion + "/meta-data"
|
Ec2MetadataUrl = BaseUrl + Ec2ApiVersion + "/meta-data"
|
||||||
OpenstackApiVersion = "openstack/2012-08-10"
|
OpenstackUserdataUrl = BaseUrl + "openstack/" + OpenstackApiVersion + "/user_data"
|
||||||
OpenstackUserdataUrl = BaseUrl + OpenstackApiVersion + "/user_data"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadataService struct{}
|
type metadataService struct{}
|
||||||
|
@ -25,7 +25,7 @@ func (t *TestHttpClient) GetRetry(url string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchAttributes(t *testing.T) {
|
func TestMSFetchAttributes(t *testing.T) {
|
||||||
for _, s := range []struct {
|
for _, s := range []struct {
|
||||||
metadata map[string]string
|
metadata map[string]string
|
||||||
err error
|
err error
|
||||||
@ -77,7 +77,7 @@ func TestFetchAttributes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchAttribute(t *testing.T) {
|
func TestMSFetchAttribute(t *testing.T) {
|
||||||
for _, s := range []struct {
|
for _, s := range []struct {
|
||||||
metadata map[string]string
|
metadata map[string]string
|
||||||
err error
|
err error
|
||||||
@ -129,7 +129,7 @@ func TestFetchAttribute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchMetadata(t *testing.T) {
|
func TestMSFetchMetadata(t *testing.T) {
|
||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
metadata map[string]string
|
metadata map[string]string
|
||||||
err error
|
err error
|
||||||
|
Loading…
Reference in New Issue
Block a user