2015-01-24 19:32:33 -08:00
|
|
|
// 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.
|
2014-10-22 11:27:51 -07:00
|
|
|
|
|
|
|
package validate
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2015-01-12 15:43:58 -08:00
|
|
|
func TestCheckDiscoveryUrl(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
config string
|
|
|
|
|
|
|
|
entries []Entry
|
|
|
|
}{
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
config: "coreos:\n etcd:\n discovery: https://discovery.etcd.io/00000000000000000000000000000000",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n etcd:\n discovery: http://custom.domain/mytoken",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n etcd:\n discovery: disco",
|
|
|
|
entries: []Entry{{entryWarning, "discovery URL is not valid", 3}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
r := Report{}
|
|
|
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
checkDiscoveryUrl(n, &r)
|
|
|
|
|
|
|
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
|
|
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-13 16:28:47 -08:00
|
|
|
func TestCheckEncoding(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
config string
|
|
|
|
|
|
|
|
entries []Entry
|
|
|
|
}{
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - encoding: base64\n contents: aGVsbG8K",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - contents: !!binary aGVsbG8K",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - encoding: base64\n contents: !!binary aGVsbG8K",
|
|
|
|
entries: []Entry{{entryError, `contents cannot be decoded as "base64"`, 3}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - encoding: base64\n contents: !!binary YUdWc2JHOEsK",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - encoding: gzip\n contents: !!binary H4sIAOC3tVQAA8tIzcnJ5wIAIDA6NgYAAAA=",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - encoding: gzip+base64\n contents: H4sIAOC3tVQAA8tIzcnJ5wIAIDA6NgYAAAA=",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - encoding: custom\n contents: hello",
|
|
|
|
entries: []Entry{{entryError, `contents cannot be decoded as "custom"`, 3}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
r := Report{}
|
|
|
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
checkEncoding(n, &r)
|
|
|
|
|
|
|
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
|
|
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-22 11:27:51 -07:00
|
|
|
func TestCheckStructure(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
config string
|
|
|
|
|
|
|
|
entries []Entry
|
|
|
|
}{
|
|
|
|
{},
|
|
|
|
|
|
|
|
// Test for unrecognized keys
|
|
|
|
{
|
|
|
|
config: "test:",
|
|
|
|
entries: []Entry{{entryWarning, "unrecognized key \"test\"", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n etcd:\n bad:",
|
|
|
|
entries: []Entry{{entryWarning, "unrecognized key \"bad\"", 3}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n etcd:\n discovery: good",
|
|
|
|
},
|
|
|
|
|
|
|
|
// Test for error on list of nodes
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - hello\n - goodbye",
|
|
|
|
entries: []Entry{
|
|
|
|
{entryWarning, "incorrect type for \"units[0]\" (want struct)", 3},
|
|
|
|
{entryWarning, "incorrect type for \"units[1]\" (want struct)", 4},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
// Test for incorrect types
|
|
|
|
// Want boolean
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - enable: true",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - enable: 4",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - enable: bad",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - enable:\n bad:",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - enable:\n - bad",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"enable\" (want bool)", 3}},
|
|
|
|
},
|
|
|
|
// Want string
|
|
|
|
{
|
|
|
|
config: "hostname: true",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "hostname: 4",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "hostname: host",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "hostname:\n name:",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"hostname\" (want string)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "hostname:\n - name",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"hostname\" (want string)", 1}},
|
|
|
|
},
|
|
|
|
// Want struct
|
|
|
|
{
|
|
|
|
config: "coreos: true",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos: 4",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos: hello",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n etcd:\n discovery: fire in the disco",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n - hello",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"coreos\" (want struct)", 1}},
|
|
|
|
},
|
|
|
|
// Want []string
|
|
|
|
{
|
|
|
|
config: "ssh_authorized_keys: true",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "ssh_authorized_keys: 4",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "ssh_authorized_keys: key",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "ssh_authorized_keys:\n key: value",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys\" (want []string)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "ssh_authorized_keys:\n - key",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "ssh_authorized_keys:\n - key: value",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"ssh_authorized_keys[0]\" (want string)", 2}},
|
|
|
|
},
|
|
|
|
// Want []struct
|
|
|
|
{
|
|
|
|
config: "users:\n true",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n 4",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n bad",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n bad:",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users\" (want []struct)", 1}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n - name: good",
|
|
|
|
},
|
|
|
|
// Want struct within array
|
|
|
|
{
|
|
|
|
config: "users:\n - true",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n - name: hi\n - true",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users[1]\" (want struct)", 3}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n - 4",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n - bad",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "users:\n - - bad",
|
|
|
|
entries: []Entry{{entryWarning, "incorrect type for \"users[0]\" (want struct)", 2}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
r := Report{}
|
|
|
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
checkStructure(n, &r)
|
|
|
|
|
|
|
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
|
|
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCheckValidity(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
config string
|
|
|
|
|
|
|
|
entries []Entry
|
|
|
|
}{
|
|
|
|
// string
|
|
|
|
{
|
|
|
|
config: "hostname: test",
|
|
|
|
},
|
|
|
|
|
|
|
|
// int
|
|
|
|
{
|
|
|
|
config: "coreos:\n fleet:\n verbosity: 2",
|
|
|
|
},
|
|
|
|
|
|
|
|
// bool
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - enable: true",
|
|
|
|
},
|
|
|
|
|
|
|
|
// slice
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - command: start\n - name: stop",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n units:\n - command: lol",
|
2014-11-26 10:22:39 -08:00
|
|
|
entries: []Entry{{entryError, "invalid value lol", 3}},
|
2014-10-22 11:27:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
// struct
|
|
|
|
{
|
|
|
|
config: "coreos:\n update:\n reboot_strategy: off",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n update:\n reboot_strategy: always",
|
2014-11-26 10:22:39 -08:00
|
|
|
entries: []Entry{{entryError, "invalid value always", 3}},
|
2014-10-22 11:27:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
// unknown
|
|
|
|
{
|
|
|
|
config: "unknown: hi",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
r := Report{}
|
|
|
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
checkValidity(n, &r)
|
|
|
|
|
|
|
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
|
|
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-12 12:25:28 -08:00
|
|
|
|
|
|
|
func TestCheckWriteFiles(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
config string
|
|
|
|
|
|
|
|
entries []Entry
|
|
|
|
}{
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - path: /valid",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - path: /tmp/usr/valid",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - path: /usr/invalid",
|
|
|
|
entries: []Entry{{entryError, "file cannot be written to a read-only filesystem", 2}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "write-files:\n - path: /tmp/../usr/invalid",
|
|
|
|
entries: []Entry{{entryError, "file cannot be written to a read-only filesystem", 2}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
r := Report{}
|
|
|
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
checkWriteFiles(n, &r)
|
|
|
|
|
|
|
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
|
|
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-12 16:09:21 -08:00
|
|
|
|
|
|
|
func TestCheckWriteFilesUnderCoreos(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
config string
|
|
|
|
|
|
|
|
entries []Entry
|
|
|
|
}{
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
config: "write_files:\n - path: /hi",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n write_files:\n - path: /hi",
|
|
|
|
entries: []Entry{{entryInfo, "write_files doesn't belong under coreos", 2}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: "coreos:\n write-files:\n - path: /hyphen",
|
|
|
|
entries: []Entry{{entryInfo, "write_files doesn't belong under coreos", 2}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tt := range tests {
|
|
|
|
r := Report{}
|
|
|
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
checkWriteFilesUnderCoreos(n, &r)
|
|
|
|
|
|
|
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
|
|
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|