Merge pull request #158 from jonboulle/nettttt
cloudinit: retrieve IPv4 addresses from metadata
This commit is contained in:
commit
80d00cde94
@ -88,7 +88,16 @@ func main() {
|
|||||||
die()
|
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 len(userdataBytes) > 0 {
|
||||||
if err := processUserdata(string(userdataBytes), env); err != nil {
|
if err := processUserdata(string(userdataBytes), env); err != nil {
|
||||||
fmt.Printf("Failed to process user-data: %v\n", err)
|
fmt.Printf("Failed to process user-data: %v\n", err)
|
||||||
|
@ -17,10 +17,16 @@ type Environment struct {
|
|||||||
substitutions map[string]string
|
substitutions map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnvironment(root, configRoot, workspace, netconfType, sshKeyName string) *Environment {
|
// TODO(jonboulle): this is getting unwieldy, should be able to simplify the interface somehow
|
||||||
substitutions := map[string]string{
|
func NewEnvironment(root, configRoot, workspace, netconfType, sshKeyName string, substitutions map[string]string) *Environment {
|
||||||
|
// If certain values are not in the supplied substitution, fall back to retrieving them from the environment
|
||||||
|
for k, v := range map[string]string{
|
||||||
"$public_ipv4": os.Getenv("COREOS_PUBLIC_IPV4"),
|
"$public_ipv4": os.Getenv("COREOS_PUBLIC_IPV4"),
|
||||||
"$private_ipv4": os.Getenv("COREOS_PRIVATE_IPV4"),
|
"$private_ipv4": os.Getenv("COREOS_PRIVATE_IPV4"),
|
||||||
|
} {
|
||||||
|
if _, ok := substitutions[k]; !ok {
|
||||||
|
substitutions[k] = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &Environment{root, configRoot, workspace, netconfType, sshKeyName, substitutions}
|
return &Environment{root, configRoot, workspace, netconfType, sshKeyName, substitutions}
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,47 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestEnvironmentApply(t *testing.T) {
|
func TestEnvironmentApply(t *testing.T) {
|
||||||
os.Setenv("COREOS_PUBLIC_IPV4", "192.0.2.3")
|
os.Setenv("COREOS_PUBLIC_IPV4", "1.2.3.4")
|
||||||
os.Setenv("COREOS_PRIVATE_IPV4", "192.0.2.203")
|
os.Setenv("COREOS_PRIVATE_IPV4", "5.6.7.8")
|
||||||
env := NewEnvironment("./", "./", "./", "", "")
|
for _, tt := range []struct {
|
||||||
input := `[Service]
|
subs map[string]string
|
||||||
|
input string
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// Substituting both values directly should always take precedence
|
||||||
|
// over environment variables
|
||||||
|
map[string]string{
|
||||||
|
"$public_ipv4": "192.0.2.3",
|
||||||
|
"$private_ipv4": "192.0.2.203",
|
||||||
|
},
|
||||||
|
`[Service]
|
||||||
ExecStart=/usr/bin/echo "$public_ipv4"
|
ExecStart=/usr/bin/echo "$public_ipv4"
|
||||||
ExecStop=/usr/bin/echo $private_ipv4
|
ExecStop=/usr/bin/echo $private_ipv4
|
||||||
ExecStop=/usr/bin/echo $unknown
|
ExecStop=/usr/bin/echo $unknown`,
|
||||||
`
|
`[Service]
|
||||||
expected := `[Service]
|
|
||||||
ExecStart=/usr/bin/echo "192.0.2.3"
|
ExecStart=/usr/bin/echo "192.0.2.3"
|
||||||
ExecStop=/usr/bin/echo 192.0.2.203
|
ExecStop=/usr/bin/echo 192.0.2.203
|
||||||
ExecStop=/usr/bin/echo $unknown
|
ExecStop=/usr/bin/echo $unknown`,
|
||||||
`
|
},
|
||||||
|
{
|
||||||
|
// Substituting one value directly while falling back with the other
|
||||||
|
map[string]string{"$private_ipv4": "127.0.0.1"},
|
||||||
|
"$private_ipv4\n$public_ipv4",
|
||||||
|
"127.0.0.1\n1.2.3.4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Falling back to environment variables for both values
|
||||||
|
map[string]string{"foo": "bar"},
|
||||||
|
"$private_ipv4\n$public_ipv4",
|
||||||
|
"5.6.7.8\n1.2.3.4",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
|
||||||
output := env.Apply(input)
|
env := NewEnvironment("./", "./", "./", "", "", tt.subs)
|
||||||
if output != expected {
|
got := env.Apply(tt.input)
|
||||||
t.Fatalf("Environment incorrectly applied.\nOutput:\n%s\nExpected:\n%s", output, expected)
|
if got != tt.out {
|
||||||
|
t.Fatalf("Environment incorrectly applied.\ngot:\n%s\nwant:\n%s", got, tt.out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package initialize
|
package initialize
|
||||||
|
|
||||||
import (
|
import "encoding/json"
|
||||||
"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) {
|
func ParseMetaData(contents string) (cfg CloudConfig, err error) {
|
||||||
var metadata struct {
|
var metadata struct {
|
||||||
SSHAuthorizedKeyMap map[string]string `json:"public_keys"`
|
SSHAuthorizedKeyMap map[string]string `json:"public_keys"`
|
||||||
@ -24,3 +24,23 @@ func ParseMetaData(contents string) (cfg CloudConfig, err error) {
|
|||||||
cfg.NetworkConfigPath = metadata.NetworkConfig.ContentPath
|
cfg.NetworkConfigPath = metadata.NetworkConfig.ContentPath
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
36
initialize/meta_data_test.go
Normal file
36
initialize/meta_data_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user