Merge branch 'master' into generic
This commit is contained in:
@@ -1,26 +1,27 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package configdrive
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -49,21 +50,36 @@ func (cd *configDrive) ConfigRoot() string {
|
||||
return cd.openstackRoot()
|
||||
}
|
||||
|
||||
func (cd *configDrive) FetchMetadata() ([]byte, error) {
|
||||
return cd.tryReadFile(path.Join(cd.openstackVersionRoot(), "meta_data.json"))
|
||||
func (cd *configDrive) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
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 || len(data) == 0 {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal([]byte(data), &m); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
metadata.SSHPublicKeys = m.SSHAuthorizedKeyMap
|
||||
metadata.Hostname = m.Hostname
|
||||
if m.NetworkConfig.ContentPath != "" {
|
||||
metadata.NetworkConfig, err = cd.tryReadFile(path.Join(cd.openstackRoot(), m.NetworkConfig.ContentPath))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (cd *configDrive) FetchUserdata() ([]byte, error) {
|
||||
return cd.tryReadFile(path.Join(cd.openstackVersionRoot(), "user_data"))
|
||||
}
|
||||
|
||||
func (cd *configDrive) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
if filename == "" {
|
||||
return []byte{}, nil
|
||||
}
|
||||
return cd.tryReadFile(path.Join(cd.openstackRoot(), filename))
|
||||
}
|
||||
|
||||
func (cd *configDrive) Type() string {
|
||||
return "cloud-drive"
|
||||
}
|
||||
|
@@ -1,99 +1,103 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package configdrive
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/test"
|
||||
)
|
||||
|
||||
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 TestFetchMetadata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
filename string
|
||||
files mockFilesystem
|
||||
root string
|
||||
files test.MockFilesystem
|
||||
|
||||
metadata datasource.Metadata
|
||||
}{
|
||||
{
|
||||
"/",
|
||||
"",
|
||||
mockFilesystem{},
|
||||
root: "/",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/openstack/latest/meta_data.json", Contents: ""}),
|
||||
},
|
||||
{
|
||||
"/",
|
||||
"/openstack/latest/meta_data.json",
|
||||
mockFilesystem([]string{"/openstack/latest/meta_data.json"}),
|
||||
root: "/",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/openstack/latest/meta_data.json", Contents: `{"ignore": "me"}`}),
|
||||
},
|
||||
{
|
||||
"/media/configdrive",
|
||||
"/media/configdrive/openstack/latest/meta_data.json",
|
||||
mockFilesystem([]string{"/media/configdrive/openstack/latest/meta_data.json"}),
|
||||
root: "/",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/openstack/latest/meta_data.json", Contents: `{"hostname": "host"}`}),
|
||||
metadata: datasource.Metadata{Hostname: "host"},
|
||||
},
|
||||
{
|
||||
root: "/media/configdrive",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/media/configdrive/openstack/latest/meta_data.json", Contents: `{"hostname": "host", "network_config": {"content_path": "config_file.json"}, "public_keys":{"1": "key1", "2": "key2"}}`},
|
||||
test.File{Path: "/media/configdrive/openstack/config_file.json", Contents: "make it work"},
|
||||
),
|
||||
metadata: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
NetworkConfig: []byte("make it work"),
|
||||
SSHPublicKeys: map[string]string{
|
||||
"1": "key1",
|
||||
"2": "key2",
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
cd := configDrive{tt.root, tt.files.readFile}
|
||||
filename, err := cd.FetchMetadata()
|
||||
cd := configDrive{tt.root, tt.files.ReadFile}
|
||||
metadata, err := cd.FetchMetadata()
|
||||
if err != nil {
|
||||
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
||||
t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err)
|
||||
}
|
||||
if string(filename) != tt.filename {
|
||||
t.Fatalf("bad path for %q: want %q, got %q", tt, tt.filename, filename)
|
||||
if !reflect.DeepEqual(tt.metadata, metadata) {
|
||||
t.Fatalf("bad metadata for %+v: want %#v, got %#v", tt, tt.metadata, metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchUserdata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
filename string
|
||||
files mockFilesystem
|
||||
root string
|
||||
files test.MockFilesystem
|
||||
|
||||
userdata string
|
||||
}{
|
||||
{
|
||||
"/",
|
||||
test.NewMockFilesystem(),
|
||||
"",
|
||||
mockFilesystem{},
|
||||
},
|
||||
{
|
||||
"/",
|
||||
"/openstack/latest/user_data",
|
||||
mockFilesystem([]string{"/openstack/latest/user_data"}),
|
||||
test.NewMockFilesystem(test.File{Path: "/openstack/latest/user_data", Contents: "userdata"}),
|
||||
"userdata",
|
||||
},
|
||||
{
|
||||
"/media/configdrive",
|
||||
"/media/configdrive/openstack/latest/user_data",
|
||||
mockFilesystem([]string{"/media/configdrive/openstack/latest/user_data"}),
|
||||
test.NewMockFilesystem(test.File{Path: "/media/configdrive/openstack/latest/user_data", Contents: "userdata"}),
|
||||
"userdata",
|
||||
},
|
||||
} {
|
||||
cd := configDrive{tt.root, tt.files.readFile}
|
||||
filename, err := cd.FetchUserdata()
|
||||
cd := configDrive{tt.root, tt.files.ReadFile}
|
||||
userdata, err := cd.FetchUserdata()
|
||||
if err != nil {
|
||||
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
||||
t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err)
|
||||
}
|
||||
if string(filename) != tt.filename {
|
||||
t.Fatalf("bad path for %q: want %q, got %q", tt, tt.filename, filename)
|
||||
if string(userdata) != tt.userdata {
|
||||
t.Fatalf("bad userdata for %+v: want %q, got %q", tt, tt.userdata, userdata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,27 +1,38 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
type Datasource interface {
|
||||
IsAvailable() bool
|
||||
AvailabilityChanges() bool
|
||||
ConfigRoot() string
|
||||
FetchMetadata() ([]byte, error)
|
||||
FetchMetadata() (Metadata, error)
|
||||
FetchUserdata() ([]byte, error)
|
||||
FetchNetworkConfig(string) ([]byte, error)
|
||||
Type() string
|
||||
}
|
||||
|
||||
type Metadata struct {
|
||||
PublicIPv4 net.IP
|
||||
PublicIPv6 net.IP
|
||||
PrivateIPv4 net.IP
|
||||
PrivateIPv6 net.IP
|
||||
Hostname string
|
||||
SSHPublicKeys map[string]string
|
||||
NetworkConfig []byte
|
||||
}
|
||||
|
@@ -1,24 +1,24 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
)
|
||||
|
||||
type localFile struct {
|
||||
@@ -42,18 +42,14 @@ func (f *localFile) ConfigRoot() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f *localFile) FetchMetadata() ([]byte, error) {
|
||||
return []byte{}, nil
|
||||
func (f *localFile) FetchMetadata() (datasource.Metadata, error) {
|
||||
return datasource.Metadata{}, nil
|
||||
}
|
||||
|
||||
func (f *localFile) FetchUserdata() ([]byte, error) {
|
||||
return ioutil.ReadFile(f.path)
|
||||
}
|
||||
|
||||
func (f *localFile) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (f *localFile) Type() string {
|
||||
return "local-file"
|
||||
}
|
||||
|
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudsigma
|
||||
|
||||
@@ -26,6 +24,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/cloudsigma/cepgo"
|
||||
)
|
||||
|
||||
@@ -71,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"`
|
||||
@@ -90,48 +90,43 @@ 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
|
||||
}
|
||||
|
||||
if key, ok := inputMetadata.Meta["ssh_public_key"]; ok {
|
||||
metadata.SSHPublicKeys = map[string]string{}
|
||||
// CloudSigma uses an empty string, rather than no string,
|
||||
// to represent the lack of a SSH key
|
||||
if key, _ := inputMetadata.Meta["ssh_public_key"]; len(key) > 0 {
|
||||
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) {
|
||||
@@ -152,18 +147,14 @@ func (scs *serverContextService) FetchUserdata() ([]byte, error) {
|
||||
return []byte(userData), nil
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -178,12 +169,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 {
|
||||
|
@@ -1,23 +1,21 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudsigma
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
@@ -45,13 +43,28 @@ func (f *fakeCepgoClient) FetchRaw(key string) ([]byte, error) {
|
||||
return f.raw, f.err
|
||||
}
|
||||
|
||||
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"`
|
||||
func TestServerContextWithEmptyPublicSSHKey(t *testing.T) {
|
||||
client := new(fakeCepgoClient)
|
||||
scs := NewServerContextService()
|
||||
scs.client = client
|
||||
client.raw = []byte(`{
|
||||
"meta": {
|
||||
"base64_fields": "cloudinit-user-data",
|
||||
"cloudinit-user-data": "I2Nsb3VkLWNvbmZpZwoKaG9zdG5hbWU6IGNvcmVvczE=",
|
||||
"ssh_public_key": ""
|
||||
}
|
||||
}`)
|
||||
metadata, err := scs.FetchMetadata()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
if len(metadata.SSHPublicKeys) != 0 {
|
||||
t.Error("There should be no Public SSH Keys provided")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerContextFetchMetadata(t *testing.T) {
|
||||
client := new(fakeCepgoClient)
|
||||
scs := NewServerContextService()
|
||||
scs.client = client
|
||||
@@ -116,24 +129,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)
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package digitalocean
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
)
|
||||
|
||||
@@ -61,8 +61,6 @@ type Metadata struct {
|
||||
}
|
||||
|
||||
type metadataService struct {
|
||||
interfaces Interfaces
|
||||
dns DNS
|
||||
metadata.MetadataService
|
||||
}
|
||||
|
||||
@@ -70,52 +68,41 @@ 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 = 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 len(m.Interfaces.Public) > 0 {
|
||||
if m.Interfaces.Public[0].IPv4 != nil {
|
||||
metadata.PublicIPv4 = net.ParseIP(m.Interfaces.Public[0].IPv4.IPAddress)
|
||||
}
|
||||
if metadata.Interfaces.Public[0].IPv6 != nil {
|
||||
attrs["public-ipv6"] = metadata.Interfaces.Public[0].IPv6.IPAddress
|
||||
if m.Interfaces.Public[0].IPv6 != nil {
|
||||
metadata.PublicIPv6 = net.ParseIP(m.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 len(m.Interfaces.Private) > 0 {
|
||||
if m.Interfaces.Private[0].IPv4 != nil {
|
||||
metadata.PrivateIPv4 = net.ParseIP(m.Interfaces.Private[0].IPv4.IPAddress)
|
||||
}
|
||||
if metadata.Interfaces.Private[0].IPv6 != nil {
|
||||
attrs["local-ipv6"] = metadata.Interfaces.Private[0].IPv6.IPAddress
|
||||
if m.Interfaces.Private[0].IPv6 != nil {
|
||||
metadata.PrivateIPv6 = net.ParseIP(m.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
|
||||
metadata.Hostname = m.Hostname
|
||||
metadata.SSHPublicKeys = map[string]string{}
|
||||
for i, key := range m.PublicKeys {
|
||||
metadata.SSHPublicKeys[strconv.Itoa(i)] = key
|
||||
}
|
||||
attrs["public_keys"] = keys
|
||||
metadata.NetworkConfig = data
|
||||
|
||||
return json.Marshal(attrs)
|
||||
}
|
||||
|
||||
func (ms metadataService) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
return json.Marshal(Metadata{
|
||||
Interfaces: ms.interfaces,
|
||||
DNS: ms.dns,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (ms metadataService) Type() string {
|
||||
|
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
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"
|
||||
@@ -38,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
|
||||
}{
|
||||
@@ -83,7 +83,42 @@ 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",
|
||||
},
|
||||
NetworkConfig: []byte(`{
|
||||
"droplet_id": 1,
|
||||
"user_data": "hello",
|
||||
"vendor_data": "hello",
|
||||
"public_keys": [
|
||||
"publickey1",
|
||||
"publickey2"
|
||||
],
|
||||
"region": "nyc2",
|
||||
"interfaces": {
|
||||
"public": [
|
||||
{
|
||||
"ipv4": {
|
||||
"ip_address": "192.168.1.2",
|
||||
"netmask": "255.255.255.0",
|
||||
"gateway": "192.168.1.1"
|
||||
},
|
||||
"ipv6": {
|
||||
"ip_address": "fe00::",
|
||||
"cidr": 126,
|
||||
"gateway": "fe00::"
|
||||
},
|
||||
"mac": "ab:cd:ef:gh:ij",
|
||||
"type": "public"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
@@ -101,8 +136,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,28 +1,27 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
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"
|
||||
)
|
||||
@@ -42,59 +41,51 @@ 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"] = hostname
|
||||
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,
|
||||
}
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(attrs)
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
func (ms metadataService) Type() string {
|
||||
|
@@ -1,27 +1,26 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
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"
|
||||
@@ -147,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
|
||||
}{
|
||||
@@ -163,15 +162,37 @@ func TestFetchMetadata(t *testing.T) {
|
||||
root: "/",
|
||||
metadataPath: "2009-04-04/meta-data",
|
||||
resources: map[string]string{
|
||||
"/2009-04-04/meta-data/hostname": "host",
|
||||
"/2009-04-04/meta-data/local-ipv4": "1.2.3.4",
|
||||
"/2009-04-04/meta-data/public-ipv4": "5.6.7.8",
|
||||
"/2009-04-04/meta-data/public-keys": "0=test1\n",
|
||||
"/2009-04-04/meta-data/public-keys/0": "openssh-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/hostname": "host",
|
||||
"/2009-04-04/meta-data/local-ipv4": "1.2.3.4",
|
||||
"/2009-04-04/meta-data/public-ipv4": "5.6.7.8",
|
||||
"/2009-04-04/meta-data/public-keys": "0=test1\n",
|
||||
"/2009-04-04/meta-data/public-keys/0": "openssh-key",
|
||||
"/2009-04-04/meta-data/public-keys/0/openssh-key": "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"},
|
||||
},
|
||||
},
|
||||
{
|
||||
root: "/",
|
||||
metadataPath: "2009-04-04/meta-data",
|
||||
resources: map[string]string{
|
||||
"/2009-04-04/meta-data/hostname": "host domain another_domain",
|
||||
"/2009-04-04/meta-data/local-ipv4": "1.2.3.4",
|
||||
"/2009-04-04/meta-data/public-ipv4": "5.6.7.8",
|
||||
"/2009-04-04/meta-data/public-keys": "0=test1\n",
|
||||
"/2009-04-04/meta-data/public-keys/0": "openssh-key",
|
||||
"/2009-04-04/meta-data/public-keys/0/openssh-key": "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"},
|
||||
},
|
||||
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"}}`),
|
||||
},
|
||||
{
|
||||
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
@@ -187,8 +208,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package metadata
|
||||
|
||||
@@ -54,10 +52,6 @@ func (ms MetadataService) FetchUserdata() ([]byte, error) {
|
||||
return ms.FetchData(ms.UserdataUrl())
|
||||
}
|
||||
|
||||
func (ms MetadataService) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ms MetadataService) FetchData(url string) ([]byte, error) {
|
||||
if data, err := ms.Client.GetRetry(url); err == nil {
|
||||
return data, err
|
||||
|
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package metadata
|
||||
|
||||
|
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package test
|
||||
|
||||
|
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package proc_cmdline
|
||||
|
||||
@@ -22,6 +20,7 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
)
|
||||
|
||||
@@ -57,8 +56,8 @@ func (c *procCmdline) ConfigRoot() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *procCmdline) FetchMetadata() ([]byte, error) {
|
||||
return []byte{}, nil
|
||||
func (c *procCmdline) FetchMetadata() (datasource.Metadata, error) {
|
||||
return datasource.Metadata{}, nil
|
||||
}
|
||||
|
||||
func (c *procCmdline) FetchUserdata() ([]byte, error) {
|
||||
@@ -82,10 +81,6 @@ func (c *procCmdline) FetchUserdata() ([]byte, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (c *procCmdline) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *procCmdline) Type() string {
|
||||
return "proc-cmdline"
|
||||
}
|
||||
|
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package proc_cmdline
|
||||
|
||||
|
57
datasource/test/filesystem.go
Normal file
57
datasource/test/filesystem.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type MockFilesystem map[string]File
|
||||
|
||||
type File struct {
|
||||
Path string
|
||||
Contents string
|
||||
Directory bool
|
||||
}
|
||||
|
||||
func (m MockFilesystem) ReadFile(filename string) ([]byte, error) {
|
||||
if f, ok := m[path.Clean(filename)]; ok {
|
||||
if f.Directory {
|
||||
return nil, fmt.Errorf("read %s: is a directory", filename)
|
||||
}
|
||||
return []byte(f.Contents), nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func NewMockFilesystem(files ...File) MockFilesystem {
|
||||
fs := MockFilesystem{}
|
||||
for _, file := range files {
|
||||
fs[file.Path] = file
|
||||
|
||||
// Create the directories leading up to the file
|
||||
p := path.Dir(file.Path)
|
||||
for p != "/" && p != "." {
|
||||
if f, ok := fs[p]; ok && !f.Directory {
|
||||
panic(fmt.Sprintf("%q already exists and is not a directory (%#v)", p, f))
|
||||
}
|
||||
fs[p] = File{Path: p, Directory: true}
|
||||
p = path.Dir(p)
|
||||
}
|
||||
}
|
||||
return fs
|
||||
}
|
115
datasource/test/filesystem_test.go
Normal file
115
datasource/test/filesystem_test.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
filesystem MockFilesystem
|
||||
|
||||
filename string
|
||||
contents string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
filename: "dne",
|
||||
err: os.ErrNotExist,
|
||||
},
|
||||
{
|
||||
filesystem: MockFilesystem{
|
||||
"exists": File{Contents: "hi"},
|
||||
},
|
||||
filename: "exists",
|
||||
contents: "hi",
|
||||
},
|
||||
{
|
||||
filesystem: MockFilesystem{
|
||||
"dir": File{Directory: true},
|
||||
},
|
||||
filename: "dir",
|
||||
err: errors.New("read dir: is a directory"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
contents, err := tt.filesystem.ReadFile(tt.filename)
|
||||
if tt.contents != string(contents) {
|
||||
t.Errorf("bad contents (test %d): want %q, got %q", i, tt.contents, string(contents))
|
||||
}
|
||||
if !reflect.DeepEqual(tt.err, err) {
|
||||
t.Errorf("bad error (test %d): want %v, got %v", i, tt.err, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewMockFilesystem(t *testing.T) {
|
||||
tests := []struct {
|
||||
files []File
|
||||
|
||||
filesystem MockFilesystem
|
||||
}{
|
||||
{
|
||||
filesystem: MockFilesystem{},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"file": File{Path: "file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"/file": File{Path: "/file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/dir/file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"/dir": File{Path: "/dir", Directory: true},
|
||||
"/dir/file": File{Path: "/dir/file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/dir/dir/file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"/dir": File{Path: "/dir", Directory: true},
|
||||
"/dir/dir": File{Path: "/dir/dir", Directory: true},
|
||||
"/dir/dir/file": File{Path: "/dir/dir/file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/dir/dir/dir", Directory: true}},
|
||||
filesystem: MockFilesystem{
|
||||
"/dir": File{Path: "/dir", Directory: true},
|
||||
"/dir/dir": File{Path: "/dir/dir", Directory: true},
|
||||
"/dir/dir/dir": File{Path: "/dir/dir/dir", Directory: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
filesystem := NewMockFilesystem(tt.files...)
|
||||
if !reflect.DeepEqual(tt.filesystem, filesystem) {
|
||||
t.Errorf("bad filesystem (test %d): want %#v, got %#v", i, tt.filesystem, filesystem)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,22 +1,21 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package url
|
||||
|
||||
import (
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
)
|
||||
|
||||
@@ -42,8 +41,8 @@ func (f *remoteFile) ConfigRoot() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f *remoteFile) FetchMetadata() ([]byte, error) {
|
||||
return []byte{}, nil
|
||||
func (f *remoteFile) FetchMetadata() (datasource.Metadata, error) {
|
||||
return datasource.Metadata{}, nil
|
||||
}
|
||||
|
||||
func (f *remoteFile) FetchUserdata() ([]byte, error) {
|
||||
@@ -51,10 +50,6 @@ func (f *remoteFile) FetchUserdata() ([]byte, error) {
|
||||
return client.GetRetry(f.url)
|
||||
}
|
||||
|
||||
func (f *remoteFile) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (f *remoteFile) Type() string {
|
||||
return "url"
|
||||
}
|
||||
|
@@ -1,29 +1,28 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package waagent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
)
|
||||
|
||||
type waagent struct {
|
||||
@@ -48,13 +47,13 @@ func (a *waagent) ConfigRoot() string {
|
||||
return a.root
|
||||
}
|
||||
|
||||
func (a *waagent) FetchMetadata() ([]byte, error) {
|
||||
metadataBytes, err := a.tryReadFile(path.Join(a.root, "SharedConfig.xml"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (a *waagent) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
var metadataBytes []byte
|
||||
if metadataBytes, err = a.tryReadFile(path.Join(a.root, "SharedConfig.xml")); err != nil {
|
||||
return
|
||||
}
|
||||
if len(metadataBytes) == 0 {
|
||||
return metadataBytes, nil
|
||||
return
|
||||
}
|
||||
|
||||
type Instance struct {
|
||||
@@ -76,40 +75,34 @@ func (a *waagent) FetchMetadata() ([]byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var metadata SharedConfig
|
||||
if err := xml.Unmarshal(metadataBytes, &metadata); err != nil {
|
||||
return nil, err
|
||||
var m SharedConfig
|
||||
if err = xml.Unmarshal(metadataBytes, &m); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var instance Instance
|
||||
for _, i := range metadata.Instances.Instances {
|
||||
if i.Id == metadata.Incarnation.Instance {
|
||||
for _, i := range m.Instances.Instances {
|
||||
if i.Id == m.Incarnation.Instance {
|
||||
instance = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
attrs := map[string]string{
|
||||
"local-ipv4": instance.Address,
|
||||
}
|
||||
metadata.PrivateIPv4 = net.ParseIP(instance.Address)
|
||||
for _, e := range instance.InputEndpoints.Endpoints {
|
||||
host, _, err := net.SplitHostPort(e.LoadBalancedPublicAddress)
|
||||
if err == nil {
|
||||
attrs["public-ipv4"] = host
|
||||
metadata.PublicIPv4 = net.ParseIP(host)
|
||||
break
|
||||
}
|
||||
}
|
||||
return json.Marshal(attrs)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *waagent) FetchUserdata() ([]byte, error) {
|
||||
return a.tryReadFile(path.Join(a.root, "CustomData"))
|
||||
}
|
||||
|
||||
func (a *waagent) FetchNetworkConfig(filename string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (a *waagent) Type() string {
|
||||
return "waagent"
|
||||
}
|
||||
|
@@ -1,61 +1,49 @@
|
||||
/*
|
||||
Copyright 2014 CoreOS, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package waagent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/test"
|
||||
)
|
||||
|
||||
type mockFilesystem map[string][]byte
|
||||
|
||||
func (m mockFilesystem) readFile(filename string) ([]byte, error) {
|
||||
if contents := m[filename]; contents != nil {
|
||||
return contents, nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func TestFetchMetadata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
files mockFilesystem
|
||||
metadata map[string]string
|
||||
files test.MockFilesystem
|
||||
metadata datasource.Metadata
|
||||
}{
|
||||
{
|
||||
"/",
|
||||
mockFilesystem{},
|
||||
nil,
|
||||
root: "/",
|
||||
files: test.NewMockFilesystem(),
|
||||
},
|
||||
{
|
||||
"/",
|
||||
mockFilesystem{"/SharedConfig.xml": []byte("")},
|
||||
nil,
|
||||
root: "/",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/SharedConfig.xml", Contents: ""}),
|
||||
},
|
||||
{
|
||||
"/var/lib/waagent",
|
||||
mockFilesystem{"/var/lib/waagent/SharedConfig.xml": []byte("")},
|
||||
nil,
|
||||
root: "/var/lib/waagent",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/var/lib/waagent/SharedConfig.xml", Contents: ""}),
|
||||
},
|
||||
{
|
||||
"/var/lib/waagent",
|
||||
mockFilesystem{"/var/lib/waagent/SharedConfig.xml": []byte(`<?xml version="1.0" encoding="utf-8"?>
|
||||
root: "/var/lib/waagent",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/var/lib/waagent/SharedConfig.xml", Contents: `<?xml version="1.0" encoding="utf-8"?>
|
||||
<SharedConfig version="1.0.0.0" goalStateIncarnation="1">
|
||||
<Deployment name="c8f9e4c9c18948e1bebf57c5685da756" guid="{1d10394f-c741-4a1a-a6bb-278f213c5a5e}" incarnation="0" isNonCancellableTopologyChangeEnabled="false">
|
||||
<Service name="core-test-1" guid="{00000000-0000-0000-0000-000000000000}" />
|
||||
@@ -91,26 +79,20 @@ func TestFetchMetadata(t *testing.T) {
|
||||
</InputEndpoints>
|
||||
</Instance>
|
||||
</Instances>
|
||||
</SharedConfig>`)},
|
||||
map[string]string{
|
||||
"local-ipv4": "100.73.202.64",
|
||||
"public-ipv4": "191.239.39.77",
|
||||
</SharedConfig>`}),
|
||||
metadata: datasource.Metadata{
|
||||
PrivateIPv4: net.ParseIP("100.73.202.64"),
|
||||
PublicIPv4: net.ParseIP("191.239.39.77"),
|
||||
},
|
||||
},
|
||||
} {
|
||||
a := waagent{tt.root, tt.files.readFile}
|
||||
metadataBytes, err := a.FetchMetadata()
|
||||
a := waagent{tt.root, tt.files.ReadFile}
|
||||
metadata, err := a.FetchMetadata()
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err)
|
||||
}
|
||||
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 %+v: want %#v, got %#v", tt, tt.metadata, metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,25 +100,25 @@ func TestFetchMetadata(t *testing.T) {
|
||||
func TestFetchUserdata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
files mockFilesystem
|
||||
files test.MockFilesystem
|
||||
}{
|
||||
{
|
||||
"/",
|
||||
mockFilesystem{},
|
||||
test.NewMockFilesystem(),
|
||||
},
|
||||
{
|
||||
"/",
|
||||
mockFilesystem{"/CustomData": []byte{}},
|
||||
test.NewMockFilesystem(test.File{Path: "/CustomData", Contents: ""}),
|
||||
},
|
||||
{
|
||||
"/var/lib/waagent/",
|
||||
mockFilesystem{"/var/lib/waagent/CustomData": []byte{}},
|
||||
test.NewMockFilesystem(test.File{Path: "/var/lib/waagent/CustomData", Contents: ""}),
|
||||
},
|
||||
} {
|
||||
a := waagent{tt.root, tt.files.readFile}
|
||||
a := waagent{tt.root, tt.files.ReadFile}
|
||||
_, err := a.FetchUserdata()
|
||||
if err != nil {
|
||||
t.Fatalf("bad error for %q: want %v, got %q", tt, nil, err)
|
||||
t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user