Compare commits

...

28 Commits

Author SHA1 Message Date
Alex Crawford
fac805dc11 Merge pull request #375 from crawford/build
build: extract the version number from git
2015-08-12 11:09:29 -07:00
Alex Crawford
94ea0b99ea Merge pull request #374 from crawford/timeout
pkg/http: up the timeout to 10 seconds
2015-08-12 11:08:04 -07:00
Alex Crawford
56a80d84cf build: extract the version number from git
Update the tests as well.
2015-08-12 11:05:04 -07:00
Alex Crawford
00c9174da4 pkg/http: up the timeout to 10 seconds
Additionally, fix the units on that multiplication. This isn't
acceleration.
2015-08-11 10:42:41 -07:00
Alex Crawford
ec8742c9ba Merge pull request #371 from crawford/http-client
pkg: update HttpClient to use newer Go features
2015-08-07 20:03:01 -07:00
Alex Crawford
b3b09aeb19 pkg: update HttpClient to use newer Go features 2015-08-07 19:30:47 -07:00
Alex Crawford
481d98c0b5 Merge pull request #370 from crawford/etcd2
config: update flags for etcd 2.1
2015-08-07 17:03:43 -07:00
Alex Crawford
f30727a675 config: update flags for etcd 2.1 2015-08-07 16:20:36 -07:00
Alex Crawford
e1305937e6 Merge pull request #362 from bodgit/mkisofs
Add note for creating config-drive ISO on OS X
2015-07-23 18:42:37 -07:00
Alex Crawford
20c4653ecf Merge pull request #365 from cusspvz/flannel/add-public-ip-opt
Add PublicIP option on flannel
2015-07-23 13:41:06 -07:00
José Moreira
43c6da06a5 add public_ip opt on cloud-config.md 2015-07-23 17:04:37 +01:00
José Moreira
7ab84601c3 Add PublicIP opt 2015-07-22 22:54:03 +01:00
Alex Crawford
a24b23663c Merge pull request #364 from crawford/etcd
config: specific valid values for ETCD_PROXY
2015-07-21 22:21:25 -07:00
Alex Crawford
91fe744bd2 config: specific valid values for ETCD_PROXY 2015-07-21 14:20:10 -07:00
Matt Dainty
eb8fc045ee Add note for creating config-drive ISO on OS X 2015-07-20 10:27:02 +01:00
Alex Crawford
ba83b2871f coreos-cloudinit: bump to v1.5.0+git 2015-07-14 11:55:39 -07:00
Alex Crawford
f36821f7ce coreos-cloudinit: bump to v1.5.0 2015-07-14 11:54:56 -07:00
Alex Crawford
97fe210760 Merge pull request #356 from crawford/ignition
config: recognize Ignition configs and no-op
2015-07-10 16:34:18 -07:00
Alex Crawford
c6400f7751 config: recognize Ignition configs and no-op 2015-07-10 16:32:57 -07:00
Alex Crawford
f6647634f0 Merge pull request #352 from packethost/packet-datasource
datasource: add packethost metadata
2015-07-10 12:25:37 -07:00
Sam Tresler
837d3d3622 datasource: add packethost metadata 2015-07-10 15:13:57 -04:00
Alex Crawford
1063a4b9ee Merge pull request #351 from packethost/bond-config-options
Bond options persisted to the generated netdev file.
2015-07-10 09:08:31 -07:00
Sam Tresler
081f77a102 Persisting bond options to the netdev file, and updating the test. 2015-06-23 11:21:26 -04:00
Alex Crawford
41289286ca Merge pull request #354 from packethost/go-ci-versions
Go ci versions
2015-06-22 16:04:56 -07:00
Sam Tresler
d50a4069a6 Removing goland 1.3 and 1.2 from Travis testing 2015-06-22 18:43:27 -04:00
Alex Crawford
be0c9c56e4 Merge pull request #347 from crawford/import
doc: deprecate coreos-ssh-import-*
2015-05-28 13:45:02 -07:00
Alex Crawford
6467f06656 doc: deprecate coreos-ssh-import-* 2015-05-28 13:35:51 -07:00
Alex Crawford
7a05e63fcc coreos-cloudinit: bump to v1.4.1+git 2015-05-12 17:08:27 -07:00
18 changed files with 413 additions and 128 deletions

View File

@@ -4,10 +4,6 @@ matrix:
include:
- go: 1.4
env: TOOLS_CMD=golang.org/x/tools/cmd
- go: 1.3
env: TOOLS_CMD=code.google.com/p/go.tools/cmd
- go: 1.2
env: TOOLS_CMD=code.google.com/p/go.tools/cmd
install:
- go get ${TOOLS_CMD}/cover

View File

@@ -0,0 +1,38 @@
# Deprecated Cloud-Config Features
## Retrieving SSH Authorized Keys
### From a GitHub User
Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server.
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-github: elroy
```
### From an HTTP Endpoint
We can also pull public SSH keys from any HTTP endpoint which matches [GitHub's API response format](https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user).
For example, if you have an installation of GitHub Enterprise, you can provide a complete URL with an authentication token:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://github-enterprise.example.com/api/v3/users/elroy/keys?access_token=<TOKEN>
```
You can also specify any URL whose response matches the JSON format for public keys:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://example.com/public-keys
```

View File

@@ -169,6 +169,7 @@ List of flannel configuration parameters:
- **ip_masq**: Install IP masquerade rules for traffic outside of flannel subnet
- **subnet_file**: Path to flannel subnet file to write out
- **interface**: Interface (name or IP) that should be used for inter-host communication
- **public_ip**: IP accessible by other nodes for inter-host communication
[flannel-readme]: https://github.com/coreos/flannel/blob/master/README.md
@@ -334,9 +335,9 @@ All but the `passwd` and `ssh-authorized-keys` fields will be ignored if the use
- **groups**: Add user to these additional groups
- **no-user-group**: Boolean. Skip default group creation.
- **ssh-authorized-keys**: List of public SSH keys to authorize for this user
- **coreos-ssh-import-github**: Authorize SSH keys from GitHub user
- **coreos-ssh-import-github-users**: Authorize SSH keys from a list of GitHub users
- **coreos-ssh-import-url**: Authorize SSH keys imported from a url endpoint.
- **coreos-ssh-import-github** [DEPRECATED]: Authorize SSH keys from GitHub user
- **coreos-ssh-import-github-users** [DEPRECATED]: Authorize SSH keys from a list of GitHub users
- **coreos-ssh-import-url** [DEPRECATED]: Authorize SSH keys imported from a url endpoint.
- **system**: Create the user as a system user. No home directory will be created.
- **no-log-init**: Boolean. Skip initialization of lastlog and faillog databases.
- **shell**: User's login shell.
@@ -382,43 +383,6 @@ perl -e 'print crypt("password","\$6\$SALT\$") . "\n"'
Using a higher number of rounds will help create more secure passwords, but given enough time, password hashes can be reversed. On most RPM based distributions there is a tool called mkpasswd available in the `expect` package, but this does not handle "rounds" nor advanced hashing algorithms.
#### Retrieving SSH Authorized Keys
##### From a GitHub User
Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server.
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-github: elroy
```
##### From an HTTP Endpoint
We can also pull public SSH keys from any HTTP endpoint which matches [GitHub's API response format](https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user).
For example, if you have an installation of GitHub Enterprise, you can provide a complete URL with an authentication token:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://github-enterprise.example.com/api/v3/users/elroy/keys?access_token=<TOKEN>
```
You can also specify any URL whose response matches the JSON format for public keys:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://example.com/public-keys
```
### write_files
The `write_files` directive defines a set of files to create on the local filesystem.

View File

@@ -21,6 +21,12 @@ mkisofs -R -V config-2 -o configdrive.iso /tmp/new-drive
rm -r /tmp/new-drive
```
If on OS X, replace the `mkisofs` invocation with:
```sh
hdiutil makehybrid -iso -joliet -default-volume-name config-2 -o configdrive.iso /tmp/new-drive
```
## QEMU virtfs
One exception to the above, when using QEMU it is possible to skip creating an

7
build
View File

@@ -1,7 +1,10 @@
#!/bin/bash -e
NAME="coreos-cloudinit"
ORG_PATH="github.com/coreos"
REPO_PATH="${ORG_PATH}/coreos-cloudinit"
REPO_PATH="${ORG_PATH}/${NAME}"
VERSION=$(git describe --dirty --tags)
GLDFLAGS="-X main.version \"${VERSION}\""
if [ ! -h gopath/src/${REPO_PATH} ]; then
mkdir -p gopath/src/${ORG_PATH}
@@ -11,4 +14,4 @@ fi
export GOBIN=${PWD}/bin
export GOPATH=${PWD}/gopath
go build -o bin/coreos-cloudinit ${REPO_PATH}
go build -ldflags "${GLDFLAGS}" -o ${GOBIN}/${NAME} ${REPO_PATH}

View File

@@ -16,15 +16,18 @@ package config
type Etcd2 struct {
AdvertiseClientURLs string `yaml:"advertise_client_urls" env:"ETCD_ADVERTISE_CLIENT_URLS"`
CAFile string `yaml:"ca_file" env:"ETCD_CA_FILE"`
CAFile string `yaml:"ca_file" env:"ETCD_CA_FILE" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"`
CertFile string `yaml:"cert_file" env:"ETCD_CERT_FILE"`
ClientCertAuth bool `yaml:"client_cert_auth" env:"ETCD_CLIENT_CERT_AUTH"`
CorsOrigins string `yaml:"cors" env:"ETCD_CORS"`
DataDir string `yaml:"data_dir" env:"ETCD_DATA_DIR"`
Debug bool `yaml:"debug" env:"ETCD_DEBUG"`
Discovery string `yaml:"discovery" env:"ETCD_DISCOVERY"`
DiscoveryFallback string `yaml:"discovery_fallback" env:"ETCD_DISCOVERY_FALLBACK"`
DiscoverySRV string `yaml:"discovery_srv" env:"ETCD_DISCOVERY_SRV"`
DiscoveryProxy string `yaml:"discovery_proxy" env:"ETCD_DISCOVERY_PROXY"`
ElectionTimeout int `yaml:"election_timeout" env:"ETCD_ELECTION_TIMEOUT"`
ForceNewCluster bool `yaml:"force_new_cluster" env:"ETCD_FORCE_NEW_CLUSTER"`
HeartbeatInterval int `yaml:"heartbeat_interval" env:"ETCD_HEARTBEAT_INTERVAL"`
InitialAdvertisePeerURLs string `yaml:"initial_advertise_peer_urls" env:"ETCD_INITIAL_ADVERTISE_PEER_URLS"`
InitialCluster string `yaml:"initial_cluster" env:"ETCD_INITIAL_CLUSTER"`
@@ -33,12 +36,21 @@ type Etcd2 struct {
KeyFile string `yaml:"key_file" env:"ETCD_KEY_FILE"`
ListenClientURLs string `yaml:"listen_client_urls" env:"ETCD_LISTEN_CLIENT_URLS"`
ListenPeerURLs string `yaml:"listen_peer_urls" env:"ETCD_LISTEN_PEER_URLS"`
LogPackageLevels string `yaml:"log_package_levels" env:"ETCD_LOG_PACKAGE_LEVELS"`
MaxSnapshots int `yaml:"max_snapshots" env:"ETCD_MAX_SNAPSHOTS"`
MaxWALs int `yaml:"max_wals" env:"ETCD_MAX_WALS"`
Name string `yaml:"name" env:"ETCD_NAME"`
PeerCAFile string `yaml:"peer_ca_file" env:"ETCD_PEER_CA_FILE"`
PeerCAFile string `yaml:"peer_ca_file" env:"ETCD_PEER_CA_FILE" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"`
PeerCertFile string `yaml:"peer_cert_file" env:"ETCD_PEER_CERT_FILE"`
PeerKeyFile string `yaml:"peer_key_file" env:"ETCD_PEER_KEY_FILE"`
Proxy string `yaml:"proxy" env:"ETCD_PROXY"`
SnapshotCount int `yaml:"snapshot_count" env:"ETCD_SNAPSHOTCOUNT"`
PeerClientCertAuth bool `yaml:"peer_client_cert_auth" env:"ETCD_PEER_CLIENT_CERT_AUTH"`
PeerTrustedCAFile string `yaml:"peer_trusted_ca_file" env:"ETCD_PEER_TRUSTED_CA_FILE"`
Proxy string `yaml:"proxy" env:"ETCD_PROXY" valid:"^(on|off|readonly)$"`
ProxyDialTimeout int `yaml:"proxy_dial_timeout" env:"ETCD_PROXY_DIAL_TIMEOUT"`
ProxyFailureWait int `yaml:"proxy_failure_wait" env:"ETCD_PROXY_FAILURE_WAIT"`
ProxyReadTimeout int `yaml:"proxy_read_timeout" env:"ETCD_PROXY_READ_TIMEOUT"`
ProxyRefreshInterval int `yaml:"proxy_refresh_interval" env:"ETCD_PROXY_REFRESH_INTERVAL"`
ProxyWriteTimeout int `yaml:"proxy_write_timeout" env:"ETCD_PROXY_WRITE_TIMEOUT"`
SnapshotCount int `yaml:"snapshot_count" env:"ETCD_SNAPSHOT_COUNT"`
TrustedCAFile string `yaml:"trusted_ca_file" env:"ETCD_TRUSTED_CA_FILE"`
}

View File

@@ -23,4 +23,5 @@ type Flannel struct {
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"`
PublicIP string `yaml:"public_ip" env:"FLANNELD_PUBLIC_IP"`
}

26
config/ignition.go Normal file
View File

@@ -0,0 +1,26 @@
// 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 config
import (
"encoding/json"
)
func IsIgnitionConfig(userdata string) bool {
var cfg struct {
Version *int `json:"ignitionVersion" yaml:"ignition_version"`
}
return (json.Unmarshal([]byte(userdata), &cfg) == nil && cfg.Version != nil)
}

View File

@@ -40,6 +40,8 @@ func Validate(userdataBytes []byte) (Report, error) {
return Report{}, nil
case config.IsScript(string(userdataBytes)):
return Report{}, nil
case config.IsIgnitionConfig(string(userdataBytes)):
return Report{}, nil
case config.IsCloudConfig(string(userdataBytes)):
return validateCloudConfig(userdataBytes, Rules)
default:

View File

@@ -111,6 +111,16 @@ func TestValidate(t *testing.T) {
{
config: "#!/bin/bash\necho hey",
},
{
config: "{}",
report: Report{entries: []Entry{{entryError, `must be "#cloud-config" or begin with "#!"`, 1}}},
},
{
config: `{"ignitionVersion":0}`,
},
{
config: `{"ignitionVersion":1}`,
},
}
for i, tt := range tests {

View File

@@ -29,6 +29,7 @@ import (
"github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma"
"github.com/coreos/coreos-cloudinit/datasource/metadata/digitalocean"
"github.com/coreos/coreos-cloudinit/datasource/metadata/ec2"
"github.com/coreos/coreos-cloudinit/datasource/metadata/packet"
"github.com/coreos/coreos-cloudinit/datasource/proc_cmdline"
"github.com/coreos/coreos-cloudinit/datasource/url"
"github.com/coreos/coreos-cloudinit/datasource/waagent"
@@ -39,7 +40,6 @@ import (
)
const (
version = "1.4.1"
datasourceInterval = 100 * time.Millisecond
datasourceMaxInterval = 30 * time.Second
datasourceTimeout = 5 * time.Minute
@@ -57,6 +57,7 @@ var (
ec2MetadataService string
cloudSigmaMetadataService bool
digitalOceanMetadataService string
packetMetadataService string
url string
procCmdLine bool
}
@@ -66,6 +67,7 @@ var (
oem string
validate bool
}{}
version = "was not built properly"
)
func init() {
@@ -78,6 +80,7 @@ func init() {
flag.StringVar(&flags.sources.ec2MetadataService, "from-ec2-metadata", "", "Download EC2 data from the provided url")
flag.BoolVar(&flags.sources.cloudSigmaMetadataService, "from-cloudsigma-metadata", false, "Download data from CloudSigma server context")
flag.StringVar(&flags.sources.digitalOceanMetadataService, "from-digitalocean-metadata", "", "Download DigitalOcean data from the provided url")
flag.StringVar(&flags.sources.packetMetadataService, "from-packet-metadata", "", "Download Packet data from metadata service")
flag.StringVar(&flags.sources.url, "from-url", "", "Download user-data from provided url")
flag.BoolVar(&flags.sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", proc_cmdline.ProcCmdlineLocation, proc_cmdline.ProcCmdlineCloudConfigFlag))
flag.StringVar(&flags.oem, "oem", "", "Use the settings specific to the provided OEM")
@@ -109,6 +112,10 @@ var (
"cloudsigma": oemConfig{
"from-cloudsigma-metadata": "true",
},
"packet": oemConfig{
"from-packet-metadata": "https://metadata.packet.net/",
"convert-netconf": "packet",
},
}
)
@@ -131,7 +138,7 @@ func main() {
}
if flags.printVersion == true {
fmt.Printf("coreos-cloudinit version %s\n", version)
fmt.Printf("coreos-cloudinit %s\n", version)
os.Exit(0)
}
@@ -139,14 +146,15 @@ func main() {
case "":
case "debian":
case "digitalocean":
case "packet":
default:
fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian, digitalocean'\n", flags.convertNetconf)
fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian, digitalocean, packet'\n", flags.convertNetconf)
os.Exit(2)
}
dss := getDatasources()
if len(dss) == 0 {
fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-ec2-metadata, --from-cloudsigma-metadata, --from-url or --from-proc-cmdline")
fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-ec2-metadata, --from-cloudsigma-metadata, --from-packet-metadata, --from-url or --from-proc-cmdline")
os.Exit(2)
}
@@ -192,16 +200,20 @@ func main() {
var ccu *config.CloudConfig
var script *config.Script
if ud, err := initialize.ParseUserData(userdata); err != nil {
fmt.Printf("Failed to parse user-data: %v\nContinuing...\n", err)
failure = true
} else {
switch ud, err := initialize.ParseUserData(userdata); err {
case initialize.ErrIgnitionConfig:
fmt.Printf("Detected an Ignition config. Exiting...")
os.Exit(0)
case nil:
switch t := ud.(type) {
case *config.CloudConfig:
ccu = t
case *config.Script:
script = t
}
default:
fmt.Printf("Failed to parse user-data: %v\nContinuing...\n", err)
failure = true
}
fmt.Println("Merging cloud-config from meta-data and user-data")
@@ -215,6 +227,8 @@ func main() {
ifaces, err = network.ProcessDebianNetconf(metadata.NetworkConfig)
case "digitalocean":
ifaces, err = network.ProcessDigitalOceanNetconf(metadata.NetworkConfig)
case "packet":
ifaces, err = network.ProcessPacketNetconf(metadata.NetworkConfig)
default:
err = fmt.Errorf("Unsupported network config format %q", flags.convertNetconf)
}
@@ -290,6 +304,9 @@ func getDatasources() []datasource.Datasource {
if flags.sources.waagent != "" {
dss = append(dss, waagent.NewDatasource(flags.sources.waagent))
}
if flags.sources.packetMetadataService != "" {
dss = append(dss, packet.NewDatasource(flags.sources.packetMetadataService))
}
if flags.sources.procCmdLine {
dss = append(dss, proc_cmdline.NewDatasource())
}

View File

@@ -0,0 +1,106 @@
// 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 packet
import (
"encoding/json"
"net"
"strconv"
"github.com/coreos/coreos-cloudinit/datasource"
"github.com/coreos/coreos-cloudinit/datasource/metadata"
)
const (
DefaultAddress = "https://metadata.packet.net/"
apiVersion = ""
userdataUrl = "userdata"
metadataPath = "metadata"
)
type Netblock struct {
Address net.IP `json:"address"`
Cidr int `json:"cidr"`
Netmask net.IP `json:"netmask"`
Gateway net.IP `json:"gateway"`
AddressFamily int `json:"address_family"`
Public bool `json:"public"`
}
type Nic struct {
Name string `json:"name"`
Mac string `json:"mac"`
}
type NetworkData struct {
Interfaces []Nic `json:"interfaces"`
Netblocks []Netblock `json:"addresses"`
DNS []net.IP `json:"dns"`
}
// Metadata that will be pulled from the https://metadata.packet.net/metadata only. We have the opportunity to add more later.
type Metadata struct {
Hostname string `json:"hostname"`
SSHKeys []string `json:"ssh_keys"`
NetworkData NetworkData `json:"network"`
}
type metadataService struct {
metadata.MetadataService
}
func NewDatasource(root string) *metadataService {
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath)}
}
func (ms *metadataService) FetchMetadata() (metadata datasource.Metadata, err error) {
var data []byte
var m Metadata
if data, err = ms.FetchData(ms.MetadataUrl()); err != nil || len(data) == 0 {
return
}
if err = json.Unmarshal(data, &m); err != nil {
return
}
if len(m.NetworkData.Netblocks) > 0 {
for _, Netblock := range m.NetworkData.Netblocks {
if Netblock.AddressFamily == 4 {
if Netblock.Public == true {
metadata.PublicIPv4 = Netblock.Address
} else {
metadata.PrivateIPv4 = Netblock.Address
}
} else {
metadata.PublicIPv6 = Netblock.Address
}
}
}
metadata.Hostname = m.Hostname
metadata.SSHPublicKeys = map[string]string{}
for i, key := range m.SSHKeys {
metadata.SSHPublicKeys[strconv.Itoa(i)] = key
}
metadata.NetworkConfig, err = json.Marshal(m.NetworkData)
return
}
func (ms metadataService) Type() string {
return "packet-metadata-service"
}

View File

@@ -21,6 +21,10 @@ import (
"github.com/coreos/coreos-cloudinit/config"
)
var (
ErrIgnitionConfig = errors.New("not a config (found Ignition)")
)
func ParseUserData(contents string) (interface{}, error) {
if len(contents) == 0 {
return nil, nil
@@ -33,6 +37,8 @@ func ParseUserData(contents string) (interface{}, error) {
case config.IsCloudConfig(contents):
log.Printf("Parsing user-data as cloud-config")
return config.NewCloudConfig(contents)
case config.IsIgnitionConfig(contents):
return nil, ErrIgnitionConfig
default:
return nil, errors.New("Unrecognized user-data format")
}

View File

@@ -130,7 +130,17 @@ type bondInterface struct {
}
func (b *bondInterface) Netdev() string {
return fmt.Sprintf("[NetDev]\nKind=bond\nName=%s\n", b.name)
config := fmt.Sprintf("[NetDev]\nKind=bond\nName=%s\n", b.name)
if b.hwaddr != nil {
config += fmt.Sprintf("MACAddress=%s\n", b.hwaddr.String())
}
config += fmt.Sprintf("\n[Bond]\n")
for _, name := range sortedKeys(b.options) {
config += fmt.Sprintf("%s=%s\n", name, b.options[name])
}
return config
}
func (b *bondInterface) Type() string {

View File

@@ -52,7 +52,7 @@ func TestInterfaceGenerators(t *testing.T) {
},
{
name: "testname",
netdev: "[NetDev]\nKind=bond\nName=testname\n",
netdev: "[NetDev]\nKind=bond\nName=testname\n\n[Bond]\n",
network: "[Match]\nName=testname\n\n[Network]\nBond=testbond1\nVLAN=testvlan1\nVLAN=testvlan2\nDHCP=true\n",
kind: "bond",
iface: &bondInterface{logicalInterface: logicalInterface{

133
network/packet.go Normal file
View File

@@ -0,0 +1,133 @@
// 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 network
import (
"encoding/json"
"net"
"github.com/coreos/coreos-cloudinit/datasource/metadata/packet"
)
func ProcessPacketNetconf(config []byte) ([]InterfaceGenerator, error) {
var netdata packet.NetworkData
if err := json.Unmarshal(config, &netdata); err != nil {
return nil, err
}
var nameservers []net.IP
if netdata.DNS != nil {
nameservers = netdata.DNS
} else {
nameservers = append(nameservers, net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4"))
}
generators, err := parseNetwork(netdata, nameservers)
if err != nil {
return nil, err
}
return generators, nil
}
func parseNetwork(netdata packet.NetworkData, nameservers []net.IP) ([]InterfaceGenerator, error) {
var interfaces []InterfaceGenerator
var addresses []net.IPNet
var routes []route
for _, netblock := range netdata.Netblocks {
addresses = append(addresses, net.IPNet{
IP: netblock.Address,
Mask: net.IPMask(netblock.Netmask),
})
if netblock.Public == false {
routes = append(routes, route{
destination: net.IPNet{
IP: net.IPv4(10, 0, 0, 0),
Mask: net.IPv4Mask(255, 0, 0, 0),
},
gateway: netblock.Gateway,
})
} else {
if netblock.AddressFamily == 4 {
routes = append(routes, route{
destination: net.IPNet{
IP: net.IPv4zero,
Mask: net.IPMask(net.IPv4zero),
},
gateway: netblock.Gateway,
})
} else {
routes = append(routes, route{
destination: net.IPNet{
IP: net.IPv6zero,
Mask: net.IPMask(net.IPv6zero),
},
gateway: netblock.Gateway,
})
}
}
}
bond := bondInterface{
logicalInterface: logicalInterface{
name: "bond0",
config: configMethodStatic{
addresses: addresses,
nameservers: nameservers,
routes: routes,
},
},
options: map[string]string{
"Mode": "802.3ad",
"LACPTransmitRate": "fast",
"MIIMonitorSec": ".2",
"UpDelaySec": ".2",
"DownDelaySec": ".2",
},
}
for _, iface := range netdata.Interfaces {
if iface.Name != "chassis0" && iface.Name != "ipmi0" {
bond.slaves = append(bond.slaves, iface.Name)
if iface.Name == "enp1s0f0" {
bond.hwaddr, _ = net.ParseMAC(iface.Mac)
}
}
}
for _, iface := range netdata.Interfaces {
if iface.Name != "chassis0" && iface.Name != "ipmi0" {
p := physicalInterface{
logicalInterface: logicalInterface{
name: iface.Name,
config: configMethodStatic{
nameservers: nameservers,
},
children: []networkInterface{&bond},
},
}
if iface.Name == "enp1s0f0" {
p.configDepth = 20
}
interfaces = append(interfaces, &p)
}
}
interfaces = append(interfaces, &bond)
return interfaces, nil
}

View File

@@ -15,12 +15,10 @@
package pkg
import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
neturl "net/url"
"strings"
@@ -55,16 +53,15 @@ type ErrNetwork struct {
}
type HttpClient struct {
// Initial backoff duration. Defaults to 50 milliseconds
InitialBackoff time.Duration
// Maximum exp backoff duration. Defaults to 5 seconds
MaxBackoff time.Duration
// Maximum number of connection retries. Defaults to 15
MaxRetries int
// HTTP client timeout, this is suggested to be low since exponential
// backoff will kick off too. Defaults to 2 seconds
Timeout time.Duration
// Whether or not to skip TLS verification. Defaults to false
SkipTLS bool
@@ -78,29 +75,12 @@ type Getter interface {
func NewHttpClient() *HttpClient {
hc := &HttpClient{
MaxBackoff: time.Second * 5,
MaxRetries: 15,
Timeout: time.Duration(2) * time.Second,
SkipTLS: false,
}
// We need to create our own client in order to add timeout support.
// TODO(c4milo) Replace it once Go 1.3 is officially used by CoreOS
// More info: https://code.google.com/p/go/source/detail?r=ada6f2d5f99f
hc.client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: hc.SkipTLS,
},
Dial: func(network, addr string) (net.Conn, error) {
deadline := time.Now().Add(hc.Timeout)
c, err := net.DialTimeout(network, addr, hc.Timeout)
if err != nil {
return nil, err
}
c.SetDeadline(deadline)
return c, nil
},
InitialBackoff: 50 * time.Millisecond,
MaxBackoff: time.Second * 5,
MaxRetries: 15,
SkipTLS: false,
client: &http.Client{
Timeout: 10 * time.Second,
},
}
@@ -134,7 +114,7 @@ func (h *HttpClient) GetRetry(rawurl string) ([]byte, error) {
dataURL := url.String()
duration := 50 * time.Millisecond
duration := h.InitialBackoff
for retry := 1; retry <= h.MaxRetries; retry++ {
log.Printf("Fetching data from %s. Attempt #%d", dataURL, retry)

51
test
View File

@@ -1,19 +1,8 @@
#!/bin/bash -e
#
# Run all coreos-cloudinit tests
# ./test
# ./test -v
#
# Run tests for one package
# PKG=initialize ./test
#
# Invoke ./cover for HTML output
COVER=${COVER:-"-cover"}
source ./build
declare -a TESTPKGS=(
SRC="
config
config/validate
datasource
@@ -31,36 +20,22 @@ declare -a TESTPKGS=(
network
pkg
system
)
"
if [ -z "$PKG" ]; then
GOFMTPATH="${TESTPKGS[*]} *.go"
# prepend repo path to each package
TESTPKGS="${TESTPKGS[*]/#/${REPO_PATH}/} ./"
else
GOFMTPATH="$TESTPKGS"
# strip out slashes and dots from PKG=./foo/
TESTPKGS=${PKG//\//}
TESTPKGS=${TESTPKGS//./}
TESTPKGS=${TESTPKGS/#/${REPO_PATH}/}
fi
echo "Running tests..."
go test -i ${TESTPKGS}
go test ${COVER} $@ ${TESTPKGS}
echo "Checking gofix..."
go tool fix -diff $SRC
echo "Checking gofmt..."
fmtRes=$(gofmt -l $GOFMTPATH)
if [ -n "$fmtRes" ]; then
echo "$fmtRes"
exit 1
fi
gofmt -d -e $SRC
# split SRC into an array and prepend REPO_PATH to each local package for go vet
split_vet=(${SRC// / })
VET_TEST=${split_vet[@]/#/${REPO_PATH}/}
echo "Checking govet..."
vetRes=$(go vet $TESTPKGS)
if [ -n "${vetRes}" ]; then
echo -e "govet checking failed:\n${vetRes}"
exit 255
fi
go vet $VET_TEST
echo "Running tests..."
go test -timeout 60s -cover $@ ${VET_TEST} --race
echo "Success"