cloudinit: retrieve IPv4 addresses from metadata

This uses the new MetadataService implementation to retrieve values for
$private_ipv4 and $public_ipv4 substitutions, instead of using
environment variables.
This commit is contained in:
Jonathan Boulle 2014-06-24 17:46:06 -07:00
parent 29a7b0e34f
commit ba1c1e97d0
5 changed files with 77 additions and 17 deletions

View File

@ -86,7 +86,16 @@ func main() {
die()
}
env := initialize.NewEnvironment("/", ds.ConfigRoot(), workspace, convertNetconf, sshKeyName)
var subs map[string]string
if len(metadataBytes) > 0 {
subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
if err != nil {
fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
die()
}
}
env := initialize.NewEnvironment("/", ds.ConfigRoot(), workspace, convertNetconf, sshKeyName, subs)
if len(userdataBytes) > 0 {
if err := processUserdata(string(userdataBytes), env); err != nil {
fmt.Printf("Failed to process user-data: %v\n", err)

View File

@ -1,7 +1,6 @@
package initialize
import (
"os"
"path"
"strings"
)
@ -17,11 +16,8 @@ type Environment struct {
substitutions map[string]string
}
func NewEnvironment(root, configRoot, workspace, netconfType, sshKeyName string) *Environment {
substitutions := map[string]string{
"$public_ipv4": os.Getenv("COREOS_PUBLIC_IPV4"),
"$private_ipv4": os.Getenv("COREOS_PRIVATE_IPV4"),
}
// TODO(jonboulle): this is getting unwieldy, should be able to simplify the interface somehow
func NewEnvironment(root, configRoot, workspace, netconfType, sshKeyName string, substitutions map[string]string) *Environment {
return &Environment{root, configRoot, workspace, netconfType, sshKeyName, substitutions}
}

View File

@ -1,14 +1,13 @@
package initialize
import (
"os"
"testing"
)
import "testing"
func TestEnvironmentApply(t *testing.T) {
os.Setenv("COREOS_PUBLIC_IPV4", "192.0.2.3")
os.Setenv("COREOS_PRIVATE_IPV4", "192.0.2.203")
env := NewEnvironment("./", "./", "./", "", "")
subs := map[string]string{
"$public_ipv4": "192.0.2.3",
"$private_ipv4": "192.0.2.203",
}
env := NewEnvironment("./", "./", "./", "", "", subs)
input := `[Service]
ExecStart=/usr/bin/echo "$public_ipv4"
ExecStop=/usr/bin/echo $private_ipv4

View File

@ -1,9 +1,9 @@
package initialize
import (
"encoding/json"
)
import "encoding/json"
// ParseMetaData parses a JSON blob in the OpenStack metadata service format, and
// converts it to a CloudConfig
func ParseMetaData(contents string) (cfg CloudConfig, err error) {
var metadata struct {
SSHAuthorizedKeyMap map[string]string `json:"public_keys"`
@ -24,3 +24,23 @@ func ParseMetaData(contents string) (cfg CloudConfig, err error) {
cfg.NetworkConfigPath = metadata.NetworkConfig.ContentPath
return
}
// ExtractIPsFromMetaData parses a JSON blob in the OpenStack metadata service format,
// and returns a substitution map possibly containing private_ipv4 and public_ipv4 addresses
func ExtractIPsFromMetadata(contents []byte) (map[string]string, error) {
var ips struct {
Public string `json:"public-ipv4"`
Private string `json:"local-ipv4"`
}
if err := json.Unmarshal(contents, &ips); err != nil {
return nil, err
}
m := make(map[string]string)
if ips.Private != "" {
m["$private_ipv4"] = ips.Private
}
if ips.Public != "" {
m["$public_ipv4"] = ips.Public
}
return m, nil
}

View File

@ -0,0 +1,36 @@
package initialize
import "reflect"
import "testing"
func TestExtractIPsFromMetadata(t *testing.T) {
for i, tt := range []struct {
in []byte
err bool
out map[string]string
}{
{
[]byte(`{"public-ipv4": "12.34.56.78", "local-ipv4": "1.2.3.4"}`),
false,
map[string]string{"$public_ipv4": "12.34.56.78", "$private_ipv4": "1.2.3.4"},
},
{
[]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)
if (err != nil) != tt.err {
t.Errorf("bad error state (got %t, want %t)", err != nil, tt.err)
}
if !reflect.DeepEqual(got, tt.out) {
t.Errorf("case %d: got %s, want %s", i, got, tt.out)
}
}
}