initialize: change env to process from metadata

We don't use general substitutions so just have env pick the values it
wants to substitute.
This commit is contained in:
Alex Crawford 2015-01-26 15:45:15 -08:00
parent 650a239fdb
commit 42153edbbc
5 changed files with 43 additions and 139 deletions

View File

@ -182,11 +182,8 @@ func main() {
os.Exit(1)
}
// Extract IPv4 addresses from metadata
subs := initialize.ExtractIPsFromMetadata(metadata)
// 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, metadata)
userdata := env.Apply(string(userdataBytes))
var ccu *config.CloudConfig

View File

@ -15,12 +15,14 @@
package initialize
import (
"net"
"os"
"path"
"regexp"
"strings"
"github.com/coreos/coreos-cloudinit/config"
"github.com/coreos/coreos-cloudinit/datasource"
"github.com/coreos/coreos-cloudinit/system"
)
@ -36,20 +38,18 @@ type Environment struct {
}
// 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 {
if substitutions == nil {
substitutions = make(map[string]string)
func NewEnvironment(root, configRoot, workspace, netconfType, sshKeyName string, metadata datasource.Metadata) *Environment {
firstNonNull := func(ip net.IP, env string) string {
if ip == nil {
return env
}
// 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"),
"$private_ipv4": os.Getenv("COREOS_PRIVATE_IPV4"),
"$public_ipv6": os.Getenv("COREOS_PUBLIC_IPV6"),
"$private_ipv6": os.Getenv("COREOS_PRIVATE_IPV6"),
} {
if _, ok := substitutions[k]; !ok {
substitutions[k] = v
return ip.String()
}
substitutions := map[string]string{
"$public_ipv4": firstNonNull(metadata.PublicIPv4, os.Getenv("COREOS_PUBLIC_IPV4")),
"$private_ipv4": firstNonNull(metadata.PrivateIPv4, os.Getenv("COREOS_PRIVATE_IPV4")),
"$public_ipv6": firstNonNull(metadata.PublicIPv6, os.Getenv("COREOS_PUBLIC_IPV6")),
"$private_ipv6": firstNonNull(metadata.PrivateIPv6, os.Getenv("COREOS_PRIVATE_IPV6")),
}
return &Environment{root, configRoot, workspace, netconfType, sshKeyName, substitutions}
}

View File

@ -16,10 +16,12 @@ package initialize
import (
"io/ioutil"
"net"
"os"
"path"
"testing"
"github.com/coreos/coreos-cloudinit/datasource"
"github.com/coreos/coreos-cloudinit/system"
)
@ -29,18 +31,18 @@ func TestEnvironmentApply(t *testing.T) {
os.Setenv("COREOS_PUBLIC_IPV6", "1234::")
os.Setenv("COREOS_PRIVATE_IPV6", "5678::")
for _, tt := range []struct {
subs map[string]string
metadata datasource.Metadata
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",
"$public_ipv6": "fe00:1234::",
"$private_ipv6": "fe00:5678::",
datasource.Metadata{
PublicIPv4: net.ParseIP("192.0.2.3"),
PrivateIPv4: net.ParseIP("192.0.2.203"),
PublicIPv6: net.ParseIP("fe00:1234::"),
PrivateIPv6: net.ParseIP("fe00:5678::"),
},
`[Service]
ExecStart=/usr/bin/echo "$public_ipv4 $public_ipv6"
@ -53,25 +55,29 @@ ExecStop=/usr/bin/echo $unknown`,
},
{
// Substituting one value directly while falling back with the other
map[string]string{"$private_ipv4": "127.0.0.1"},
datasource.Metadata{
PrivateIPv4: net.ParseIP("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"},
datasource.Metadata{},
"$private_ipv4\n$public_ipv4",
"5.6.7.8\n1.2.3.4",
},
{
// No substitutions
nil,
datasource.Metadata{},
"$private_ipv4\nfoobar",
"5.6.7.8\nfoobar",
},
{
// Escaping substitutions
map[string]string{"$private_ipv4": "127.0.0.1"},
datasource.Metadata{
PrivateIPv4: net.ParseIP("127.0.0.1"),
},
`\$private_ipv4
$private_ipv4
addr: \$private_ipv4
@ -83,13 +89,13 @@ addr: $private_ipv4
},
{
// No substitutions with escaping
nil,
datasource.Metadata{},
"\\$test\n$test",
"\\$test\n$test",
},
} {
env := NewEnvironment("./", "./", "./", "", "", tt.subs)
env := NewEnvironment("./", "./", "./", "", "", tt.metadata)
got := env.Apply(tt.input)
if got != tt.out {
t.Fatalf("Environment incorrectly applied.\ngot:\n%s\nwant:\n%s", got, tt.out)
@ -98,11 +104,11 @@ addr: $private_ipv4
}
func TestEnvironmentFile(t *testing.T) {
subs := map[string]string{
"$public_ipv4": "1.2.3.4",
"$private_ipv4": "5.6.7.8",
"$public_ipv6": "1234::",
"$private_ipv6": "5678::",
metadata := datasource.Metadata{
PublicIPv4: net.ParseIP("1.2.3.4"),
PrivateIPv4: net.ParseIP("5.6.7.8"),
PublicIPv6: net.ParseIP("1234::"),
PrivateIPv6: net.ParseIP("5678::"),
}
expect := "COREOS_PRIVATE_IPV4=5.6.7.8\nCOREOS_PRIVATE_IPV6=5678::\nCOREOS_PUBLIC_IPV4=1.2.3.4\nCOREOS_PUBLIC_IPV6=1234::\n"
@ -112,7 +118,7 @@ func TestEnvironmentFile(t *testing.T) {
}
defer os.RemoveAll(dir)
env := NewEnvironment("./", "./", "./", "", "", subs)
env := NewEnvironment("./", "./", "./", "", "", metadata)
ef := env.DefaultEnvironmentFile()
err = system.WriteEnvFile(ef, dir)
if err != nil {
@ -131,14 +137,10 @@ func TestEnvironmentFile(t *testing.T) {
}
func TestEnvironmentFileNil(t *testing.T) {
subs := map[string]string{
"$public_ipv4": "",
"$private_ipv4": "",
"$public_ipv6": "",
"$private_ipv6": "",
}
os.Clearenv()
metadata := datasource.Metadata{}
env := NewEnvironment("./", "./", "./", "", "", subs)
env := NewEnvironment("./", "./", "./", "", "", metadata)
ef := env.DefaultEnvironmentFile()
if ef != nil {
t.Fatalf("Environment file not nil: %v", ef)

View File

@ -1,50 +0,0 @@
// 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 initialize
import (
"sort"
"github.com/coreos/coreos-cloudinit/datasource"
)
// ExtractIPsFromMetaData parses a JSON blob in the OpenStack metadata service
// format and returns a substitution map possibly containing private_ipv4,
// public_ipv4, private_ipv6, and public_ipv6 addresses.
func ExtractIPsFromMetadata(metadata datasource.Metadata) map[string]string {
subs := map[string]string{}
if metadata.PrivateIPv4 != nil {
subs["$private_ipv4"] = metadata.PrivateIPv4.String()
}
if metadata.PublicIPv4 != nil {
subs["$public_ipv4"] = metadata.PublicIPv4.String()
}
if metadata.PrivateIPv6 != nil {
subs["$private_ipv6"] = metadata.PrivateIPv6.String()
}
if metadata.PublicIPv6 != nil {
subs["$public_ipv6"] = metadata.PublicIPv6.String()
}
return subs
}
func sortedKeys(m map[string]string) (keys []string) {
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
return
}

View File

@ -1,45 +0,0 @@
// 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 initialize
import (
"net"
"reflect"
"testing"
"github.com/coreos/coreos-cloudinit/datasource"
)
func TestExtractIPsFromMetadata(t *testing.T) {
for i, tt := range []struct {
in datasource.Metadata
out map[string]string
}{
{
datasource.Metadata{
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::"},
},
} {
got := ExtractIPsFromMetadata(tt.in)
if !reflect.DeepEqual(got, tt.out) {
t.Errorf("case %d: got %s, want %s", i, got, tt.out)
}
}
}