Compare commits

...

24 Commits

Author SHA1 Message Date
Alex Crawford
eca51031c8 coreos-cloudinit: bump to 0.11.4 2014-11-21 20:11:37 -08:00
Alex Crawford
19522bcb82 Merge pull request #266 from crawford/config
config: update configs to match etcd, fleet, and flannel
2014-11-21 20:10:34 -08:00
Alex Crawford
62248ea33d config/fleet: fix configs
Added EtcdKeyPrefix and fixed the types of EngineReconcileInterval and EtcdRequestTimeout.
2014-11-21 16:57:00 -08:00
Alex Crawford
d2a19cc86d config/flannel: correct - vs _ 2014-11-21 16:57:00 -08:00
Alex Crawford
08131ffab1 config/etcd: fix configs
This new table is pulled from the etcd codebase rather than the docs...

Added:
 GraphiteHost
 PeerElectionTimeout
 PeerHeartbeatInterval
 PeerKeyFile
 RetryInterval
 SnapshotCount
 StrTrace
 VeryVeryVerbose

Fixed types:
 ClusterActiveSize
 ClusterRemoveDelay
 ClusterSyncInterval
 HTTPReadTimeout
 HTTPWriteTimeout
 MaxResultBuffer
 MaxRetryAttempts
 Snapshot
 Verbose
 VeryVerbose

Renamed:
 Cors

Removed:
 MaxClusterSize
 CPUProfileFile
2014-11-21 16:57:00 -08:00
Alex Crawford
4a0019c669 config: add support for float64 2014-11-21 16:13:49 -08:00
Alex Crawford
3275ead1ec coreos-cloudinit: bump to 0.11.3+git 2014-11-21 12:25:26 -08:00
Alex Crawford
32b6a55724 coreos-cloudinit: bump to 0.11.3 2014-11-21 12:25:04 -08:00
Alex Crawford
6c43644369 Merge pull request #265 from crawford/update
config/update: add "off" as a valid strategy
2014-11-21 12:22:45 -08:00
Alex Crawford
e6593d49e6 config/update: add "off" as a valid strategy
It was assumed that the user would specify the reboot strategy as an
unquoted value. In the case that they turn off updates, `off` is
interpreted as a boolean and the normalization pass converts that to
`false`. In the event that the user uses `"off"`, it's interpreted as a
string and not modified.
2014-11-21 10:41:03 -08:00
Alex Crawford
ab752b239f coreos-cloudinit: bump to 0.11.2+git 2014-11-20 11:29:25 -08:00
Alex Crawford
0742e4d357 coreos-cloudinit: bump to 0.11.2 2014-11-20 11:29:12 -08:00
Alex Crawford
78f586ec9e Merge pull request #262 from crawford/permissions
config: fix parsing of file permissions
2014-11-20 11:28:11 -08:00
Alex Crawford
6f91b76d79 docs: correct type of permissions 2014-11-20 11:14:44 -08:00
Alex Crawford
5c80ccacc4 config: fix parsing of file permissions
The file permissions can be specified (unfortunately) as a string or an
octal integer. During the normalization step, every field is
unmarshalled into an interface{}. String types are kept in tact but
integers are converted to decimal integers. If the raw config
represented the permissions as an octal, it would be converted to
decimal _before_ it was saved to RawFilePermissions. Permissions() would
then try to convert it again, assuming it was an octal. The new behavior
doesn't assume the radix of the number, allowing decimal and octal
input.
2014-11-20 11:14:44 -08:00
Alex Crawford
97758b343b coreos-cloudinit: bump to 0.11.1+git 2014-11-18 12:14:34 -08:00
Alex Crawford
fb6f52b360 coreos-cloudinit: bump to 0.11.1 2014-11-18 12:14:29 -08:00
Alex Crawford
786cd2a539 Merge pull request #259 from crawford/hyphen
config/validate: disable - vs _ message for now
2014-11-18 12:12:26 -08:00
Alex Crawford
45793f1254 config/validate: disable - vs _ message for now 2014-11-18 12:11:50 -08:00
Alex Crawford
b621756d92 Merge pull request #258 from crawford/header
config/validate: fix line number for header check
2014-11-18 12:11:35 -08:00
Alex Crawford
a5b5c700a6 config/validate: fix line number for header check 2014-11-18 12:02:23 -08:00
Alex Crawford
d7602f3c08 Merge pull request #244 from eyakubovich/master
flannel: added flannel support and helper to make dropins
2014-11-14 10:46:19 -08:00
Eugene Yakubovich
a20addd05e flannel: added flannel support and helper to make dropins
fleet, flannel, and etcd all generate dropins from config.
To reduce code duplication, factor out a helper to do that.
2014-11-14 10:45:23 -08:00
Alex Crawford
d9d89a6fa0 coreos-cloudinit: bump to 0.11.0+git 2014-11-14 10:42:00 -08:00
24 changed files with 316 additions and 83 deletions

View File

@@ -97,6 +97,29 @@ For more information on fleet configuration, see the [fleet documentation][fleet
[fleet-config]: https://github.com/coreos/fleet/blob/master/Documentation/deployment-and-configuration.md#configuration
#### flannel
The `coreos.flannel.*` parameters also work very similarly to `coreos.etcd.*` and `coreos.fleet.*`. They can be used to set enviornment variables for flanneld. Given the following cloud-config...
```yaml
#cloud-config
coreos:
flannel:
etcd-prefix: /coreos.com/network2
```
...will generate systemd unit drop-in like so:
```
[Service]
Environment="FLANNELD_ETCD_PREFIX=/coreos.com/network2"
```
For complete list of flannel configuraion parameters, see the [flannel documentation][flannel-readme].
[flannel-readme]: https://github.com/coreos/flannel/blob/master/README.md
#### update
The `coreos.update.*` parameters manipulate settings related to how CoreOS instances are updated.
@@ -303,7 +326,7 @@ Each item in the list may have the following keys:
- **path**: Absolute location on disk where contents should be written
- **content**: Data to write at the provided `path`
- **permissions**: String representing file permissions in octal notation (i.e. '0644')
- **permissions**: Integer representing file permissions, typically in octal notation (i.e. 0644)
- **owner**: User and group that should own the file written to disk. This is equivalent to the `<user>:<group>` argument to `chown <user>:<group> <path>`.
Explicitly not implemented is the **encoding** attribute.

View File

@@ -30,11 +30,12 @@ import (
type CloudConfig struct {
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
Coreos struct {
Etcd Etcd `yaml:"etcd"`
Fleet Fleet `yaml:"fleet"`
OEM OEM `yaml:"oem"`
Update Update `yaml:"update"`
Units []Unit `yaml:"units"`
Etcd Etcd `yaml:"etcd"`
Flannel Flannel `yaml:"flannel"`
Fleet Fleet `yaml:"fleet"`
OEM OEM `yaml:"oem"`
Update Update `yaml:"update"`
Units []Unit `yaml:"units"`
} `yaml:"coreos"`
WriteFiles []File `yaml:"write_files"`
Hostname string `yaml:"hostname"`

View File

@@ -276,6 +276,40 @@ Address=10.209.171.177/19
if cfg.Coreos.Update.RebootStrategy != "reboot" {
t.Errorf("Failed to parse locksmith strategy")
}
contents = `
coreos:
write_files:
- path: /home/me/notes
permissions: 0744
`
cfg, err = NewCloudConfig(contents)
if err != nil {
t.Fatalf("Encountered unexpected error :%v", err)
}
if len(cfg.WriteFiles) != 1 {
t.Error("Failed to parse correct number of write_files")
} else {
wf := cfg.WriteFiles[0]
if wf.Content != "" {
t.Errorf("WriteFile has incorrect contents '%s'", wf.Content)
}
if wf.Encoding != "" {
t.Errorf("WriteFile has incorrect encoding %s", wf.Encoding)
}
// Verify that the normalization of the config converted 0744 to its decimal
// representation, 484.
if wf.RawFilePermissions != "484" {
t.Errorf("WriteFile has incorrect permissions %s", wf.RawFilePermissions)
}
if wf.Path != "/home/me/notes" {
t.Errorf("WriteFile has incorrect path %s", wf.Path)
}
if wf.Owner != "" {
t.Errorf("WriteFile has incorrect owner %s", wf.Owner)
}
}
}
// Assert that our interface conversion doesn't panic
@@ -479,6 +513,7 @@ func TestNormalizeKeys(t *testing.T) {
{"a:\n b:\n - key-name: the-value\n", "a:\n b:\n - key_name: the-value\n"},
{"coreos:\n update:\n reboot-strategy: off\n", "coreos:\n update:\n reboot_strategy: false\n"},
{"coreos:\n update:\n reboot-strategy: 'off'\n", "coreos:\n update:\n reboot_strategy: \"off\"\n"},
} {
out, err := normalizeConfig(tt.in)
if err != nil {

View File

@@ -17,32 +17,37 @@
package config
type Etcd struct {
Addr string `yaml:"addr" env:"ETCD_ADDR"`
BindAddr string `yaml:"bind_addr" env:"ETCD_BIND_ADDR"`
CAFile string `yaml:"ca_file" env:"ETCD_CA_FILE"`
CertFile string `yaml:"cert_file" env:"ETCD_CERT_FILE"`
ClusterActiveSize string `yaml:"cluster_active_size" env:"ETCD_CLUSTER_ACTIVE_SIZE"`
ClusterRemoveDelay string `yaml:"cluster_remove_delay" env:"ETCD_CLUSTER_REMOVE_DELAY"`
ClusterSyncInterval string `yaml:"cluster_sync_interval" env:"ETCD_CLUSTER_SYNC_INTERVAL"`
Cors string `yaml:"cors" env:"ETCD_CORS"`
CPUProfileFile string `yaml:"cpu_profile_file" env:"ETCD_CPU_PROFILE_FILE"`
DataDir string `yaml:"data_dir" env:"ETCD_DATA_DIR"`
Discovery string `yaml:"discovery" env:"ETCD_DISCOVERY"`
HTTPReadTimeout string `yaml:"http_read_timeout" env:"ETCD_HTTP_READ_TIMEOUT"`
HTTPWriteTimeout string `yaml:"http_write_timeout" env:"ETCD_HTTP_WRITE_TIMEOUT"`
KeyFile string `yaml:"key_file" env:"ETCD_KEY_FILE"`
MaxClusterSize string `yaml:"max_cluster_size" env:"ETCD_MAX_CLUSTER_SIZE"`
MaxResultBuffer string `yaml:"max_result_buffer" env:"ETCD_MAX_RESULT_BUFFER"`
MaxRetryAttempts string `yaml:"max_retry_attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"`
Name string `yaml:"name" env:"ETCD_NAME"`
PeerAddr string `yaml:"peer_addr" env:"ETCD_PEER_ADDR"`
PeerBindAddr string `yaml:"peer_bind_addr" env:"ETCD_PEER_BIND_ADDR"`
PeerCAFile string `yaml:"peer_ca_file" env:"ETCD_PEER_CA_FILE"`
PeerCertFile string `yaml:"peer_cert_file" env:"ETCD_PEER_CERT_FILE"`
PeerKeyFile string `yaml:"peer_key_file" env:"ETCD_PEER_KEY_FILE"`
Peers string `yaml:"peers" env:"ETCD_PEERS"`
PeersFile string `yaml:"peers_file" env:"ETCD_PEERS_FILE"`
Snapshot string `yaml:"snapshot" env:"ETCD_SNAPSHOT"`
Verbose string `yaml:"verbose" env:"ETCD_VERBOSE"`
VeryVerbose string `yaml:"very_verbose" env:"ETCD_VERY_VERBOSE"`
Addr string `yaml:"addr" env:"ETCD_ADDR"`
BindAddr string `yaml:"bind_addr" env:"ETCD_BIND_ADDR"`
CAFile string `yaml:"ca_file" env:"ETCD_CA_FILE"`
CertFile string `yaml:"cert_file" env:"ETCD_CERT_FILE"`
ClusterActiveSize int `yaml:"cluster_active_size" env:"ETCD_CLUSTER_ACTIVE_SIZE"`
ClusterRemoveDelay float64 `yaml:"cluster_remove_delay" env:"ETCD_CLUSTER_REMOVE_DELAY"`
ClusterSyncInterval float64 `yaml:"cluster_sync_interval" env:"ETCD_CLUSTER_SYNC_INTERVAL"`
CorsOrigins string `yaml:"cors" env:"ETCD_CORS"`
DataDir string `yaml:"data_dir" env:"ETCD_DATA_DIR"`
Discovery string `yaml:"discovery" env:"ETCD_DISCOVERY"`
GraphiteHost string `yaml:"graphite_host" env:"ETCD_GRAPHITE_HOST"`
HTTPReadTimeout float64 `yaml:"http_read_timeout" env:"ETCD_HTTP_READ_TIMEOUT"`
HTTPWriteTimeout float64 `yaml:"http_write_timeout" env:"ETCD_HTTP_WRITE_TIMEOUT"`
KeyFile string `yaml:"key_file" env:"ETCD_KEY_FILE"`
MaxResultBuffer int `yaml:"max_result_buffer" env:"ETCD_MAX_RESULT_BUFFER"`
MaxRetryAttempts int `yaml:"max_retry_attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"`
Name string `yaml:"name" env:"ETCD_NAME"`
PeerAddr string `yaml:"peer_addr" env:"ETCD_PEER_ADDR"`
PeerBindAddr string `yaml:"peer_bind_addr" env:"ETCD_PEER_BIND_ADDR"`
PeerCAFile string `yaml:"peer_ca_file" env:"ETCD_PEER_CA_FILE"`
PeerCertFile string `yaml:"peer_cert_file" env:"ETCD_PEER_CERT_FILE"`
PeerElectionTimeout int `yaml:"peer_election_timeout" env:"ETCD_PEER_ELECTION_TIMEOUT"`
PeerHeartbeatInterval int `yaml:"peer_heartbeat_interval" env:"ETCD_PEER_HEARTBEAT_INTERVAL"`
PeerKeyFile string `yaml:"peer_key_file" env:"ETCD_PEER_KEY_FILE"`
Peers string `yaml:"peers" env:"ETCD_PEERS"`
PeersFile string `yaml:"peers_file" env:"ETCD_PEERS_FILE"`
RetryInterval float64 `yaml:"retry_interval" env:"ETCD_RETRY_INTERVAL"`
Snapshot bool `yaml:"snapshot" env:"ETCD_SNAPSHOT"`
SnapshotCount int `yaml:"snapshot_count" env:"ETCD_SNAPSHOTCOUNT"`
StrTrace string `yaml:"trace" env:"ETCD_TRACE"`
Verbose bool `yaml:"verbose" env:"ETCD_VERBOSE"`
VeryVerbose bool `yaml:"very_verbose" env:"ETCD_VERY_VERBOSE"`
VeryVeryVerbose bool `yaml:"very_very_verbose" env:"ETCD_VERY_VERY_VERBOSE"`
}

9
config/flannel.go Normal file
View File

@@ -0,0 +1,9 @@
package config
type Flannel struct {
EtcdEndpoint string `yaml:"etcd_endpoint" env:"FLANNELD_ETCD_ENDPOINT"`
EtcdPrefix string `yaml:"etcd_prefix" env:"FLANNELD_ETCD_PREFIX"`
IPMasq string `yaml:"ip_masq" env:"FLANNELD_IP_MASQ"`
SubnetFile string `yaml:"subnet_file" env:"FLANNELD_SUBNET_FILE"`
Iface string `yaml:"interface" env:"FLANNELD_IFACE"`
}

View File

@@ -17,14 +17,15 @@
package config
type Fleet struct {
AgentTTL string `yaml:"agent_ttl" env:"FLEET_AGENT_TTL"`
EngineReconcileInterval string `yaml:"engine_reconcile_interval" env:"FLEET_ENGINE_RECONCILE_INTERVAL"`
EtcdCAFile string `yaml:"etcd_cafile" env:"FLEET_ETCD_CAFILE"`
EtcdCertFile string `yaml:"etcd_certfile" env:"FLEET_ETCD_CERTFILE"`
EtcdKeyFile string `yaml:"etcd_keyfile" env:"FLEET_ETCD_KEYFILE"`
EtcdRequestTimeout string `yaml:"etcd_request_timeout" env:"FLEET_ETCD_REQUEST_TIMEOUT"`
EtcdServers string `yaml:"etcd_servers" env:"FLEET_ETCD_SERVERS"`
Metadata string `yaml:"metadata" env:"FLEET_METADATA"`
PublicIP string `yaml:"public_ip" env:"FLEET_PUBLIC_IP"`
Verbosity string `yaml:"verbosity" env:"FLEET_VERBOSITY"`
AgentTTL string `yaml:"agent_ttl" env:"FLEET_AGENT_TTL"`
EngineReconcileInterval float64 `yaml:"engine_reconcile_interval" env:"FLEET_ENGINE_RECONCILE_INTERVAL"`
EtcdCAFile string `yaml:"etcd_cafile" env:"FLEET_ETCD_CAFILE"`
EtcdCertFile string `yaml:"etcd_certfile" env:"FLEET_ETCD_CERTFILE"`
EtcdKeyFile string `yaml:"etcd_keyfile" env:"FLEET_ETCD_KEYFILE"`
EtcdKeyPrefix string `yaml:"etcd_key_prefix" env:"FLEET_ETCD_KEY_PREFIX"`
EtcdRequestTimeout float64 `yaml:"etcd_request_timeout" env:"FLEET_ETCD_REQUEST_TIMEOUT"`
EtcdServers string `yaml:"etcd_servers" env:"FLEET_ETCD_SERVERS"`
Metadata string `yaml:"metadata" env:"FLEET_METADATA"`
PublicIP string `yaml:"public_ip" env:"FLEET_PUBLIC_IP"`
Verbosity int `yaml:"verbosity" env:"FLEET_VERBOSITY"`
}

View File

@@ -17,7 +17,7 @@
package config
type Update struct {
RebootStrategy string `yaml:"reboot_strategy" env:"REBOOT_STRATEGY" valid:"best-effort,etcd-lock,reboot,false"`
RebootStrategy string `yaml:"reboot_strategy" env:"REBOOT_STRATEGY" valid:"best-effort,etcd-lock,reboot,off,false"`
Group string `yaml:"group" env:"GROUP"`
Server string `yaml:"server" env:"SERVER"`
}

View File

@@ -125,7 +125,7 @@ func toNode(v interface{}, c context, n *node) {
n.children = append(n.children, cn)
c.Increment()
}
case reflect.String, reflect.Int, reflect.Bool:
case reflect.String, reflect.Int, reflect.Bool, reflect.Float64:
default:
panic(fmt.Sprintf("toNode(): unhandled kind %s", vv.Kind()))
}

View File

@@ -61,7 +61,7 @@ func checkNodeStructure(n, g node, r *Report) {
toNode(reflect.New(c).Elem().Interface(), context{}, &cg)
checkNodeStructure(cn, cg, r)
}
case reflect.String, reflect.Int, reflect.Bool:
case reflect.String, reflect.Int, reflect.Float64, reflect.Bool:
default:
panic(fmt.Sprintf("checkNodeStructure(): unhandled kind %s", g.Kind()))
}
@@ -92,7 +92,7 @@ func checkNodeValidity(n, g node, r *Report) {
toNode(reflect.New(c).Elem().Interface(), context{}, &cg)
checkNodeValidity(cn, cg, r)
}
case reflect.String, reflect.Int, reflect.Bool:
case reflect.String, reflect.Int, reflect.Float64, reflect.Bool:
default:
panic(fmt.Sprintf("checkNodeValidity(): unhandled kind %s", g.Kind()))
}
@@ -104,10 +104,10 @@ func checkNodeValidity(n, g node, r *Report) {
func isCompatible(n, g reflect.Kind) bool {
switch g {
case reflect.String:
return n == reflect.String || n == reflect.Int || n == reflect.Bool
return n == reflect.String || n == reflect.Int || n == reflect.Float64 || n == reflect.Bool
case reflect.Struct:
return n == reflect.Struct || n == reflect.Map
case reflect.Bool, reflect.Slice:
case reflect.Bool, reflect.Slice, reflect.Int, reflect.Float64:
return n == g
default:
panic(fmt.Sprintf("isCompatible(): unhandled kind %s", g))

View File

@@ -44,7 +44,7 @@ func Validate(userdataBytes []byte) (Report, error) {
return validateCloudConfig(userdataBytes, Rules)
default:
return Report{entries: []Entry{
Entry{kind: entryError, message: `must be "#cloud-config" or begin with "#!"`},
Entry{kind: entryError, message: `must be "#cloud-config" or begin with "#!"`, line: 1},
}}, nil
}
}
@@ -103,7 +103,8 @@ func parseCloudConfig(config []byte, report *Report) (n node, err error) {
// and makes a note of each replacement in the report.
func normalizeNodeNames(node node, report *Report) node {
if strings.Contains(node.name, "-") {
report.Info(node.line, fmt.Sprintf("%q uses '-' instead of '_'", node.name))
// TODO(crawford): Enable this message once the new validator hits stable.
//report.Info(node.line, fmt.Sprintf("%q uses '-' instead of '_'", node.name))
node.name = strings.Replace(node.name, "-", "_", -1)
}
for i := range node.children {

View File

@@ -40,7 +40,7 @@ import (
)
const (
version = "0.11.0"
version = "0.11.4"
datasourceInterval = 100 * time.Millisecond
datasourceMaxInterval = 30 * time.Second
datasourceTimeout = 5 * time.Minute

View File

@@ -131,6 +131,7 @@ func Apply(cfg config.CloudConfig, env *Environment) error {
for _, ccu := range []CloudConfigUnit{
system.Etcd{Etcd: cfg.Coreos.Etcd},
system.Fleet{Fleet: cfg.Coreos.Fleet},
system.Flannel{Flannel: cfg.Coreos.Flannel},
system.Update{Update: cfg.Coreos.Update, ReadConfig: system.DefaultReadConfig},
} {
units = append(units, ccu.Units()...)

View File

@@ -19,6 +19,8 @@ package system
import (
"fmt"
"reflect"
"github.com/coreos/coreos-cloudinit/config"
)
// dropinContents generates the contents for a drop-in unit given the config.
@@ -29,9 +31,9 @@ func dropinContents(e interface{}) string {
var out string
for i := 0; i < et.NumField(); i++ {
if val := ev.Field(i).String(); val != "" {
if val := ev.Field(i).Interface(); !config.IsZero(val) {
key := et.Field(i).Tag.Get("env")
out += fmt.Sprintf("Environment=\"%s=%s\"\n", key, val)
out += fmt.Sprintf("Environment=\"%s=%v\"\n", key, val)
}
}
@@ -40,3 +42,16 @@ func dropinContents(e interface{}) string {
}
return "[Service]\n" + out
}
func dropinFromConfig(cfg interface{}, name string) []Unit {
content := dropinContents(cfg)
if content == "" {
return nil
}
return []Unit{{config.Unit{
Name: name,
Runtime: true,
DropIn: true,
Content: content,
}}}
}

55
system/env_test.go Normal file
View File

@@ -0,0 +1,55 @@
package system
import (
"testing"
)
func TestDropinContents(t *testing.T) {
tests := []struct {
Config interface{}
Contents string
}{
{
struct{}{},
"",
},
{
struct {
A string `env:"A"`
B int `env:"B"`
C bool `env:"C"`
D float64 `env:"D"`
}{
"hi", 1, true, 0.12345,
},
`[Service]
Environment="A=hi"
Environment="B=1"
Environment="C=true"
Environment="D=0.12345"
`,
},
{
struct {
A float64 `env:"A"`
B float64 `env:"B"`
C float64 `env:"C"`
D float64 `env:"D"`
}{
0.000001, 1, 0.9999999, 0.1,
},
`[Service]
Environment="A=1e-06"
Environment="B=1"
Environment="C=0.9999999"
Environment="D=0.1"
`,
},
}
for _, tt := range tests {
if c := dropinContents(tt.Config); c != tt.Contents {
t.Errorf("bad contents (%+v): want %q, got %q", tt, tt.Contents, c)
}
}
}

View File

@@ -28,14 +28,5 @@ type Etcd struct {
// Units creates a Unit file drop-in for etcd, using any configured options.
func (ee Etcd) Units() []Unit {
content := dropinContents(ee.Etcd)
if content == "" {
return nil
}
return []Unit{{config.Unit{
Name: "etcd.service",
Runtime: true,
DropIn: true,
Content: content,
}}}
return dropinFromConfig(ee.Etcd, "etcd.service")
}

View File

@@ -67,7 +67,7 @@ Environment="ETCD_PEER_BIND_ADDR=127.0.0.1:7002"
} {
units := Etcd{tt.config}.Units()
if !reflect.DeepEqual(tt.units, units) {
t.Errorf("bad units (%q): want %#v, got %#v", tt.config, tt.units, units)
t.Errorf("bad units (%+v): want %#v, got %#v", tt.config, tt.units, units)
}
}
}

View File

@@ -17,7 +17,6 @@
package system
import (
"errors"
"fmt"
"io/ioutil"
"os"
@@ -39,10 +38,10 @@ func (f *File) Permissions() (os.FileMode, error) {
return os.FileMode(0644), nil
}
// Parse string representation of file mode as octal
perm, err := strconv.ParseInt(f.RawFilePermissions, 8, 32)
// Parse string representation of file mode as integer
perm, err := strconv.ParseInt(f.RawFilePermissions, 0, 32)
if err != nil {
return 0, errors.New("Unable to parse file permissions as octal integer")
return 0, fmt.Errorf("Unable to parse file permissions %q as integer", f.RawFilePermissions)
}
return os.FileMode(perm), nil
}

View File

@@ -85,6 +85,38 @@ func TestWriteFileInvalidPermission(t *testing.T) {
}
}
func TestDecimalFilePermissions(t *testing.T) {
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
if err != nil {
t.Fatalf("Unable to create tempdir: %v", err)
}
defer os.RemoveAll(dir)
fn := "foo"
fullPath := path.Join(dir, fn)
wf := File{config.File{
Path: fn,
RawFilePermissions: "484", // Decimal representation of 0744
}}
path, err := WriteFile(&wf, dir)
if err != nil {
t.Fatalf("Processing of WriteFile failed: %v", err)
} else if path != fullPath {
t.Fatalf("WriteFile returned bad path: want %s, got %s", fullPath, path)
}
fi, err := os.Stat(fullPath)
if err != nil {
t.Fatalf("Unable to stat file: %v", err)
}
if fi.Mode() != os.FileMode(0744) {
t.Errorf("File has incorrect mode: %v", fi.Mode())
}
}
func TestWriteFilePermissions(t *testing.T) {
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
if err != nil {

17
system/flannel.go Normal file
View File

@@ -0,0 +1,17 @@
package system
import (
"github.com/coreos/coreos-cloudinit/config"
)
// flannel is a top-level structure which embeds its underlying configuration,
// config.Flannel, and provides the system-specific Unit().
type Flannel struct {
config.Flannel
}
// Units generates a Unit file drop-in for flannel, if any flannel options were
// configured in cloud-config
func (fl Flannel) Units() []Unit {
return dropinFromConfig(fl.Flannel, "flannel.service")
}

40
system/flannel_test.go Normal file
View File

@@ -0,0 +1,40 @@
package system
import (
"reflect"
"testing"
"github.com/coreos/coreos-cloudinit/config"
)
func TestFlannelUnits(t *testing.T) {
for _, tt := range []struct {
config config.Flannel
units []Unit
}{
{
config.Flannel{},
nil,
},
{
config.Flannel{
EtcdEndpoint: "http://12.34.56.78:4001",
EtcdPrefix: "/coreos.com/network/tenant1",
},
[]Unit{{config.Unit{
Name: "flannel.service",
Content: `[Service]
Environment="FLANNELD_ETCD_ENDPOINT=http://12.34.56.78:4001"
Environment="FLANNELD_ETCD_PREFIX=/coreos.com/network/tenant1"
`,
Runtime: true,
DropIn: true,
}}},
},
} {
units := Flannel{tt.config}.Units()
if !reflect.DeepEqual(units, tt.units) {
t.Errorf("bad units (%q): want %v, got %v", tt.config, tt.units, units)
}
}
}

View File

@@ -29,14 +29,5 @@ type Fleet struct {
// Units generates a Unit file drop-in for fleet, if any fleet options were
// configured in cloud-config
func (fe Fleet) Units() []Unit {
content := dropinContents(fe.Fleet)
if content == "" {
return nil
}
return []Unit{{config.Unit{
Name: "fleet.service",
Runtime: true,
DropIn: true,
Content: content,
}}}
return dropinFromConfig(fe.Fleet, "fleet.service")
}

View File

@@ -48,7 +48,7 @@ Environment="FLEET_PUBLIC_IP=12.34.56.78"
} {
units := Fleet{tt.config}.Units()
if !reflect.DeepEqual(units, tt.units) {
t.Errorf("bad units (%q): want %#v, got %#v", tt.config, tt.units, units)
t.Errorf("bad units (%+v): want %#v, got %#v", tt.config, tt.units, units)
}
}
}

View File

@@ -126,7 +126,7 @@ func (uc Update) Units() []Unit {
Runtime: true,
}}
if uc.Update.RebootStrategy == "false" {
if uc.Update.RebootStrategy == "false" || uc.Update.RebootStrategy == "off" {
ls.Command = "stop"
ls.Mask = true
}

View File

@@ -80,6 +80,15 @@ func TestUpdateUnits(t *testing.T) {
Mask: true,
}}},
},
{
config: config.Update{RebootStrategy: "off"},
units: []Unit{{config.Unit{
Name: "locksmithd.service",
Command: "stop",
Runtime: true,
Mask: true,
}}},
},
} {
units := Update{Update: tt.config, ReadConfig: testReadConfig("")}.Units()
if !reflect.DeepEqual(tt.units, units) {
@@ -100,7 +109,7 @@ func TestUpdateFile(t *testing.T) {
},
{
config: config.Update{RebootStrategy: "wizzlewazzle"},
err: &config.ErrorValid{Value: "wizzlewazzle", Field: "RebootStrategy", Valid: []string{"best-effort", "etcd-lock", "reboot", "false"}},
err: &config.ErrorValid{Value: "wizzlewazzle", Field: "RebootStrategy", Valid: []string{"best-effort", "etcd-lock", "reboot", "off", "false"}},
},
{
config: config.Update{Group: "master", Server: "http://foo.com"},
@@ -142,6 +151,14 @@ func TestUpdateFile(t *testing.T) {
RawFilePermissions: "0644",
}},
},
{
config: config.Update{RebootStrategy: "off"},
file: &File{config.File{
Content: "REBOOT_STRATEGY=off\n",
Path: "etc/coreos/update.conf",
RawFilePermissions: "0644",
}},
},
{
config: config.Update{RebootStrategy: "etcd-lock"},
orig: "SERVER=https://example.com\nGROUP=thegroupc\nREBOOT_STRATEGY=awesome",