mirror of
https://github.com/outbackdingo/matchbox.git
synced 2026-01-27 10:19:35 +00:00
vendor: Update fuze, cloudinit, and go-systemd
This commit is contained in:
11
glide.lock
generated
11
glide.lock
generated
@@ -1,5 +1,5 @@
|
||||
hash: ed75f60308590c51616b57d4b2ecac260fe8da6fe54dc6d436dccc148d0d90c5
|
||||
updated: 2016-09-06T16:41:57.122230713-07:00
|
||||
hash: 1f2a602a6a995b4f8eb93ad0fa3ef5734b57078366e5969237d117d02146db88
|
||||
updated: 2016-09-07T11:42:59.832174164-07:00
|
||||
imports:
|
||||
- name: github.com/alecthomas/units
|
||||
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
|
||||
@@ -8,12 +8,11 @@ imports:
|
||||
subpackages:
|
||||
- pkg/errorutil
|
||||
- name: github.com/coreos/coreos-cloudinit
|
||||
version: b3f805dee6a4aa5ed298a1f370284df470eecf43
|
||||
version: 4c333e657bfbaa8f6594298b48324f45e6bf5961
|
||||
subpackages:
|
||||
- Godeps/_workspace/src/github.com/coreos/yaml
|
||||
- config
|
||||
- name: github.com/coreos/fuze
|
||||
version: 60c987a0aba4976ac6cbc9350671c2fedc431e8b
|
||||
version: 7df4f06041d9daba45e4c68221b9b04203dff1d8
|
||||
subpackages:
|
||||
- config
|
||||
- name: github.com/coreos/go-semver
|
||||
@@ -21,7 +20,7 @@ imports:
|
||||
subpackages:
|
||||
- semver
|
||||
- name: github.com/coreos/go-systemd
|
||||
version: 7b2428fec40033549c68f54e26e89e7ca9a9ce31
|
||||
version: 43e4800a6165b4e02bb2a36673c54b230d6f7b26
|
||||
subpackages:
|
||||
- journal
|
||||
- name: github.com/coreos/ignition
|
||||
|
||||
85
glide.yaml
85
glide.yaml
@@ -1,28 +1,23 @@
|
||||
package: github.com/coreos/coreos-baremetal
|
||||
import:
|
||||
- package: github.com/alecthomas/units
|
||||
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
|
||||
- package: github.com/camlistore/camlistore
|
||||
version: 9106ce829629773474c689b34aacd7d3aaa99426
|
||||
- package: github.com/coreos/coreos-cloudinit
|
||||
version: b3f805dee6a4aa5ed298a1f370284df470eecf43
|
||||
- package: github.com/golang/protobuf
|
||||
version: 7cc19b78d562895b13596ddce7aafb59dd789318
|
||||
subpackages:
|
||||
- Godeps/_workspace/src/github.com/coreos/yaml
|
||||
- config
|
||||
- package: github.com/coreos/go-semver
|
||||
version: 294930c1e79c64e7dbe360054274fdad492c8cf5
|
||||
- proto
|
||||
- package: google.golang.org/grpc
|
||||
version: 83e628beaa8cab332f304ad93dff7abc46722386
|
||||
subpackages:
|
||||
- semver
|
||||
- package: github.com/coreos/go-systemd
|
||||
version: 7b2428fec40033549c68f54e26e89e7ca9a9ce31
|
||||
subpackages:
|
||||
- journal
|
||||
- codes
|
||||
- package: github.com/coreos/ignition
|
||||
version: b6850837b3b9bd17b673e58b5c406b5e4192ddca
|
||||
subpackages:
|
||||
- config
|
||||
- package: github.com/coreos/fuze
|
||||
version: 60c987a0aba4976ac6cbc9350671c2fedc431e8b
|
||||
version: 7df4f06041d9daba45e4c68221b9b04203dff1d8
|
||||
subpackages:
|
||||
- config
|
||||
- package: github.com/coreos/coreos-cloudinit
|
||||
version: v1.11.0
|
||||
subpackages:
|
||||
- config
|
||||
- package: github.com/coreos/pkg
|
||||
@@ -33,32 +28,8 @@ import:
|
||||
version: v0.10.0
|
||||
subpackages:
|
||||
- hooks/test
|
||||
- package: github.com/davecgh/go-spew
|
||||
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||
subpackages:
|
||||
- spew
|
||||
- package: github.com/golang/protobuf
|
||||
version: 7cc19b78d562895b13596ddce7aafb59dd789318
|
||||
subpackages:
|
||||
- proto
|
||||
- package: github.com/pmezard/go-difflib
|
||||
version: 792786c7400a136282c1664665ae0a8db921c6c2
|
||||
subpackages:
|
||||
- difflib
|
||||
- package: github.com/spf13/cobra
|
||||
version: 65a708cee0a4424f4e353d031ce440643e312f92
|
||||
- package: github.com/spf13/pflag
|
||||
version: 7f60f83a2c81bc3c3c0d5297f61ddfa68da9d3b7
|
||||
- package: github.com/stretchr/testify
|
||||
version: 1f4a1643a57e798696635ea4c126e9127adb7d3c
|
||||
subpackages:
|
||||
- assert
|
||||
- package: github.com/vincent-petithory/dataurl
|
||||
version: 9a301d65acbb728fcc3ace14f45f511a4cfeea9c
|
||||
- package: go4.org
|
||||
version: 03efcb870d84809319ea509714dd6d19a1498483
|
||||
subpackages:
|
||||
- errorutil
|
||||
- package: golang.org/x/crypto
|
||||
version: 5dc8cb4b8a8eb076cbb5a06bc3b8682c15bdbbd3
|
||||
subpackages:
|
||||
@@ -71,11 +42,39 @@ import:
|
||||
- http2
|
||||
- internal/timeseries
|
||||
- trace
|
||||
- package: google.golang.org/grpc
|
||||
version: 83e628beaa8cab332f304ad93dff7abc46722386
|
||||
- package: github.com/stretchr/testify
|
||||
version: 1f4a1643a57e798696635ea4c126e9127adb7d3c
|
||||
subpackages:
|
||||
- codes
|
||||
- assert
|
||||
- package: gopkg.in/yaml.v2
|
||||
version: f7716cbe52baa25d2e9b0d0da546fcf909fc16b4
|
||||
- package: github.com/coreos/yaml
|
||||
version: 6b16a5714269b2f70720a45406b1babd947a17ef
|
||||
- package: github.com/alecthomas/units
|
||||
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
|
||||
- package: github.com/camlistore/camlistore
|
||||
version: 9106ce829629773474c689b34aacd7d3aaa99426
|
||||
- package: github.com/coreos/go-semver
|
||||
version: 294930c1e79c64e7dbe360054274fdad492c8cf5
|
||||
subpackages:
|
||||
- semver
|
||||
- package: github.com/coreos/go-systemd
|
||||
version: v12
|
||||
subpackages:
|
||||
- journal
|
||||
- package: github.com/davecgh/go-spew
|
||||
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||
subpackages:
|
||||
- spew
|
||||
- package: github.com/pmezard/go-difflib
|
||||
version: 792786c7400a136282c1664665ae0a8db921c6c2
|
||||
subpackages:
|
||||
- difflib
|
||||
- package: github.com/spf13/pflag
|
||||
version: 7f60f83a2c81bc3c3c0d5297f61ddfa68da9d3b7
|
||||
- package: github.com/vincent-petithory/dataurl
|
||||
version: 9a301d65acbb728fcc3ace14f45f511a4cfeea9c
|
||||
- package: go4.org
|
||||
version: 03efcb870d84809319ea509714dd6d19a1498483
|
||||
subpackages:
|
||||
- errorutil
|
||||
|
||||
7
vendor/github.com/coreos/coreos-cloudinit/.travis.yml
generated
vendored
7
vendor/github.com/coreos/coreos-cloudinit/.travis.yml
generated
vendored
@@ -1,12 +1,9 @@
|
||||
language: go
|
||||
sudo: false
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.4
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go: 1.5
|
||||
env: GO15VENDOREXPERIMENT=1
|
||||
- go: 1.6
|
||||
|
||||
script:
|
||||
- ./test
|
||||
|
||||
3
vendor/github.com/coreos/coreos-cloudinit/Documentation/cloud-config.md
generated
vendored
3
vendor/github.com/coreos/coreos-cloudinit/Documentation/cloud-config.md
generated
vendored
@@ -223,6 +223,9 @@ List of locksmith configuration parameters:
|
||||
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
|
||||
- **etcd_certfile**: Path to certificate file used for TLS communication with etcd
|
||||
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
|
||||
- **group**: Name of the reboot group in which this instance belongs
|
||||
- **window_start**: Start time of the reboot window
|
||||
- **window_length**: Duration of the reboot window
|
||||
|
||||
For the complete list of locksmith configuration parameters, see the [locksmith documentation][locksmith-readme].
|
||||
|
||||
|
||||
46
vendor/github.com/coreos/coreos-cloudinit/Godeps/Godeps.json
generated
vendored
46
vendor/github.com/coreos/coreos-cloudinit/Godeps/Godeps.json
generated
vendored
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"ImportPath": "github.com/coreos/coreos-cloudinit",
|
||||
"GoVersion": "go1.3.3",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/cloudsigma/cepgo",
|
||||
"Rev": "1bfc4895bf5c4d3b599f3f6ee142299488c8739b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-systemd/dbus",
|
||||
"Rev": "4fbc5060a317b142e6c7bfbedb65596d5f0ab99b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/yaml",
|
||||
"Rev": "6b16a5714269b2f70720a45406b1babd947a17ef"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/dotcloud/docker/pkg/netlink",
|
||||
"Comment": "v0.11.1-359-g55d41c3e21e1",
|
||||
"Rev": "55d41c3e21e1593b944c06196ffb2ac57ab7f653"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/guelfey/go.dbus",
|
||||
"Rev": "f6a3a2366cc39b8479cadc499d3c735fb10fbdda"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/tarm/goserial",
|
||||
"Rev": "cdabc8d44e8e84f58f18074ae44337e1f2f375b9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/sigma/vmw-guestinfo",
|
||||
"Rev": "95dd4126d6e8b4ef1970b3f3fe2e8cdd470d2903"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/sigma/vmw-ovflib",
|
||||
"Rev": "56b4f44581cac03d17d8270158bdfd0942ffe790"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/sigma/bdoor",
|
||||
"Rev": "babf2a4017b020d4ce04e8167076186e82645dd1"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
vendor/github.com/coreos/coreos-cloudinit/Godeps/Readme
generated
vendored
5
vendor/github.com/coreos/coreos-cloudinit/Godeps/Readme
generated
vendored
@@ -1,5 +0,0 @@
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
16
vendor/github.com/coreos/coreos-cloudinit/config/config.go
generated
vendored
16
vendor/github.com/coreos/coreos-cloudinit/config/config.go
generated
vendored
@@ -68,6 +68,22 @@ func NewCloudConfig(contents string) (*CloudConfig, error) {
|
||||
return &cfg, err
|
||||
}
|
||||
|
||||
// Decode decodes the content of cloud config. Currently only WriteFiles section
|
||||
// supports several types of encoding and all of them are supported. After
|
||||
// decode operation, Encoding type is unset.
|
||||
func (cc *CloudConfig) Decode() error {
|
||||
for i, file := range cc.WriteFiles {
|
||||
content, err := DecodeContent(file.Content, file.Encoding)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cc.WriteFiles[i].Content = string(content)
|
||||
cc.WriteFiles[i].Encoding = ""
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (cc CloudConfig) String() string {
|
||||
bytes, err := yaml.Marshal(cc)
|
||||
if err != nil {
|
||||
|
||||
57
vendor/github.com/coreos/coreos-cloudinit/config/config_test.go
generated
vendored
57
vendor/github.com/coreos/coreos-cloudinit/config/config_test.go
generated
vendored
@@ -15,6 +15,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -30,11 +31,11 @@ func TestNewCloudConfig(t *testing.T) {
|
||||
{},
|
||||
{
|
||||
contents: "#cloud-config\nwrite_files:\n - path: underscore",
|
||||
config: CloudConfig{WriteFiles: []File{File{Path: "underscore"}}},
|
||||
config: CloudConfig{WriteFiles: []File{{Path: "underscore"}}},
|
||||
},
|
||||
{
|
||||
contents: "#cloud-config\nwrite-files:\n - path: hyphen",
|
||||
config: CloudConfig{WriteFiles: []File{File{Path: "hyphen"}}},
|
||||
config: CloudConfig{WriteFiles: []File{{Path: "hyphen"}}},
|
||||
},
|
||||
{
|
||||
contents: "#cloud-config\ncoreos:\n update:\n reboot-strategy: off",
|
||||
@@ -46,19 +47,19 @@ func TestNewCloudConfig(t *testing.T) {
|
||||
},
|
||||
{
|
||||
contents: "#cloud-config\nwrite_files:\n - permissions: 0744",
|
||||
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "0744"}}},
|
||||
config: CloudConfig{WriteFiles: []File{{RawFilePermissions: "0744"}}},
|
||||
},
|
||||
{
|
||||
contents: "#cloud-config\nwrite_files:\n - permissions: 744",
|
||||
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "744"}}},
|
||||
config: CloudConfig{WriteFiles: []File{{RawFilePermissions: "744"}}},
|
||||
},
|
||||
{
|
||||
contents: "#cloud-config\nwrite_files:\n - permissions: '0744'",
|
||||
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "0744"}}},
|
||||
config: CloudConfig{WriteFiles: []File{{RawFilePermissions: "0744"}}},
|
||||
},
|
||||
{
|
||||
contents: "#cloud-config\nwrite_files:\n - permissions: '744'",
|
||||
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "744"}}},
|
||||
config: CloudConfig{WriteFiles: []File{{RawFilePermissions: "744"}}},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -73,6 +74,50 @@ func TestNewCloudConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewCloudConfigDecode(t *testing.T) {
|
||||
// //all of these decode to "bar"
|
||||
contentTests := map[string]string{
|
||||
"base64": "YmFy",
|
||||
"b64": "YmFy",
|
||||
// theoretically gz+gzip are supported but they break yaml
|
||||
// "gz": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
|
||||
// "gzip": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
|
||||
"gz+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
"gzip+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
"gz+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
"gzip+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
contents string
|
||||
config CloudConfig
|
||||
}
|
||||
|
||||
var decodingTests []testCase
|
||||
for name, content := range contentTests {
|
||||
decodingTests = append(decodingTests, testCase{
|
||||
contents: fmt.Sprintf("#cloud-config\nwrite_files:\n - encoding: %q\n content: |\n %s", name, content),
|
||||
config: CloudConfig{WriteFiles: []File{{Content: "bar"}}},
|
||||
})
|
||||
}
|
||||
|
||||
for i, tt := range decodingTests {
|
||||
config, err := NewCloudConfig(tt.contents)
|
||||
if err != nil {
|
||||
t.Errorf("bad error (test case #%d): want %v, got %s", i, nil, err)
|
||||
}
|
||||
|
||||
if err := config.Decode(); err != nil {
|
||||
t.Errorf("bad error (test case #%d): want %v, got %s", i, nil, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(&tt.config, config) {
|
||||
t.Errorf("bad config (test case #%d): want %#v, got %#v", i, tt.config, config)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIsZero(t *testing.T) {
|
||||
tests := []struct {
|
||||
c interface{}
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/config/etcd2.go
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/config/etcd2.go
generated
vendored
@@ -27,6 +27,7 @@ type Etcd2 struct {
|
||||
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"`
|
||||
EnablePprof bool `yaml:"enable_pprof" env:"ETCD_ENABLE_PPROF"`
|
||||
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"`
|
||||
@@ -52,6 +53,7 @@ type Etcd2 struct {
|
||||
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"`
|
||||
StrictReconfigCheck bool `yaml:"strict_reconfig_check" env:"ETCD_STRICT_RECONFIG_CHECK"`
|
||||
TrustedCAFile string `yaml:"trusted_ca_file" env:"ETCD_TRUSTED_CA_FILE"`
|
||||
WalDir string `yaml:"wal_dir" env:"ETCD_WAL_DIR"`
|
||||
}
|
||||
|
||||
7
vendor/github.com/coreos/coreos-cloudinit/config/ignition.go
generated
vendored
7
vendor/github.com/coreos/coreos-cloudinit/config/ignition.go
generated
vendored
@@ -20,7 +20,10 @@ import (
|
||||
|
||||
func IsIgnitionConfig(userdata string) bool {
|
||||
var cfg struct {
|
||||
Version *int `json:"ignitionVersion" yaml:"ignition_version"`
|
||||
Version *int `json:"ignitionVersion"`
|
||||
Ignition struct {
|
||||
Version *string `json:"version"`
|
||||
} `json:"ignition"`
|
||||
}
|
||||
return (json.Unmarshal([]byte(userdata), &cfg) == nil && cfg.Version != nil)
|
||||
return (json.Unmarshal([]byte(userdata), &cfg) == nil && (cfg.Version != nil || cfg.Ignition.Version != nil))
|
||||
}
|
||||
|
||||
28
vendor/github.com/coreos/coreos-cloudinit/config/validate/node_test.go
generated
vendored
28
vendor/github.com/coreos/coreos-cloudinit/config/validate/node_test.go
generated
vendored
@@ -33,18 +33,18 @@ func TestChild(t *testing.T) {
|
||||
{
|
||||
parent: node{
|
||||
children: []node{
|
||||
node{name: "c1"},
|
||||
node{name: "c2"},
|
||||
node{name: "c3"},
|
||||
{name: "c1"},
|
||||
{name: "c2"},
|
||||
{name: "c3"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
parent: node{
|
||||
children: []node{
|
||||
node{name: "c1"},
|
||||
node{name: "c2"},
|
||||
node{name: "c3"},
|
||||
{name: "c1"},
|
||||
{name: "c2"},
|
||||
{name: "c3"},
|
||||
},
|
||||
},
|
||||
name: "c2",
|
||||
@@ -76,8 +76,8 @@ func TestHumanType(t *testing.T) {
|
||||
node: node{
|
||||
Value: reflect.ValueOf([]int{1, 2}),
|
||||
children: []node{
|
||||
node{Value: reflect.ValueOf(1)},
|
||||
node{Value: reflect.ValueOf(2)},
|
||||
{Value: reflect.ValueOf(1)},
|
||||
{Value: reflect.ValueOf(2)},
|
||||
}},
|
||||
humanType: "[]int",
|
||||
},
|
||||
@@ -108,7 +108,7 @@ func TestToNode(t *testing.T) {
|
||||
}{},
|
||||
node: node{
|
||||
children: []node{
|
||||
node{
|
||||
{
|
||||
name: "a",
|
||||
field: reflect.TypeOf(struct {
|
||||
A int `yaml:"a"`
|
||||
@@ -123,7 +123,7 @@ func TestToNode(t *testing.T) {
|
||||
}{},
|
||||
node: node{
|
||||
children: []node{
|
||||
node{
|
||||
{
|
||||
name: "a",
|
||||
field: reflect.TypeOf(struct {
|
||||
A []int `yaml:"a"`
|
||||
@@ -141,11 +141,11 @@ func TestToNode(t *testing.T) {
|
||||
context: NewContext([]byte("a:\n b: 2")),
|
||||
node: node{
|
||||
children: []node{
|
||||
node{
|
||||
{
|
||||
line: 1,
|
||||
name: "a",
|
||||
children: []node{
|
||||
node{name: "b", line: 2},
|
||||
{name: "b", line: 2},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -159,10 +159,10 @@ func TestToNode(t *testing.T) {
|
||||
}{},
|
||||
node: node{
|
||||
children: []node{
|
||||
node{
|
||||
{
|
||||
name: "a",
|
||||
children: []node{
|
||||
node{
|
||||
{
|
||||
name: "b",
|
||||
field: reflect.TypeOf(struct {
|
||||
Jon bool `yaml:"b"`
|
||||
|
||||
6
vendor/github.com/coreos/coreos-cloudinit/config/validate/report_test.go
generated
vendored
6
vendor/github.com/coreos/coreos-cloudinit/config/validate/report_test.go
generated
vendored
@@ -77,9 +77,9 @@ func TestReport(t *testing.T) {
|
||||
{(*Report).Info, 10, "test info 10"},
|
||||
},
|
||||
[]Entry{
|
||||
Entry{entryWarning, "test warning 1", 1},
|
||||
Entry{entryError, "test error 2", 2},
|
||||
Entry{entryInfo, "test info 10", 10},
|
||||
{entryWarning, "test warning 1", 1},
|
||||
{entryError, "test error 2", 2},
|
||||
{entryInfo, "test info 10", 10},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/config/validate/validate.go
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/config/validate/validate.go
generated
vendored
@@ -46,7 +46,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 "#!"`, line: 1},
|
||||
{kind: entryError, message: `must be "#cloud-config" or begin with "#!"`, line: 1},
|
||||
}}, nil
|
||||
}
|
||||
}
|
||||
|
||||
25
vendor/github.com/coreos/coreos-cloudinit/coreos-cloudinit.go
generated
vendored
25
vendor/github.com/coreos/coreos-cloudinit/coreos-cloudinit.go
generated
vendored
@@ -34,6 +34,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/gce"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata/packet"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/proc_cmdline"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/url"
|
||||
@@ -61,6 +62,7 @@ var (
|
||||
waagent string
|
||||
metadataService bool
|
||||
ec2MetadataService string
|
||||
gceMetadataService string
|
||||
cloudSigmaMetadataService bool
|
||||
digitalOceanMetadataService string
|
||||
packetMetadataService string
|
||||
@@ -86,6 +88,7 @@ func init() {
|
||||
flag.StringVar(&flags.sources.waagent, "from-waagent", "", "Read data from provided waagent directory")
|
||||
flag.BoolVar(&flags.sources.metadataService, "from-metadata-service", false, "[DEPRECATED - Use -from-ec2-metadata] Download data from metadata service")
|
||||
flag.StringVar(&flags.sources.ec2MetadataService, "from-ec2-metadata", "", "Download EC2 data from the provided url")
|
||||
flag.StringVar(&flags.sources.gceMetadataService, "from-gce-metadata", "", "Download GCE 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")
|
||||
@@ -104,28 +107,31 @@ type oemConfig map[string]string
|
||||
|
||||
var (
|
||||
oemConfigs = map[string]oemConfig{
|
||||
"digitalocean": oemConfig{
|
||||
"digitalocean": {
|
||||
"from-digitalocean-metadata": "http://169.254.169.254/",
|
||||
"convert-netconf": "digitalocean",
|
||||
},
|
||||
"ec2-compat": oemConfig{
|
||||
"ec2-compat": {
|
||||
"from-ec2-metadata": "http://169.254.169.254/",
|
||||
"from-configdrive": "/media/configdrive",
|
||||
},
|
||||
"rackspace-onmetal": oemConfig{
|
||||
"gce": {
|
||||
"from-gce-metadata": "http://metadata.google.internal/",
|
||||
},
|
||||
"rackspace-onmetal": {
|
||||
"from-configdrive": "/media/configdrive",
|
||||
"convert-netconf": "debian",
|
||||
},
|
||||
"azure": oemConfig{
|
||||
"azure": {
|
||||
"from-waagent": "/var/lib/waagent",
|
||||
},
|
||||
"cloudsigma": oemConfig{
|
||||
"cloudsigma": {
|
||||
"from-cloudsigma-metadata": "true",
|
||||
},
|
||||
"packet": oemConfig{
|
||||
"packet": {
|
||||
"from-packet-metadata": "https://metadata.packet.net/",
|
||||
},
|
||||
"vmware": oemConfig{
|
||||
"vmware": {
|
||||
"from-vmware-guestinfo": "true",
|
||||
"convert-netconf": "vmware",
|
||||
},
|
||||
@@ -174,7 +180,7 @@ func main() {
|
||||
|
||||
dss := getDatasources()
|
||||
if len(dss) == 0 {
|
||||
fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-ec2-metadata, --from-cloudsigma-metadata, --from-packet-metadata, --from-digitalocean-metadata, --from-vmware-guestinfo, --from-waagent, --from-url or --from-proc-cmdline")
|
||||
fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-ec2-metadata, --from-gce-metadata, --from-cloudsigma-metadata, --from-packet-metadata, --from-digitalocean-metadata, --from-vmware-guestinfo, --from-waagent, --from-url or --from-proc-cmdline")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
@@ -322,6 +328,9 @@ func getDatasources() []datasource.Datasource {
|
||||
if flags.sources.ec2MetadataService != "" {
|
||||
dss = append(dss, ec2.NewDatasource(flags.sources.ec2MetadataService))
|
||||
}
|
||||
if flags.sources.gceMetadataService != "" {
|
||||
dss = append(dss, gce.NewDatasource(flags.sources.gceMetadataService))
|
||||
}
|
||||
if flags.sources.cloudSigmaMetadataService {
|
||||
dss = append(dss, cloudsigma.NewServerContextService())
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ type metadataService struct {
|
||||
}
|
||||
|
||||
func NewDatasource(root string) *metadataService {
|
||||
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath)}
|
||||
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath, nil)}
|
||||
}
|
||||
|
||||
func (ms *metadataService) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestFetchMetadata(t *testing.T) {
|
||||
NetworkConfig: Metadata{
|
||||
Interfaces: Interfaces{
|
||||
Public: []Interface{
|
||||
Interface{
|
||||
{
|
||||
IPv4: &Address{
|
||||
IPAddress: "192.168.1.2",
|
||||
Netmask: "255.255.255.0",
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/ec2/metadata.go
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/ec2/metadata.go
generated
vendored
@@ -39,7 +39,7 @@ type metadataService struct {
|
||||
}
|
||||
|
||||
func NewDatasource(root string) *metadataService {
|
||||
return &metadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath)}
|
||||
return &metadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath, nil)}
|
||||
}
|
||||
|
||||
func (ms metadataService) FetchMetadata() (datasource.Metadata, error) {
|
||||
|
||||
89
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/gce/metadata.go
generated
vendored
Normal file
89
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/gce/metadata.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2016 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 gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
apiVersion = "computeMetadata/v1/"
|
||||
metadataPath = apiVersion + "instance/"
|
||||
userdataPath = apiVersion + "instance/attributes/user-data"
|
||||
)
|
||||
|
||||
type metadataService struct {
|
||||
metadata.MetadataService
|
||||
}
|
||||
|
||||
func NewDatasource(root string) *metadataService {
|
||||
return &metadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath, http.Header{"Metadata-Flavor": {"Google"}})}
|
||||
}
|
||||
|
||||
func (ms metadataService) FetchMetadata() (datasource.Metadata, error) {
|
||||
public, err := ms.fetchIP("network-interfaces/0/access-configs/0/external-ip")
|
||||
if err != nil {
|
||||
return datasource.Metadata{}, err
|
||||
}
|
||||
local, err := ms.fetchIP("network-interfaces/0/ip")
|
||||
if err != nil {
|
||||
return datasource.Metadata{}, err
|
||||
}
|
||||
hostname, err := ms.fetchString("hostname")
|
||||
if err != nil {
|
||||
return datasource.Metadata{}, err
|
||||
}
|
||||
|
||||
return datasource.Metadata{
|
||||
PublicIPv4: public,
|
||||
PrivateIPv4: local,
|
||||
Hostname: hostname,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ms metadataService) Type() string {
|
||||
return "gce-metadata-service"
|
||||
}
|
||||
|
||||
func (ms metadataService) fetchString(key string) (string, error) {
|
||||
data, err := ms.FetchData(ms.MetadataUrl() + key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func (ms metadataService) fetchIP(key string) (net.IP, error) {
|
||||
str, err := ms.fetchString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if str == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if ip := net.ParseIP(str); ip != nil {
|
||||
return ip, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("couldn't parse %q as IP address", str)
|
||||
}
|
||||
}
|
||||
99
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/gce/metadata_test.go
generated
vendored
Normal file
99
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/gce/metadata_test.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// 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 gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata"
|
||||
"github.com/coreos/coreos-cloudinit/datasource/metadata/test"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
)
|
||||
|
||||
func TestType(t *testing.T) {
|
||||
want := "gce-metadata-service"
|
||||
if kind := (metadataService{}).Type(); kind != want {
|
||||
t.Fatalf("bad type: want %q, got %q", want, kind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchMetadata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
metadataPath string
|
||||
resources map[string]string
|
||||
expect datasource.Metadata
|
||||
clientErr error
|
||||
expectErr error
|
||||
}{
|
||||
{
|
||||
root: "/",
|
||||
metadataPath: "computeMetadata/v1/instance/",
|
||||
resources: map[string]string{},
|
||||
},
|
||||
{
|
||||
root: "/",
|
||||
metadataPath: "computeMetadata/v1/instance/",
|
||||
resources: map[string]string{
|
||||
"/computeMetadata/v1/instance/hostname": "host",
|
||||
},
|
||||
expect: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
},
|
||||
},
|
||||
{
|
||||
root: "/",
|
||||
metadataPath: "computeMetadata/v1/instance/",
|
||||
resources: map[string]string{
|
||||
"/computeMetadata/v1/instance/hostname": "host",
|
||||
"/computeMetadata/v1/instance/network-interfaces/0/ip": "1.2.3.4",
|
||||
"/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip": "5.6.7.8",
|
||||
},
|
||||
expect: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
PrivateIPv4: net.ParseIP("1.2.3.4"),
|
||||
PublicIPv4: net.ParseIP("5.6.7.8"),
|
||||
},
|
||||
},
|
||||
{
|
||||
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
expectErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
},
|
||||
} {
|
||||
service := &metadataService{metadata.MetadataService{
|
||||
Root: tt.root,
|
||||
Client: &test.HttpClient{Resources: tt.resources, Err: tt.clientErr},
|
||||
MetadataPath: tt.metadataPath,
|
||||
}}
|
||||
metadata, err := service.FetchMetadata()
|
||||
if Error(err) != Error(tt.expectErr) {
|
||||
t.Fatalf("bad error (%q): want %q, got %q", tt.resources, tt.expectErr, err)
|
||||
}
|
||||
if !reflect.DeepEqual(tt.expect, metadata) {
|
||||
t.Fatalf("bad fetch (%q): want %#v, got %#v", tt.resources, tt.expect, metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Error(err error) string {
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
5
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/metadata.go
generated
vendored
5
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/metadata.go
generated
vendored
@@ -15,6 +15,7 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
@@ -28,11 +29,11 @@ type MetadataService struct {
|
||||
MetadataPath string
|
||||
}
|
||||
|
||||
func NewDatasource(root, apiVersion, userdataPath, metadataPath string) MetadataService {
|
||||
func NewDatasource(root, apiVersion, userdataPath, metadataPath string, header http.Header) MetadataService {
|
||||
if !strings.HasSuffix(root, "/") {
|
||||
root += "/"
|
||||
}
|
||||
return MetadataService{root, pkg.NewHttpClient(), apiVersion, userdataPath, metadataPath}
|
||||
return MetadataService{root, pkg.NewHttpClientHeader(header), apiVersion, userdataPath, metadataPath}
|
||||
}
|
||||
|
||||
func (ms MetadataService) IsAvailable() bool {
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/metadata_test.go
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/metadata_test.go
generated
vendored
@@ -170,7 +170,7 @@ func TestNewDatasource(t *testing.T) {
|
||||
expectRoot: "http://169.254.169.254/",
|
||||
},
|
||||
} {
|
||||
service := NewDatasource(tt.root, "", "", "")
|
||||
service := NewDatasource(tt.root, "", "", "", nil)
|
||||
if service.Root != tt.expectRoot {
|
||||
t.Fatalf("bad root (%q): want %q, got %q", tt.root, tt.expectRoot, service.Root)
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/packet/metadata.go
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/datasource/metadata/packet/metadata.go
generated
vendored
@@ -62,7 +62,7 @@ type metadataService struct {
|
||||
}
|
||||
|
||||
func NewDatasource(root string) *metadataService {
|
||||
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath)}
|
||||
return &metadataService{MetadataService: metadata.NewDatasource(root, apiVersion, userdataUrl, metadataPath, nil)}
|
||||
}
|
||||
|
||||
func (ms *metadataService) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
|
||||
10
vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem_test.go
generated
vendored
10
vendor/github.com/coreos/coreos-cloudinit/datasource/test/filesystem_test.go
generated
vendored
@@ -70,26 +70,26 @@ func TestNewMockFilesystem(t *testing.T) {
|
||||
filesystem: MockFilesystem{},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "file"}},
|
||||
files: []File{{Path: "file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"file": File{Path: "file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/file"}},
|
||||
files: []File{{Path: "/file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"/file": File{Path: "/file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/dir/file"}},
|
||||
files: []File{{Path: "/dir/file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"/dir": File{Path: "/dir", Directory: true},
|
||||
"/dir/file": File{Path: "/dir/file"},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/dir/dir/file"}},
|
||||
files: []File{{Path: "/dir/dir/file"}},
|
||||
filesystem: MockFilesystem{
|
||||
"/dir": File{Path: "/dir", Directory: true},
|
||||
"/dir/dir": File{Path: "/dir/dir", Directory: true},
|
||||
@@ -97,7 +97,7 @@ func TestNewMockFilesystem(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
files: []File{File{Path: "/dir/dir/dir", Directory: true}},
|
||||
files: []File{{Path: "/dir/dir/dir", Directory: true}},
|
||||
filesystem: MockFilesystem{
|
||||
"/dir": File{Path: "/dir", Directory: true},
|
||||
"/dir/dir": File{Path: "/dir/dir", Directory: true},
|
||||
|
||||
82
vendor/github.com/coreos/coreos-cloudinit/datasource/vmware/vmware.go
generated
vendored
82
vendor/github.com/coreos/coreos-cloudinit/datasource/vmware/vmware.go
generated
vendored
@@ -16,18 +16,10 @@ package vmware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/config"
|
||||
"github.com/coreos/coreos-cloudinit/datasource"
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
|
||||
"github.com/sigma/vmw-guestinfo/rpcvmx"
|
||||
"github.com/sigma/vmw-guestinfo/vmcheck"
|
||||
"github.com/sigma/vmw-ovflib"
|
||||
)
|
||||
|
||||
type readConfigFunction func(key string) (string, error)
|
||||
@@ -39,65 +31,6 @@ type vmware struct {
|
||||
urlDownload urlDownloadFunction
|
||||
}
|
||||
|
||||
type ovfWrapper struct {
|
||||
env *ovf.OvfEnvironment
|
||||
}
|
||||
|
||||
func (ovf ovfWrapper) readConfig(key string) (string, error) {
|
||||
return ovf.env.Properties["guestinfo."+key], nil
|
||||
}
|
||||
|
||||
func NewDatasource(fileName string) *vmware {
|
||||
getOvfReadConfig := func(ovfEnv []byte) readConfigFunction {
|
||||
env := &ovf.OvfEnvironment{}
|
||||
if len(ovfEnv) != 0 {
|
||||
env = ovf.ReadEnvironment(ovfEnv)
|
||||
}
|
||||
|
||||
wrapper := ovfWrapper{env}
|
||||
return wrapper.readConfig
|
||||
}
|
||||
|
||||
// read from provided ovf environment document (typically /media/ovfenv/ovf-env.xml)
|
||||
if fileName != "" {
|
||||
log.Printf("Using OVF environment from %s\n", fileName)
|
||||
ovfEnv, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
ovfEnv = make([]byte, 0)
|
||||
}
|
||||
return &vmware{
|
||||
ovfFileName: fileName,
|
||||
readConfig: getOvfReadConfig(ovfEnv),
|
||||
urlDownload: urlDownload,
|
||||
}
|
||||
}
|
||||
|
||||
// try to read ovf environment from VMware tools
|
||||
data, err := readConfig("ovfenv")
|
||||
if err == nil && data != "" {
|
||||
log.Printf("Using OVF environment from guestinfo\n")
|
||||
return &vmware{
|
||||
readConfig: getOvfReadConfig([]byte(data)),
|
||||
urlDownload: urlDownload,
|
||||
}
|
||||
}
|
||||
|
||||
// if everything fails, fallback to directly reading variables from the backdoor
|
||||
log.Printf("Using guestinfo variables\n")
|
||||
return &vmware{
|
||||
readConfig: readConfig,
|
||||
urlDownload: urlDownload,
|
||||
}
|
||||
}
|
||||
|
||||
func (v vmware) IsAvailable() bool {
|
||||
if v.ovfFileName != "" {
|
||||
_, err := os.Stat(v.ovfFileName)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
return vmcheck.IsVirtualWorld()
|
||||
}
|
||||
|
||||
func (v vmware) AvailabilityChanges() bool {
|
||||
return false
|
||||
}
|
||||
@@ -218,18 +151,3 @@ func (v vmware) FetchUserdata() ([]byte, error) {
|
||||
func (v vmware) Type() string {
|
||||
return "vmware"
|
||||
}
|
||||
|
||||
func urlDownload(url string) ([]byte, error) {
|
||||
client := pkg.NewHttpClient()
|
||||
return client.GetRetry(url)
|
||||
}
|
||||
|
||||
func readConfig(key string) (string, error) {
|
||||
data, err := rpcvmx.NewConfig().String(key, "")
|
||||
if err == nil {
|
||||
log.Printf("Read from %q: %q\n", key, data)
|
||||
} else {
|
||||
log.Printf("Failed to read from %q: %v\n", key, err)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
101
vendor/github.com/coreos/coreos-cloudinit/datasource/vmware/vmware_amd64.go
generated
vendored
Normal file
101
vendor/github.com/coreos/coreos-cloudinit/datasource/vmware/vmware_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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 vmware
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/coreos-cloudinit/pkg"
|
||||
|
||||
"github.com/sigma/vmw-guestinfo/rpcvmx"
|
||||
"github.com/sigma/vmw-guestinfo/vmcheck"
|
||||
"github.com/sigma/vmw-ovflib"
|
||||
)
|
||||
|
||||
type ovfWrapper struct {
|
||||
env *ovf.OvfEnvironment
|
||||
}
|
||||
|
||||
func (ovf ovfWrapper) readConfig(key string) (string, error) {
|
||||
return ovf.env.Properties["guestinfo."+key], nil
|
||||
}
|
||||
|
||||
func NewDatasource(fileName string) *vmware {
|
||||
// read from provided ovf environment document (typically /media/ovfenv/ovf-env.xml)
|
||||
if fileName != "" {
|
||||
log.Printf("Using OVF environment from %s\n", fileName)
|
||||
ovfEnv, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
ovfEnv = make([]byte, 0)
|
||||
}
|
||||
return &vmware{
|
||||
ovfFileName: fileName,
|
||||
readConfig: getOvfReadConfig(ovfEnv),
|
||||
urlDownload: urlDownload,
|
||||
}
|
||||
}
|
||||
|
||||
// try to read ovf environment from VMware tools
|
||||
data, err := readConfig("ovfenv")
|
||||
if err == nil && data != "" {
|
||||
log.Printf("Using OVF environment from guestinfo\n")
|
||||
return &vmware{
|
||||
readConfig: getOvfReadConfig([]byte(data)),
|
||||
urlDownload: urlDownload,
|
||||
}
|
||||
}
|
||||
|
||||
// if everything fails, fallback to directly reading variables from the backdoor
|
||||
log.Printf("Using guestinfo variables\n")
|
||||
return &vmware{
|
||||
readConfig: readConfig,
|
||||
urlDownload: urlDownload,
|
||||
}
|
||||
}
|
||||
|
||||
func (v vmware) IsAvailable() bool {
|
||||
if v.ovfFileName != "" {
|
||||
_, err := os.Stat(v.ovfFileName)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
return vmcheck.IsVirtualWorld()
|
||||
}
|
||||
|
||||
func readConfig(key string) (string, error) {
|
||||
data, err := rpcvmx.NewConfig().String(key, "")
|
||||
if err == nil {
|
||||
log.Printf("Read from %q: %q\n", key, data)
|
||||
} else {
|
||||
log.Printf("Failed to read from %q: %v\n", key, err)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func getOvfReadConfig(ovfEnv []byte) readConfigFunction {
|
||||
env := &ovf.OvfEnvironment{}
|
||||
if len(ovfEnv) != 0 {
|
||||
env = ovf.ReadEnvironment(ovfEnv)
|
||||
}
|
||||
|
||||
wrapper := ovfWrapper{env}
|
||||
return wrapper.readConfig
|
||||
}
|
||||
|
||||
func urlDownload(url string) ([]byte, error) {
|
||||
client := pkg.NewHttpClient()
|
||||
return client.GetRetry(url)
|
||||
}
|
||||
25
vendor/github.com/coreos/coreos-cloudinit/datasource/vmware/vmware_unsupported.go
generated
vendored
Normal file
25
vendor/github.com/coreos/coreos-cloudinit/datasource/vmware/vmware_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
// +build !amd64
|
||||
|
||||
package vmware
|
||||
|
||||
func NewDatasource(fileName string) *vmware {
|
||||
return &vmware{}
|
||||
}
|
||||
|
||||
func (v vmware) IsAvailable() bool {
|
||||
return false
|
||||
}
|
||||
38
vendor/github.com/coreos/coreos-cloudinit/initialize/config_test.go
generated
vendored
38
vendor/github.com/coreos/coreos-cloudinit/initialize/config_test.go
generated
vendored
@@ -123,9 +123,9 @@ func TestCreateNetworkingUnits(t *testing.T) {
|
||||
network.InterfaceGenerator(mockInterface{filename: "test3", network: "test network"}),
|
||||
},
|
||||
[]system.Unit{
|
||||
system.Unit{Unit: config.Unit{Name: "test1.netdev", Runtime: true, Content: "test netdev"}},
|
||||
system.Unit{Unit: config.Unit{Name: "test2.link", Runtime: true, Content: "test link"}},
|
||||
system.Unit{Unit: config.Unit{Name: "test3.network", Runtime: true, Content: "test network"}},
|
||||
{Unit: config.Unit{Name: "test1.netdev", Runtime: true, Content: "test netdev"}},
|
||||
{Unit: config.Unit{Name: "test2.link", Runtime: true, Content: "test link"}},
|
||||
{Unit: config.Unit{Name: "test3.network", Runtime: true, Content: "test network"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -133,9 +133,9 @@ func TestCreateNetworkingUnits(t *testing.T) {
|
||||
network.InterfaceGenerator(mockInterface{filename: "test", netdev: "test netdev", link: "test link", network: "test network"}),
|
||||
},
|
||||
[]system.Unit{
|
||||
system.Unit{Unit: config.Unit{Name: "test.netdev", Runtime: true, Content: "test netdev"}},
|
||||
system.Unit{Unit: config.Unit{Name: "test.link", Runtime: true, Content: "test link"}},
|
||||
system.Unit{Unit: config.Unit{Name: "test.network", Runtime: true, Content: "test network"}},
|
||||
{Unit: config.Unit{Name: "test.netdev", Runtime: true, Content: "test netdev"}},
|
||||
{Unit: config.Unit{Name: "test.link", Runtime: true, Content: "test link"}},
|
||||
{Unit: config.Unit{Name: "test.network", Runtime: true, Content: "test network"}},
|
||||
},
|
||||
},
|
||||
} {
|
||||
@@ -154,7 +154,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "foo",
|
||||
Mask: true,
|
||||
}},
|
||||
@@ -165,16 +165,16 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "baz.service",
|
||||
Content: "[Service]\nExecStart=/bin/baz",
|
||||
Command: "start",
|
||||
}},
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "foo.network",
|
||||
Content: "[Network]\nFoo=true",
|
||||
}},
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "bar.network",
|
||||
Content: "[Network]\nBar=true",
|
||||
}},
|
||||
@@ -182,15 +182,15 @@ func TestProcessUnits(t *testing.T) {
|
||||
result: TestUnitManager{
|
||||
placed: []string{"baz.service", "foo.network", "bar.network"},
|
||||
commands: []UnitAction{
|
||||
UnitAction{"systemd-networkd.service", "restart"},
|
||||
UnitAction{"baz.service", "start"},
|
||||
{"systemd-networkd.service", "restart"},
|
||||
{"baz.service", "start"},
|
||||
},
|
||||
reload: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "baz.service",
|
||||
Content: "[Service]\nExecStart=/bin/true",
|
||||
}},
|
||||
@@ -202,7 +202,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "locksmithd.service",
|
||||
Runtime: true,
|
||||
}},
|
||||
@@ -213,7 +213,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "woof",
|
||||
Enable: true,
|
||||
}},
|
||||
@@ -224,7 +224,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "hi.service",
|
||||
Runtime: true,
|
||||
Content: "[Service]\nExecStart=/bin/echo hi",
|
||||
@@ -248,7 +248,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
DropIns: []config.UnitDropIn{
|
||||
{
|
||||
Name: "lo.conf",
|
||||
@@ -261,7 +261,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "hi.service",
|
||||
DropIns: []config.UnitDropIn{
|
||||
{
|
||||
@@ -274,7 +274,7 @@ func TestProcessUnits(t *testing.T) {
|
||||
},
|
||||
{
|
||||
units: []system.Unit{
|
||||
system.Unit{Unit: config.Unit{
|
||||
{Unit: config.Unit{
|
||||
Name: "hi.service",
|
||||
DropIns: []config.UnitDropIn{
|
||||
{
|
||||
|
||||
11
vendor/github.com/coreos/coreos-cloudinit/initialize/user_data.go
generated
vendored
11
vendor/github.com/coreos/coreos-cloudinit/initialize/user_data.go
generated
vendored
@@ -36,7 +36,16 @@ func ParseUserData(contents string) (interface{}, error) {
|
||||
return config.NewScript(contents)
|
||||
case config.IsCloudConfig(contents):
|
||||
log.Printf("Parsing user-data as cloud-config")
|
||||
return config.NewCloudConfig(contents)
|
||||
cc, err := config.NewCloudConfig(contents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cc.Decode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
case config.IsIgnitionConfig(contents):
|
||||
return nil, ErrIgnitionConfig
|
||||
default:
|
||||
|
||||
14
vendor/github.com/coreos/coreos-cloudinit/network/digitalocean_test.go
generated
vendored
14
vendor/github.com/coreos/coreos-cloudinit/network/digitalocean_test.go
generated
vendored
@@ -138,7 +138,7 @@ func TestParseInterface(t *testing.T) {
|
||||
iface: &logicalInterface{
|
||||
hwaddr: net.HardwareAddr([]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}),
|
||||
config: configMethodStatic{
|
||||
addresses: []net.IPNet{net.IPNet{
|
||||
addresses: []net.IPNet{{
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Mask: net.IPMask(net.ParseIP("255.255.0.0")),
|
||||
}},
|
||||
@@ -174,12 +174,12 @@ func TestParseInterface(t *testing.T) {
|
||||
iface: &logicalInterface{
|
||||
hwaddr: net.HardwareAddr([]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}),
|
||||
config: configMethodStatic{
|
||||
addresses: []net.IPNet{net.IPNet{
|
||||
addresses: []net.IPNet{{
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Mask: net.IPMask(net.ParseIP("255.255.0.0")),
|
||||
}},
|
||||
nameservers: []net.IP{},
|
||||
routes: []route{route{
|
||||
routes: []route{{
|
||||
net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
net.ParseIP("5.6.7.8"),
|
||||
}},
|
||||
@@ -210,7 +210,7 @@ func TestParseInterface(t *testing.T) {
|
||||
iface: &logicalInterface{
|
||||
hwaddr: net.HardwareAddr([]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}),
|
||||
config: configMethodStatic{
|
||||
addresses: []net.IPNet{net.IPNet{
|
||||
addresses: []net.IPNet{{
|
||||
IP: net.ParseIP("fe00::"),
|
||||
Mask: net.IPMask(net.ParseIP("ffff::")),
|
||||
}},
|
||||
@@ -246,12 +246,12 @@ func TestParseInterface(t *testing.T) {
|
||||
iface: &logicalInterface{
|
||||
hwaddr: net.HardwareAddr([]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}),
|
||||
config: configMethodStatic{
|
||||
addresses: []net.IPNet{net.IPNet{
|
||||
addresses: []net.IPNet{{
|
||||
IP: net.ParseIP("fe00::"),
|
||||
Mask: net.IPMask(net.ParseIP("ffff::")),
|
||||
}},
|
||||
nameservers: []net.IP{},
|
||||
routes: []route{route{
|
||||
routes: []route{{
|
||||
net.IPNet{IP: net.IPv6zero, Mask: net.IPMask(net.IPv6zero)},
|
||||
net.ParseIP("fe00:1234::"),
|
||||
}},
|
||||
@@ -446,7 +446,7 @@ func TestProcessDigitalOceanNetconf(t *testing.T) {
|
||||
cfg: digitalocean.Metadata{
|
||||
Interfaces: digitalocean.Interfaces{
|
||||
Public: []digitalocean.Interface{
|
||||
digitalocean.Interface{
|
||||
{
|
||||
IPv4: &digitalocean.Address{
|
||||
IPAddress: "bad",
|
||||
},
|
||||
|
||||
36
vendor/github.com/coreos/coreos-cloudinit/network/interface_test.go
generated
vendored
36
vendor/github.com/coreos/coreos-cloudinit/network/interface_test.go
generated
vendored
@@ -96,7 +96,7 @@ func TestInterfaceGenerators(t *testing.T) {
|
||||
config: configMethodStatic{
|
||||
addresses: []net.IPNet{{IP: []byte{192, 168, 1, 100}, Mask: []byte{255, 255, 255, 0}}},
|
||||
nameservers: []net.IP{[]byte{8, 8, 8, 8}},
|
||||
routes: []route{route{destination: net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}}, gateway: []byte{1, 2, 3, 4}}},
|
||||
routes: []route{{destination: net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}}, gateway: []byte{1, 2, 3, 4}}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
@@ -152,7 +152,7 @@ func TestModprobeParams(t *testing.T) {
|
||||
|
||||
func TestBuildInterfacesLo(t *testing.T) {
|
||||
stanzas := []*stanzaInterface{
|
||||
&stanzaInterface{
|
||||
{
|
||||
name: "lo",
|
||||
kind: interfacePhysical,
|
||||
auto: false,
|
||||
@@ -174,7 +174,7 @@ func TestBuildInterfacesBlindBond(t *testing.T) {
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{
|
||||
"bond-slaves": []string{"eth0"},
|
||||
"bond-slaves": {"eth0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -211,8 +211,8 @@ func TestBuildInterfacesBlindVLAN(t *testing.T) {
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{
|
||||
"id": []string{"0"},
|
||||
"raw_device": []string{"eth0"},
|
||||
"id": {"0"},
|
||||
"raw_device": {"eth0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -243,51 +243,51 @@ func TestBuildInterfacesBlindVLAN(t *testing.T) {
|
||||
|
||||
func TestBuildInterfaces(t *testing.T) {
|
||||
stanzas := []*stanzaInterface{
|
||||
&stanzaInterface{
|
||||
{
|
||||
name: "eth0",
|
||||
kind: interfacePhysical,
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{},
|
||||
},
|
||||
&stanzaInterface{
|
||||
{
|
||||
name: "bond0",
|
||||
kind: interfaceBond,
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{
|
||||
"bond-slaves": []string{"eth0"},
|
||||
"bond-mode": []string{"4"},
|
||||
"bond-miimon": []string{"100"},
|
||||
"bond-slaves": {"eth0"},
|
||||
"bond-mode": {"4"},
|
||||
"bond-miimon": {"100"},
|
||||
},
|
||||
},
|
||||
&stanzaInterface{
|
||||
{
|
||||
name: "bond1",
|
||||
kind: interfaceBond,
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{
|
||||
"bond-slaves": []string{"bond0"},
|
||||
"bond-slaves": {"bond0"},
|
||||
},
|
||||
},
|
||||
&stanzaInterface{
|
||||
{
|
||||
name: "vlan0",
|
||||
kind: interfaceVLAN,
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{
|
||||
"id": []string{"0"},
|
||||
"raw_device": []string{"eth0"},
|
||||
"id": {"0"},
|
||||
"raw_device": {"eth0"},
|
||||
},
|
||||
},
|
||||
&stanzaInterface{
|
||||
{
|
||||
name: "vlan1",
|
||||
kind: interfaceVLAN,
|
||||
auto: false,
|
||||
configMethod: configMethodManual{},
|
||||
options: map[string][]string{
|
||||
"id": []string{"1"},
|
||||
"raw_device": []string{"bond0"},
|
||||
"id": {"1"},
|
||||
"raw_device": {"bond0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
6
vendor/github.com/coreos/coreos-cloudinit/network/stanza_test.go
generated
vendored
6
vendor/github.com/coreos/coreos-cloudinit/network/stanza_test.go
generated
vendored
@@ -151,7 +151,7 @@ func TestParseBondStanzaNoSlaves(t *testing.T) {
|
||||
func TestParseBondStanza(t *testing.T) {
|
||||
conf := configMethodManual{}
|
||||
options := map[string][]string{
|
||||
"bond-slaves": []string{"1", "2"},
|
||||
"bond-slaves": {"1", "2"},
|
||||
}
|
||||
bond, err := parseBondStanza("test", conf, nil, options)
|
||||
if err != nil {
|
||||
@@ -171,8 +171,8 @@ func TestParseBondStanza(t *testing.T) {
|
||||
func TestParsePhysicalStanza(t *testing.T) {
|
||||
conf := configMethodManual{}
|
||||
options := map[string][]string{
|
||||
"a": []string{"1", "2"},
|
||||
"b": []string{"1"},
|
||||
"a": {"1", "2"},
|
||||
"b": {"1"},
|
||||
}
|
||||
physical, err := parsePhysicalStanza("test", conf, nil, options)
|
||||
if err != nil {
|
||||
|
||||
14
vendor/github.com/coreos/coreos-cloudinit/network/vmware_test.go
generated
vendored
14
vendor/github.com/coreos/coreos-cloudinit/network/vmware_test.go
generated
vendored
@@ -82,11 +82,11 @@ func TestProcessVMwareNetconf(t *testing.T) {
|
||||
hwaddr: mustParseMac(net.ParseMAC("00:11:22:33:44:55")),
|
||||
config: configMethodStatic{
|
||||
hwaddress: mustParseMac(net.ParseMAC("00:11:22:33:44:55")),
|
||||
addresses: []net.IPNet{net.IPNet{IP: net.ParseIP("10.0.0.100"), Mask: net.CIDRMask(24, net.IPv4len*8)}},
|
||||
addresses: []net.IPNet{{IP: net.ParseIP("10.0.0.100"), Mask: net.CIDRMask(24, net.IPv4len*8)}},
|
||||
// I realize how upset you must be that I am shoving an IPMask into an IP. This is because net.IPv4zero is
|
||||
// actually a magic IPv6 address which ruins our equality check. What's that? Just use IP::Equal()? I'd rather
|
||||
// DeepEqual just handle that for me, but until Go gets operator overloading, we are stuck with this.
|
||||
routes: []route{route{
|
||||
routes: []route{{
|
||||
destination: net.IPNet{IP: net.IP(net.CIDRMask(0, net.IPv4len*8)), Mask: net.CIDRMask(0, net.IPv4len*8)},
|
||||
gateway: net.ParseIP("10.0.0.1")},
|
||||
},
|
||||
@@ -116,10 +116,10 @@ func TestProcessVMwareNetconf(t *testing.T) {
|
||||
config: configMethodStatic{
|
||||
hwaddress: mustParseMac(net.ParseMAC("00:11:22:33:44:55")),
|
||||
addresses: []net.IPNet{
|
||||
net.IPNet{IP: net.ParseIP("10.0.0.100"), Mask: net.CIDRMask(24, net.IPv4len*8)},
|
||||
net.IPNet{IP: net.ParseIP("10.0.0.101"), Mask: net.CIDRMask(24, net.IPv4len*8)},
|
||||
{IP: net.ParseIP("10.0.0.100"), Mask: net.CIDRMask(24, net.IPv4len*8)},
|
||||
{IP: net.ParseIP("10.0.0.101"), Mask: net.CIDRMask(24, net.IPv4len*8)},
|
||||
},
|
||||
routes: []route{route{
|
||||
routes: []route{{
|
||||
destination: net.IPNet{IP: net.IP(net.CIDRMask(0, net.IPv4len*8)), Mask: net.CIDRMask(0, net.IPv4len*8)},
|
||||
gateway: net.ParseIP("10.0.0.1")},
|
||||
},
|
||||
@@ -129,8 +129,8 @@ func TestProcessVMwareNetconf(t *testing.T) {
|
||||
&physicalInterface{logicalInterface{
|
||||
name: "eth0",
|
||||
config: configMethodStatic{
|
||||
addresses: []net.IPNet{net.IPNet{IP: net.ParseIP("10.0.1.100"), Mask: net.CIDRMask(24, net.IPv4len*8)}},
|
||||
routes: []route{route{
|
||||
addresses: []net.IPNet{{IP: net.ParseIP("10.0.1.100"), Mask: net.CIDRMask(24, net.IPv4len*8)}},
|
||||
routes: []route{{
|
||||
destination: net.IPNet{IP: net.IP(net.CIDRMask(0, net.IPv4len*8)), Mask: net.CIDRMask(0, net.IPv4len*8)},
|
||||
gateway: net.ParseIP("10.0.1.1")},
|
||||
},
|
||||
|
||||
18
vendor/github.com/coreos/coreos-cloudinit/pkg/http_client.go
generated
vendored
18
vendor/github.com/coreos/coreos-cloudinit/pkg/http_client.go
generated
vendored
@@ -62,8 +62,8 @@ type HttpClient struct {
|
||||
// Maximum number of connection retries. Defaults to 15
|
||||
MaxRetries int
|
||||
|
||||
// Whether or not to skip TLS verification. Defaults to false
|
||||
SkipTLS bool
|
||||
// Headers to add to the request.
|
||||
Header http.Header
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
@@ -74,11 +74,15 @@ type Getter interface {
|
||||
}
|
||||
|
||||
func NewHttpClient() *HttpClient {
|
||||
return NewHttpClientHeader(nil)
|
||||
}
|
||||
|
||||
func NewHttpClientHeader(header http.Header) *HttpClient {
|
||||
hc := &HttpClient{
|
||||
InitialBackoff: 50 * time.Millisecond,
|
||||
MaxBackoff: time.Second * 5,
|
||||
MaxRetries: 15,
|
||||
SkipTLS: false,
|
||||
Header: header,
|
||||
client: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
@@ -139,7 +143,13 @@ func (h *HttpClient) GetRetry(rawurl string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func (h *HttpClient) Get(dataURL string) ([]byte, error) {
|
||||
if resp, err := h.client.Get(dataURL); err == nil {
|
||||
request, err := http.NewRequest("GET", dataURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request.Header = h.Header
|
||||
if resp, err := h.client.Do(request); err == nil {
|
||||
defer resp.Body.Close()
|
||||
switch resp.StatusCode / 100 {
|
||||
case HTTP_2xx:
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/system/env_file.go
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/system/env_file.go
generated
vendored
@@ -106,7 +106,7 @@ func WriteEnvFile(ef *EnvFile, root string) error {
|
||||
|
||||
// keys returns the keys of a map in sorted order
|
||||
func keys(m map[string]string) (s []string) {
|
||||
for k, _ := range m {
|
||||
for k := range m {
|
||||
s = append(s, k)
|
||||
}
|
||||
sort.Strings(s)
|
||||
|
||||
13
vendor/github.com/coreos/coreos-cloudinit/system/file.go
generated
vendored
13
vendor/github.com/coreos/coreos-cloudinit/system/file.go
generated
vendored
@@ -45,17 +45,16 @@ func (f *File) Permissions() (os.FileMode, error) {
|
||||
return os.FileMode(perm), nil
|
||||
}
|
||||
|
||||
// WriteFile writes given endecoded file to the filesystem
|
||||
func WriteFile(f *File, root string) (string, error) {
|
||||
if f.Encoding != "" {
|
||||
return "", fmt.Errorf("Unable to write file with encoding %s", f.Encoding)
|
||||
}
|
||||
|
||||
fullpath := path.Join(root, f.Path)
|
||||
dir := path.Dir(fullpath)
|
||||
log.Printf("Writing file to %q", fullpath)
|
||||
|
||||
content, err := config.DecodeContent(f.Content, f.Encoding)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to decode %s (%v)", f.Path, err)
|
||||
}
|
||||
|
||||
if err := EnsureDirectoryExists(dir); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -71,7 +70,7 @@ func WriteFile(f *File, root string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(tmp.Name(), content, perm); err != nil {
|
||||
if err := ioutil.WriteFile(tmp.Name(), []byte(f.Content), perm); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
56
vendor/github.com/coreos/coreos-cloudinit/system/file_test.go
generated
vendored
56
vendor/github.com/coreos/coreos-cloudinit/system/file_test.go
generated
vendored
@@ -147,62 +147,6 @@ func TestWriteFilePermissions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteFileEncodedContent(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)
|
||||
|
||||
//all of these decode to "bar"
|
||||
content_tests := map[string]string{
|
||||
"base64": "YmFy",
|
||||
"b64": "YmFy",
|
||||
"gz": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
|
||||
"gzip": "\x1f\x8b\x08\x08w\x14\x87T\x02\xffok\x00KJ,\x02\x00\xaa\x8c\xffv\x03\x00\x00\x00",
|
||||
"gz+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
"gzip+base64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
"gz+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
"gzip+b64": "H4sIABMVh1QAA0tKLAIAqoz/dgMAAAA=",
|
||||
}
|
||||
|
||||
for encoding, content := range content_tests {
|
||||
fullPath := path.Join(dir, encoding)
|
||||
|
||||
wf := File{config.File{
|
||||
Path: encoding,
|
||||
Encoding: encoding,
|
||||
Content: content,
|
||||
RawFilePermissions: "0644",
|
||||
}}
|
||||
|
||||
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(0644) {
|
||||
t.Errorf("File has incorrect mode: %v", fi.Mode())
|
||||
}
|
||||
|
||||
contents, err := ioutil.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read expected file: %v", err)
|
||||
}
|
||||
|
||||
if string(contents) != "bar" {
|
||||
t.Fatalf("File has incorrect contents: '%s'", contents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteFileInvalidEncodedContent(t *testing.T) {
|
||||
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
|
||||
if err != nil {
|
||||
|
||||
40
vendor/github.com/coreos/coreos-cloudinit/test
generated
vendored
40
vendor/github.com/coreos/coreos-cloudinit/test
generated
vendored
@@ -2,42 +2,26 @@
|
||||
|
||||
source ./build
|
||||
|
||||
SRC="
|
||||
config
|
||||
config/validate
|
||||
datasource
|
||||
datasource/configdrive
|
||||
datasource/file
|
||||
datasource/metadata
|
||||
datasource/metadata/cloudsigma
|
||||
datasource/metadata/digitalocean
|
||||
datasource/metadata/ec2
|
||||
datasource/proc_cmdline
|
||||
datasource/test
|
||||
datasource/url
|
||||
datasource/vmware
|
||||
datasource/waagent
|
||||
initialize
|
||||
network
|
||||
pkg
|
||||
system
|
||||
.
|
||||
"
|
||||
SRC=$(find . -name '*.go' \
|
||||
-not -path "./vendor/*")
|
||||
|
||||
PKG=$(cd gopath/src/${REPO_PATH}; go list ./... | \
|
||||
grep --invert-match vendor)
|
||||
|
||||
echo "Checking gofix..."
|
||||
go tool fix -diff $SRC
|
||||
|
||||
echo "Checking gofmt..."
|
||||
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="${REPO_PATH} ${split_vet[@]/#/${REPO_PATH}/}"
|
||||
res=$(gofmt -d -e -s $SRC)
|
||||
echo "${res}"
|
||||
if [ -n "${res}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking govet..."
|
||||
go vet $VET_TEST
|
||||
go vet $PKG
|
||||
|
||||
echo "Running tests..."
|
||||
go test -timeout 60s -cover $@ ${VET_TEST} --race
|
||||
go test -timeout 60s -cover $@ ${PKG} --race
|
||||
|
||||
echo "Success"
|
||||
|
||||
2
vendor/github.com/coreos/coreos-cloudinit/units/user-config.target
generated
vendored
2
vendor/github.com/coreos/coreos-cloudinit/units/user-config.target
generated
vendored
@@ -4,8 +4,6 @@ Requires=system-config.target
|
||||
After=system-config.target
|
||||
|
||||
# Watch for configs at a couple common paths
|
||||
Requires=user-configdrive.path
|
||||
After=user-configdrive.path
|
||||
Requires=user-cloudinit@var-lib-coreos\x2dinstall-user_data.path
|
||||
After=user-cloudinit@var-lib-coreos\x2dinstall-user_data.path
|
||||
|
||||
|
||||
10
vendor/github.com/coreos/coreos-cloudinit/units/user-configdrive.path
generated
vendored
10
vendor/github.com/coreos/coreos-cloudinit/units/user-configdrive.path
generated
vendored
@@ -1,10 +0,0 @@
|
||||
[Unit]
|
||||
Description=Watch for a cloud-config at /media/configdrive
|
||||
|
||||
# Note: This unit is essentially just here as a fall-back mechanism to
|
||||
# trigger cloudinit if it isn't triggered explicitly by other means
|
||||
# such as by a Wants= in the mount unit. This ensures we handle the
|
||||
# case where /media/configdrive is provided to a CoreOS container.
|
||||
|
||||
[Path]
|
||||
DirectoryNotEmpty=/media/configdrive
|
||||
11
vendor/github.com/coreos/coreos-cloudinit/vendor.manifest
generated
vendored
Normal file
11
vendor/github.com/coreos/coreos-cloudinit/vendor.manifest
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# If you manipulate the contents of vendor/, amend this accordingly.
|
||||
# pkg version
|
||||
github.com/cloudsigma/cepgo 1bfc4895bf5c4d3b599f3f6ee142299488c8739b
|
||||
github.com/coreos/go-systemd/dbus 4fbc5060a317b142e6c7bfbedb65596d5f0ab99b
|
||||
github.com/coreos/yaml 6b16a5714269b2f70720a45406b1babd947a17ef
|
||||
github.com/dotcloud/docker/pkg/netlink 55d41c3e21e1593b944c06196ffb2ac57ab7f653
|
||||
github.com/guelfey/go.dbus f6a3a2366cc39b8479cadc499d3c735fb10fbdda
|
||||
github.com/tarm/goserial cdabc8d44e8e84f58f18074ae44337e1f2f375b9
|
||||
github.com/sigma/vmw-guestinfo 95dd4126d6e8b4ef1970b3f3fe2e8cdd470d2903
|
||||
github.com/sigma/vmw-ovflib 56b4f44581cac03d17d8270158bdfd0942ffe790
|
||||
github.com/sigma/bdoor babf2a4017b020d4ce04e8167076186e82645dd1
|
||||
2
vendor/github.com/coreos/fuze/doc/configuration.md
generated
vendored
2
vendor/github.com/coreos/fuze/doc/configuration.md
generated
vendored
@@ -47,7 +47,7 @@ The Fuze configuration is a YAML document conforming to the following specificat
|
||||
* **_inline_** (string): the contents of the file.
|
||||
* **_remote_** (object): options related to the fetching of remote file contents.
|
||||
* **_compression_** (string): the type of compression used on the contents (null or gzip)
|
||||
* **_source_** (string): the URL of the file contents. Supported schemes are http and [data][rfc2397]. Note: When using http, it is advisable to use the verification option to ensure the contents haven't been modified.
|
||||
* **_url_** (string): the URL of the file contents. Supported schemes are http and [data][rfc2397]. Note: When using http, it is advisable to use the verification option to ensure the contents haven't been modified.
|
||||
* **_verification_** (object): options related to the verification of the file contents.
|
||||
* **_hash_** (object): the hash of the config
|
||||
* **_function_** (string): the function used to hash the config. Supported functions are sha512.
|
||||
|
||||
27
vendor/github.com/coreos/go-systemd/.travis.yml
generated
vendored
27
vendor/github.com/coreos/go-systemd/.travis.yml
generated
vendored
@@ -1,8 +1,27 @@
|
||||
language: go
|
||||
go: 1.4
|
||||
sudo: required
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
- GOPATH=/opt
|
||||
- BUILD_DIR=/opt/src/github.com/coreos/go-systemd
|
||||
matrix:
|
||||
- DOCKER_BASE=ubuntu:16.04
|
||||
- DOCKER_BASE=debian:stretch
|
||||
|
||||
before_install:
|
||||
- docker pull ${DOCKER_BASE}
|
||||
- docker run --privileged -e GOPATH=${GOPATH} --cidfile=/tmp/cidfile ${DOCKER_BASE} /bin/bash -c "apt-get update && apt-get install -y build-essential git golang dbus libsystemd-dev libpam-systemd && go get github.com/coreos/pkg/dlopen && go get github.com/godbus/dbus"
|
||||
- docker commit `cat /tmp/cidfile` go-systemd/container-tests
|
||||
- rm -f /tmp/cidfile
|
||||
|
||||
install:
|
||||
- go get github.com/godbus/dbus
|
||||
- docker run -d --cidfile=/tmp/cidfile --privileged -e GOPATH=${GOPATH} -v ${PWD}:${BUILD_DIR} go-systemd/container-tests /bin/systemd --system
|
||||
|
||||
script:
|
||||
- ./test
|
||||
- docker exec `cat /tmp/cidfile` /bin/bash -c "cd ${BUILD_DIR} && ./test"
|
||||
|
||||
after_script:
|
||||
- docker kill `cat /tmp/cidfile`
|
||||
|
||||
2
vendor/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
2
vendor/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
@@ -48,8 +48,6 @@ func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error)
|
||||
}
|
||||
|
||||
if tlsConfig != nil && err == nil {
|
||||
tlsConfig.NextProtos = []string{"http/1.1"}
|
||||
|
||||
for i, l := range listeners {
|
||||
// Activate TLS only for TCP sockets
|
||||
if l.Addr().Network() == "tcp" {
|
||||
|
||||
21
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go
generated
vendored
21
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go
generated
vendored
@@ -2,30 +2,37 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
var SdNotifyNoSocket = errors.New("No socket")
|
||||
|
||||
// SdNotify sends a message to the init daemon. It is common to ignore the error.
|
||||
func SdNotify(state string) error {
|
||||
// It returns one of the following:
|
||||
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
|
||||
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
|
||||
// (true, nil) - notification supported, data has been sent
|
||||
func SdNotify(state string) (sent bool, err error) {
|
||||
socketAddr := &net.UnixAddr{
|
||||
Name: os.Getenv("NOTIFY_SOCKET"),
|
||||
Net: "unixgram",
|
||||
}
|
||||
|
||||
// NOTIFY_SOCKET not set
|
||||
if socketAddr.Name == "" {
|
||||
return SdNotifyNoSocket
|
||||
return false, nil
|
||||
}
|
||||
|
||||
conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
|
||||
// Error connecting to NOTIFY_SOCKET
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = conn.Write([]byte(state))
|
||||
return err
|
||||
// Error sending the message
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
75
vendor/github.com/coreos/go-systemd/daemon/sdnotify_test.go
generated
vendored
Normal file
75
vendor/github.com/coreos/go-systemd/daemon/sdnotify_test.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2016 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 daemon
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestSdNotify
|
||||
func TestSdNotify(t *testing.T) {
|
||||
notificationSupportedDataSent := "Notification supported, data sent"
|
||||
notificationSupportedFailure := "Notification supported, but failure happened"
|
||||
notificationNotSupported := "Notification not supported"
|
||||
|
||||
testDir, e := ioutil.TempDir("/tmp/", "test-")
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
notifySocket := testDir + "/notify-socket.sock"
|
||||
laddr := net.UnixAddr{
|
||||
Name: notifySocket,
|
||||
Net: "unixgram",
|
||||
}
|
||||
_, e = net.ListenUnixgram("unixgram", &laddr)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
|
||||
// (true, nil) - notification supported, data has been sent
|
||||
e = os.Setenv("NOTIFY_SOCKET", notifySocket)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
sent, err := SdNotify(notificationSupportedDataSent)
|
||||
if !sent || err != nil {
|
||||
t.Errorf("TEST: %s FAILED", notificationSupportedDataSent)
|
||||
}
|
||||
|
||||
// (false, err) - notification supported, but failure happened
|
||||
e = os.Setenv("NOTIFY_SOCKET", testDir+"/not-exist.sock")
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
sent, err = SdNotify(notificationSupportedFailure)
|
||||
if sent && err == nil {
|
||||
t.Errorf("TEST: %s FAILED", notificationSupportedFailure)
|
||||
}
|
||||
|
||||
// (false, nil) - notification not supported
|
||||
e = os.Unsetenv("NOTIFY_SOCKET")
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
sent, err = SdNotify(notificationNotSupported)
|
||||
if sent || err != nil {
|
||||
t.Errorf("TEST: %s FAILED", notificationNotSupported)
|
||||
}
|
||||
}
|
||||
17
vendor/github.com/coreos/go-systemd/dbus/dbus.go
generated
vendored
17
vendor/github.com/coreos/go-systemd/dbus/dbus.go
generated
vendored
@@ -86,7 +86,7 @@ type Conn struct {
|
||||
// New establishes a connection to the system bus and authenticates.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func New() (*Conn, error) {
|
||||
return newConnection(func() (*dbus.Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
return dbusAuthHelloConnection(dbus.SystemBusPrivate)
|
||||
})
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func New() (*Conn, error) {
|
||||
// authenticates. This can be used to connect to systemd user instances.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func NewUserConnection() (*Conn, error) {
|
||||
return newConnection(func() (*dbus.Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
return dbusAuthHelloConnection(dbus.SessionBusPrivate)
|
||||
})
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func NewUserConnection() (*Conn, error) {
|
||||
// This can be used for communicating with systemd without a dbus daemon.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func NewSystemdConnection() (*Conn, error) {
|
||||
return newConnection(func() (*dbus.Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
// We skip Hello when talking directly to systemd.
|
||||
return dbusAuthConnection(func() (*dbus.Conn, error) {
|
||||
return dbus.Dial("unix:path=/run/systemd/private")
|
||||
@@ -118,13 +118,18 @@ func (c *Conn) Close() {
|
||||
c.sigconn.Close()
|
||||
}
|
||||
|
||||
func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
|
||||
sysconn, err := createBus()
|
||||
// NewConnection establishes a connection to a bus using a caller-supplied function.
|
||||
// This allows connecting to remote buses through a user-supplied mechanism.
|
||||
// The supplied function may be called multiple times, and should return independent connections.
|
||||
// The returned connection must be fully initialised: the org.freedesktop.DBus.Hello call must have succeeded,
|
||||
// and any authentication should be handled by the function.
|
||||
func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) {
|
||||
sysconn, err := dialBus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigconn, err := createBus()
|
||||
sigconn, err := dialBus()
|
||||
if err != nil {
|
||||
sysconn.Close()
|
||||
return nil, err
|
||||
|
||||
139
vendor/github.com/coreos/go-systemd/dbus/methods.go
generated
vendored
139
vendor/github.com/coreos/go-systemd/dbus/methods.go
generated
vendored
@@ -199,6 +199,11 @@ func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, err
|
||||
return c.getProperty(unit, "org.freedesktop.systemd1.Unit", propertyName)
|
||||
}
|
||||
|
||||
// GetServiceProperty returns property for given service name and property name
|
||||
func (c *Conn) GetServiceProperty(service string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(service, "org.freedesktop.systemd1.Service", propertyName)
|
||||
}
|
||||
|
||||
// GetUnitTypeProperties returns the extra properties for a unit, specific to the unit type.
|
||||
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
||||
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
||||
@@ -234,12 +239,11 @@ type UnitStatus struct {
|
||||
JobPath dbus.ObjectPath // The job object path
|
||||
}
|
||||
|
||||
// ListUnits returns an array with all currently loaded units. Note that
|
||||
// units may be known by multiple names at the same time, and hence there might
|
||||
// be more unit names loaded than actual units behind them.
|
||||
func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||
type storeFunc func(retvalues ...interface{}) error
|
||||
|
||||
func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store(&result)
|
||||
err := f(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,15 +267,43 @@ func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// ListUnits returns an array with all currently loaded units. Note that
|
||||
// units may be known by multiple names at the same time, and hence there might
|
||||
// be more unit names loaded than actual units behind them.
|
||||
func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
|
||||
}
|
||||
|
||||
// ListUnitsFiltered returns an array with units filtered by state.
|
||||
// It takes a list of units' statuses to filter.
|
||||
func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store)
|
||||
}
|
||||
|
||||
// ListUnitsByPatterns returns an array with units.
|
||||
// It takes a list of units' statuses and names to filter.
|
||||
// Note that units may be known by multiple names at the same time,
|
||||
// and hence there might be more unit names loaded than actual units behind them.
|
||||
func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store)
|
||||
}
|
||||
|
||||
// ListUnitsByNames returns an array with units. It takes a list of units'
|
||||
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
||||
// method, this method returns statuses even for inactive or non-existing
|
||||
// units. Input array should contain exact unit names, but not patterns.
|
||||
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
||||
}
|
||||
|
||||
type UnitFile struct {
|
||||
Path string
|
||||
Type string
|
||||
}
|
||||
|
||||
// ListUnitFiles returns an array of all available units on disk.
|
||||
func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
|
||||
func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store(&result)
|
||||
err := f(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -295,6 +327,16 @@ func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// ListUnitFiles returns an array of all available units on disk.
|
||||
func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
|
||||
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
|
||||
}
|
||||
|
||||
// ListUnitFilesByPatterns returns an array of all available units on disk matched the patterns.
|
||||
func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) {
|
||||
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store)
|
||||
}
|
||||
|
||||
type LinkUnitFileChange EnableUnitFileChange
|
||||
|
||||
// LinkUnitFiles() links unit files (that are located outside of the
|
||||
@@ -431,6 +473,87 @@ type DisableUnitFileChange struct {
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// MaskUnitFiles masks one or more units in the system
|
||||
//
|
||||
// It takes three arguments:
|
||||
// * list of units to mask (either just file names or full
|
||||
// absolute paths if the unit files are residing outside
|
||||
// the usual unit search paths)
|
||||
// * runtime to specify whether the unit was enabled for runtime
|
||||
// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..)
|
||||
// * force flag
|
||||
func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultInterface := make([]interface{}, len(result))
|
||||
for i := range result {
|
||||
resultInterface[i] = result[i]
|
||||
}
|
||||
|
||||
changes := make([]MaskUnitFileChange, len(result))
|
||||
changesInterface := make([]interface{}, len(changes))
|
||||
for i := range changes {
|
||||
changesInterface[i] = &changes[i]
|
||||
}
|
||||
|
||||
err = dbus.Store(resultInterface, changesInterface...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
type MaskUnitFileChange struct {
|
||||
Type string // Type of the change (one of symlink or unlink)
|
||||
Filename string // File name of the symlink
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// UnmaskUnitFiles unmasks one or more units in the system
|
||||
//
|
||||
// It takes two arguments:
|
||||
// * list of unit files to mask (either just file names or full
|
||||
// absolute paths if the unit files are residing outside
|
||||
// the usual unit search paths)
|
||||
// * runtime to specify whether the unit was enabled for runtime
|
||||
// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..)
|
||||
func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultInterface := make([]interface{}, len(result))
|
||||
for i := range result {
|
||||
resultInterface[i] = result[i]
|
||||
}
|
||||
|
||||
changes := make([]UnmaskUnitFileChange, len(result))
|
||||
changesInterface := make([]interface{}, len(changes))
|
||||
for i := range changes {
|
||||
changesInterface[i] = &changes[i]
|
||||
}
|
||||
|
||||
err = dbus.Store(resultInterface, changesInterface...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
type UnmaskUnitFileChange struct {
|
||||
Type string // Type of the change (one of symlink or unlink)
|
||||
Filename string // File name of the symlink
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// Reload instructs systemd to scan for and reload unit files. This is
|
||||
// equivalent to a 'systemctl daemon-reload'.
|
||||
func (c *Conn) Reload() error {
|
||||
|
||||
358
vendor/github.com/coreos/go-systemd/dbus/methods_test.go
generated
vendored
358
vendor/github.com/coreos/go-systemd/dbus/methods_test.go
generated
vendored
@@ -18,6 +18,8 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -70,6 +72,24 @@ func linkUnit(target string, conn *Conn, t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getUnitStatus(units []UnitStatus, name string) *UnitStatus {
|
||||
for _, u := range units {
|
||||
if u.Name == name {
|
||||
return &u
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUnitFile(units []UnitFile, name string) *UnitFile {
|
||||
for _, u := range units {
|
||||
if path.Base(u.Path) == name {
|
||||
return &u
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensure that basic unit starting and stopping works.
|
||||
func TestStartStopUnit(t *testing.T) {
|
||||
target := "start-stop.service"
|
||||
@@ -92,18 +112,11 @@ func TestStartStopUnit(t *testing.T) {
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
|
||||
var unit *UnitStatus
|
||||
for _, u := range units {
|
||||
if u.Name == target {
|
||||
unit = &u
|
||||
}
|
||||
}
|
||||
unit := getUnitStatus(units, target)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("Test unit not found in list")
|
||||
}
|
||||
|
||||
if unit.ActiveState != "active" {
|
||||
} else if unit.ActiveState != "active" {
|
||||
t.Fatalf("Test unit not active")
|
||||
}
|
||||
|
||||
@@ -118,18 +131,169 @@ func TestStartStopUnit(t *testing.T) {
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
|
||||
unit = nil
|
||||
for _, u := range units {
|
||||
if u.Name == target {
|
||||
unit = &u
|
||||
}
|
||||
}
|
||||
unit = getUnitStatus(units, target)
|
||||
|
||||
if unit != nil {
|
||||
t.Fatalf("Test unit found in list, should be stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that ListUnitsByNames works.
|
||||
func TestListUnitsByNames(t *testing.T) {
|
||||
target1 := "systemd-journald.service"
|
||||
target2 := "unexisting.service"
|
||||
|
||||
conn := setupConn(t)
|
||||
|
||||
units, err := conn.ListUnitsByNames([]string{target1, target2})
|
||||
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
unit := getUnitStatus(units, target1)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target1)
|
||||
} else if unit.ActiveState != "active" {
|
||||
t.Fatalf("%s unit should be active but it is %s", target1, unit.ActiveState)
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target2)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("Unexisting test unit not found in list")
|
||||
} else if unit.ActiveState != "inactive" {
|
||||
t.Fatalf("Test unit should be inactive")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that ListUnitsByPatterns works.
|
||||
func TestListUnitsByPatterns(t *testing.T) {
|
||||
target1 := "systemd-journald.service"
|
||||
target2 := "unexisting.service"
|
||||
|
||||
conn := setupConn(t)
|
||||
|
||||
units, err := conn.ListUnitsByPatterns([]string{}, []string{"systemd-journald*", target2})
|
||||
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
unit := getUnitStatus(units, target1)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target1)
|
||||
} else if unit.ActiveState != "active" {
|
||||
t.Fatalf("Test unit should be active")
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target2)
|
||||
|
||||
if unit != nil {
|
||||
t.Fatalf("Unexisting test unit found in list")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that ListUnitsFiltered works.
|
||||
func TestListUnitsFiltered(t *testing.T) {
|
||||
target := "systemd-journald.service"
|
||||
|
||||
conn := setupConn(t)
|
||||
|
||||
units, err := conn.ListUnitsFiltered([]string{"active"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit := getUnitStatus(units, target)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target)
|
||||
} else if unit.ActiveState != "active" {
|
||||
t.Fatalf("Test unit should be active")
|
||||
}
|
||||
|
||||
units, err = conn.ListUnitsFiltered([]string{"inactive"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target)
|
||||
|
||||
if unit != nil {
|
||||
t.Fatalf("Inactive unit should not be found in list")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that ListUnitFilesByPatterns works.
|
||||
func TestListUnitFilesByPatterns(t *testing.T) {
|
||||
target1 := "systemd-journald.service"
|
||||
target2 := "exit.target"
|
||||
|
||||
conn := setupConn(t)
|
||||
|
||||
units, err := conn.ListUnitFilesByPatterns([]string{"static"}, []string{"systemd-journald*", target2})
|
||||
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
unit := getUnitFile(units, target1)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target1)
|
||||
} else if unit.Type != "static" {
|
||||
t.Fatalf("Test unit file should be static")
|
||||
}
|
||||
|
||||
units, err = conn.ListUnitFilesByPatterns([]string{"disabled"}, []string{"systemd-journald*", target2})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit = getUnitFile(units, target2)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target2)
|
||||
} else if unit.Type != "disabled" {
|
||||
t.Fatalf("%s unit file should be disabled", target2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListUnitFiles(t *testing.T) {
|
||||
target1 := "systemd-journald.service"
|
||||
target2 := "exit.target"
|
||||
|
||||
conn := setupConn(t)
|
||||
|
||||
units, err := conn.ListUnitFiles()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit := getUnitFile(units, target1)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target1)
|
||||
} else if unit.Type != "static" {
|
||||
t.Fatalf("Test unit file should be static")
|
||||
}
|
||||
|
||||
unit = getUnitFile(units, target2)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("%s unit not found in list", target2)
|
||||
} else if unit.Type != "disabled" {
|
||||
t.Fatalf("%s unit file should be disabled", target2)
|
||||
}
|
||||
}
|
||||
|
||||
// Enables a unit and then immediately tears it down
|
||||
func TestEnableDisableUnit(t *testing.T) {
|
||||
target := "enable-disable.service"
|
||||
@@ -146,7 +310,7 @@ func TestEnableDisableUnit(t *testing.T) {
|
||||
}
|
||||
|
||||
if install != false {
|
||||
t.Fatal("Install was true")
|
||||
t.Log("Install was true")
|
||||
}
|
||||
|
||||
if len(changes) < 1 {
|
||||
@@ -158,7 +322,7 @@ func TestEnableDisableUnit(t *testing.T) {
|
||||
}
|
||||
|
||||
// 2. Disable the unit
|
||||
dChanges, err := conn.DisableUnitFiles([]string{abs}, true)
|
||||
dChanges, err := conn.DisableUnitFiles([]string{target}, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -186,27 +350,19 @@ func TestGetUnitProperties(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
names := info["Wants"].([]string)
|
||||
desc, _ := info["Description"].(string)
|
||||
|
||||
if len(names) < 1 {
|
||||
t.Fatal("/ is unwanted")
|
||||
}
|
||||
|
||||
if names[0] != "system.slice" {
|
||||
t.Fatal("unexpected wants for /")
|
||||
}
|
||||
|
||||
prop, err := conn.GetUnitProperty(unit, "Wants")
|
||||
prop, err := conn.GetUnitProperty(unit, "Description")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if prop.Name != "Wants" {
|
||||
if prop.Name != "Description" {
|
||||
t.Fatal("unexpected property name")
|
||||
}
|
||||
|
||||
val := prop.Value.Value().([]string)
|
||||
if !reflect.DeepEqual(val, names) {
|
||||
val := prop.Value.Value().(string)
|
||||
if !reflect.DeepEqual(val, desc) {
|
||||
t.Fatal("unexpected property value")
|
||||
}
|
||||
}
|
||||
@@ -230,13 +386,34 @@ func TestGetUnitPropertiesRejectsInvalidName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetUnitProperties changes a cgroup setting on the `tmp.mount`
|
||||
// TestGetServiceProperty reads the `systemd-udevd.service` which should exist
|
||||
// on all systemd systems and ensures that one of its property is valid.
|
||||
func TestGetServiceProperty(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
service := "systemd-udevd.service"
|
||||
|
||||
prop, err := conn.GetServiceProperty(service, "Type")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if prop.Name != "Type" {
|
||||
t.Fatal("unexpected property name")
|
||||
}
|
||||
|
||||
if _, ok := prop.Value.Value().(string); !ok {
|
||||
t.Fatal("invalid property value")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetUnitProperties changes a cgroup setting on the `-.mount`
|
||||
// which should exist on all systemd systems and ensures that the
|
||||
// property was set.
|
||||
func TestSetUnitProperties(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
unit := "tmp.mount"
|
||||
unit := "-.mount"
|
||||
|
||||
if err := conn.SetUnitProperties(unit, true, Property{"CPUShares", dbus.MakeVariant(uint64(1023))}); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -247,7 +424,7 @@ func TestSetUnitProperties(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value := info["CPUShares"].(uint64)
|
||||
value, _ := info["CPUShares"].(uint64)
|
||||
if value != 1023 {
|
||||
t.Fatal("CPUShares of unit is not 1023:", value)
|
||||
}
|
||||
@@ -276,18 +453,11 @@ func TestStartStopTransientUnit(t *testing.T) {
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
|
||||
var unit *UnitStatus
|
||||
for _, u := range units {
|
||||
if u.Name == target {
|
||||
unit = &u
|
||||
}
|
||||
}
|
||||
unit := getUnitStatus(units, target)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("Test unit not found in list")
|
||||
}
|
||||
|
||||
if unit.ActiveState != "active" {
|
||||
} else if unit.ActiveState != "active" {
|
||||
t.Fatalf("Test unit not active")
|
||||
}
|
||||
|
||||
@@ -302,18 +472,57 @@ func TestStartStopTransientUnit(t *testing.T) {
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
|
||||
unit = nil
|
||||
for _, u := range units {
|
||||
if u.Name == target {
|
||||
unit = &u
|
||||
}
|
||||
}
|
||||
unit = getUnitStatus(units, target)
|
||||
|
||||
if unit != nil {
|
||||
t.Fatalf("Test unit found in list, should be stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that putting running programs into scopes works
|
||||
func TestStartStopTransientScope(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
cmd := exec.Command("/bin/sleep", "400")
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
props := []Property{
|
||||
PropPids(uint32(cmd.Process.Pid)),
|
||||
}
|
||||
target := fmt.Sprintf("testing-transient-%d.scope", cmd.Process.Pid)
|
||||
|
||||
// Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err = conn.StartTransientUnit(target, "replace", props, reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
|
||||
unit := getUnitStatus(units, target)
|
||||
|
||||
if unit == nil {
|
||||
t.Fatalf("Test unit not found in list")
|
||||
} else if unit.ActiveState != "active" {
|
||||
t.Fatalf("Test unit not active")
|
||||
}
|
||||
|
||||
// maybe check if pid is really a member of the just created scope
|
||||
// systemd uses the following api which does not use dbus, but directly
|
||||
// accesses procfs for cgroup information.
|
||||
// int sd_pid_get_unit(pid_t pid, char **session)
|
||||
}
|
||||
|
||||
func TestConnJobListener(t *testing.T) {
|
||||
target := "start-stop.service"
|
||||
conn := setupConn(t)
|
||||
@@ -343,3 +552,56 @@ func TestConnJobListener(t *testing.T) {
|
||||
t.Fatal("JobListener jobs leaked")
|
||||
}
|
||||
}
|
||||
|
||||
// Enables a unit and then masks/unmasks it
|
||||
func TestMaskUnmask(t *testing.T) {
|
||||
target := "mask-unmask.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
abs := findFixture(target, t)
|
||||
runPath := filepath.Join("/run/systemd/system/", target)
|
||||
|
||||
// 1. Enable the unit
|
||||
install, changes, err := conn.EnableUnitFiles([]string{abs}, true, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if install != false {
|
||||
t.Log("Install was true")
|
||||
}
|
||||
|
||||
if len(changes) < 1 {
|
||||
t.Fatalf("Expected one change, got %v", changes)
|
||||
}
|
||||
|
||||
if changes[0].Filename != runPath {
|
||||
t.Fatal("Unexpected target filename")
|
||||
}
|
||||
|
||||
// 2. Mask the unit
|
||||
mChanges, err := conn.MaskUnitFiles([]string{target}, true, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if mChanges[0].Filename != runPath {
|
||||
t.Fatalf("Change should include correct filename, %+v", mChanges[0])
|
||||
}
|
||||
if mChanges[0].Destination != "" {
|
||||
t.Fatalf("Change destination should be empty, %+v", mChanges[0])
|
||||
}
|
||||
|
||||
// 3. Unmask the unit
|
||||
uChanges, err := conn.UnmaskUnitFiles([]string{target}, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if uChanges[0].Filename != runPath {
|
||||
t.Fatalf("Change should include correct filename, %+v", uChanges[0])
|
||||
}
|
||||
if uChanges[0].Destination != "" {
|
||||
t.Fatalf("Change destination should be empty, %+v", uChanges[0])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
10
vendor/github.com/coreos/go-systemd/dbus/properties.go
generated
vendored
10
vendor/github.com/coreos/go-systemd/dbus/properties.go
generated
vendored
@@ -216,3 +216,13 @@ func PropSlice(slice string) Property {
|
||||
Value: dbus.MakeVariant(slice),
|
||||
}
|
||||
}
|
||||
|
||||
// PropPids sets the PIDs field of scope units used in the initial construction
|
||||
// of the scope only and specifies the initial PIDs to add to the scope object.
|
||||
// See https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/#properties
|
||||
func PropPids(pids ...uint32) Property {
|
||||
return Property{
|
||||
Name: "PIDs",
|
||||
Value: dbus.MakeVariant(pids),
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/go-systemd/examples/activation/activation.go
generated
vendored
2
vendor/github.com/coreos/go-systemd/examples/activation/activation.go
generated
vendored
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Activation example used by the activation unit tests.
|
||||
package main
|
||||
|
||||
|
||||
2
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/httpserver.go
generated
vendored
2
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/httpserver.go
generated
vendored
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
2
vendor/github.com/coreos/go-systemd/examples/activation/listen.go
generated
vendored
2
vendor/github.com/coreos/go-systemd/examples/activation/listen.go
generated
vendored
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Activation example used by the activation unit tests.
|
||||
package main
|
||||
|
||||
|
||||
2
vendor/github.com/coreos/go-systemd/examples/activation/udpconn.go
generated
vendored
2
vendor/github.com/coreos/go-systemd/examples/activation/udpconn.go
generated
vendored
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Activation example used by the activation unit tests.
|
||||
package main
|
||||
|
||||
|
||||
5
vendor/github.com/coreos/go-systemd/fixtures/mask-unmask.service
generated
vendored
Normal file
5
vendor/github.com/coreos/go-systemd/fixtures/mask-unmask.service
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
[Unit]
|
||||
Description=mask unmask test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sleep 400
|
||||
66
vendor/github.com/coreos/go-systemd/sdjournal/functions.go
generated
vendored
Normal file
66
vendor/github.com/coreos/go-systemd/sdjournal/functions.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2015 RedHat, Inc.
|
||||
// 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 sdjournal
|
||||
|
||||
import (
|
||||
"github.com/coreos/pkg/dlopen"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
// lazy initialized
|
||||
libsystemdHandle *dlopen.LibHandle
|
||||
|
||||
libsystemdMutex = &sync.Mutex{}
|
||||
libsystemdFunctions = map[string]unsafe.Pointer{}
|
||||
libsystemdNames = []string{
|
||||
// systemd < 209
|
||||
"libsystemd-journal.so.0",
|
||||
"libsystemd-journal.so",
|
||||
|
||||
// systemd >= 209 merged libsystemd-journal into libsystemd proper
|
||||
"libsystemd.so.0",
|
||||
"libsystemd.so",
|
||||
}
|
||||
)
|
||||
|
||||
func getFunction(name string) (unsafe.Pointer, error) {
|
||||
libsystemdMutex.Lock()
|
||||
defer libsystemdMutex.Unlock()
|
||||
|
||||
if libsystemdHandle == nil {
|
||||
h, err := dlopen.GetHandle(libsystemdNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
libsystemdHandle = h
|
||||
}
|
||||
|
||||
f, ok := libsystemdFunctions[name]
|
||||
if !ok {
|
||||
var err error
|
||||
f, err = libsystemdHandle.GetSymbolPointer(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
libsystemdFunctions[name] = f
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
36
vendor/github.com/coreos/go-systemd/sdjournal/functions_test.go
generated
vendored
Normal file
36
vendor/github.com/coreos/go-systemd/sdjournal/functions_test.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2015 RedHat, Inc.
|
||||
// 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 sdjournal
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetFunction(t *testing.T) {
|
||||
f, err := getFunction("sd_journal_open")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error getting an existing function: %s", err)
|
||||
}
|
||||
|
||||
if f == nil {
|
||||
t.Error("Got nil function pointer")
|
||||
}
|
||||
|
||||
_, err = getFunction("non_existent_function")
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected to get an error, got nil")
|
||||
}
|
||||
}
|
||||
703
vendor/github.com/coreos/go-systemd/sdjournal/journal.go
generated
vendored
703
vendor/github.com/coreos/go-systemd/sdjournal/journal.go
generated
vendored
@@ -24,18 +24,244 @@
|
||||
// [1] http://www.freedesktop.org/software/systemd/man/sd-journal.html
|
||||
package sdjournal
|
||||
|
||||
/*
|
||||
#cgo pkg-config: libsystemd
|
||||
#include <systemd/sd-journal.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
*/
|
||||
// #include <systemd/sd-journal.h>
|
||||
// #include <systemd/sd-id128.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <syslog.h>
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_open(void *f, sd_journal **ret, int flags)
|
||||
// {
|
||||
// int (*sd_journal_open)(sd_journal **, int);
|
||||
//
|
||||
// sd_journal_open = f;
|
||||
// return sd_journal_open(ret, flags);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_open_directory(void *f, sd_journal **ret, const char *path, int flags)
|
||||
// {
|
||||
// int (*sd_journal_open_directory)(sd_journal **, const char *, int);
|
||||
//
|
||||
// sd_journal_open_directory = f;
|
||||
// return sd_journal_open_directory(ret, path, flags);
|
||||
// }
|
||||
//
|
||||
// void
|
||||
// my_sd_journal_close(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_close)(sd_journal *);
|
||||
//
|
||||
// sd_journal_close = f;
|
||||
// sd_journal_close(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_get_usage(void *f, sd_journal *j, uint64_t *bytes)
|
||||
// {
|
||||
// int (*sd_journal_get_usage)(sd_journal *, uint64_t *);
|
||||
//
|
||||
// sd_journal_get_usage = f;
|
||||
// return sd_journal_get_usage(j, bytes);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_add_match(void *f, sd_journal *j, const void *data, size_t size)
|
||||
// {
|
||||
// int (*sd_journal_add_match)(sd_journal *, const void *, size_t);
|
||||
//
|
||||
// sd_journal_add_match = f;
|
||||
// return sd_journal_add_match(j, data, size);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_add_disjunction(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_add_disjunction)(sd_journal *);
|
||||
//
|
||||
// sd_journal_add_disjunction = f;
|
||||
// return sd_journal_add_disjunction(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_add_conjunction(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_add_conjunction)(sd_journal *);
|
||||
//
|
||||
// sd_journal_add_conjunction = f;
|
||||
// return sd_journal_add_conjunction(j);
|
||||
// }
|
||||
//
|
||||
// void
|
||||
// my_sd_journal_flush_matches(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_flush_matches)(sd_journal *);
|
||||
//
|
||||
// sd_journal_flush_matches = f;
|
||||
// sd_journal_flush_matches(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_next(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_next)(sd_journal *);
|
||||
//
|
||||
// sd_journal_next = f;
|
||||
// return sd_journal_next(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_next_skip(void *f, sd_journal *j, uint64_t skip)
|
||||
// {
|
||||
// int (*sd_journal_next_skip)(sd_journal *, uint64_t);
|
||||
//
|
||||
// sd_journal_next_skip = f;
|
||||
// return sd_journal_next_skip(j, skip);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_previous(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_previous)(sd_journal *);
|
||||
//
|
||||
// sd_journal_previous = f;
|
||||
// return sd_journal_previous(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_previous_skip(void *f, sd_journal *j, uint64_t skip)
|
||||
// {
|
||||
// int (*sd_journal_previous_skip)(sd_journal *, uint64_t);
|
||||
//
|
||||
// sd_journal_previous_skip = f;
|
||||
// return sd_journal_previous_skip(j, skip);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_get_data(void *f, sd_journal *j, const char *field, const void **data, size_t *length)
|
||||
// {
|
||||
// int (*sd_journal_get_data)(sd_journal *, const char *, const void **, size_t *);
|
||||
//
|
||||
// sd_journal_get_data = f;
|
||||
// return sd_journal_get_data(j, field, data, length);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_set_data_threshold(void *f, sd_journal *j, size_t sz)
|
||||
// {
|
||||
// int (*sd_journal_set_data_threshold)(sd_journal *, size_t);
|
||||
//
|
||||
// sd_journal_set_data_threshold = f;
|
||||
// return sd_journal_set_data_threshold(j, sz);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_get_cursor(void *f, sd_journal *j, char **cursor)
|
||||
// {
|
||||
// int (*sd_journal_get_cursor)(sd_journal *, char **);
|
||||
//
|
||||
// sd_journal_get_cursor = f;
|
||||
// return sd_journal_get_cursor(j, cursor);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_test_cursor(void *f, sd_journal *j, const char *cursor)
|
||||
// {
|
||||
// int (*sd_journal_test_cursor)(sd_journal *, const char *);
|
||||
//
|
||||
// sd_journal_test_cursor = f;
|
||||
// return sd_journal_test_cursor(j, cursor);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_get_realtime_usec(void *f, sd_journal *j, uint64_t *usec)
|
||||
// {
|
||||
// int (*sd_journal_get_realtime_usec)(sd_journal *, uint64_t *);
|
||||
//
|
||||
// sd_journal_get_realtime_usec = f;
|
||||
// return sd_journal_get_realtime_usec(j, usec);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_get_monotonic_usec(void *f, sd_journal *j, uint64_t *usec, sd_id128_t *boot_id)
|
||||
// {
|
||||
// int (*sd_journal_get_monotonic_usec)(sd_journal *, uint64_t *, sd_id128_t *);
|
||||
//
|
||||
// sd_journal_get_monotonic_usec = f;
|
||||
// return sd_journal_get_monotonic_usec(j, usec, boot_id);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_seek_head(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_seek_head)(sd_journal *);
|
||||
//
|
||||
// sd_journal_seek_head = f;
|
||||
// return sd_journal_seek_head(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_seek_tail(void *f, sd_journal *j)
|
||||
// {
|
||||
// int (*sd_journal_seek_tail)(sd_journal *);
|
||||
//
|
||||
// sd_journal_seek_tail = f;
|
||||
// return sd_journal_seek_tail(j);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_seek_cursor(void *f, sd_journal *j, const char *cursor)
|
||||
// {
|
||||
// int (*sd_journal_seek_cursor)(sd_journal *, const char *);
|
||||
//
|
||||
// sd_journal_seek_cursor = f;
|
||||
// return sd_journal_seek_cursor(j, cursor);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_seek_realtime_usec(void *f, sd_journal *j, uint64_t usec)
|
||||
// {
|
||||
// int (*sd_journal_seek_realtime_usec)(sd_journal *, uint64_t);
|
||||
//
|
||||
// sd_journal_seek_realtime_usec = f;
|
||||
// return sd_journal_seek_realtime_usec(j, usec);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_wait(void *f, sd_journal *j, uint64_t timeout_usec)
|
||||
// {
|
||||
// int (*sd_journal_wait)(sd_journal *, uint64_t);
|
||||
//
|
||||
// sd_journal_wait = f;
|
||||
// return sd_journal_wait(j, timeout_usec);
|
||||
// }
|
||||
//
|
||||
// void
|
||||
// my_sd_journal_restart_data(void *f, sd_journal *j)
|
||||
// {
|
||||
// void (*sd_journal_restart_data)(sd_journal *);
|
||||
//
|
||||
// sd_journal_restart_data = f;
|
||||
// sd_journal_restart_data(j);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_journal_enumerate_data(void *f, sd_journal *j, const void **data, size_t *length)
|
||||
// {
|
||||
// int (*sd_journal_enumerate_data)(sd_journal *, const void **, size_t *);
|
||||
//
|
||||
// sd_journal_enumerate_data = f;
|
||||
// return sd_journal_enumerate_data(j, data, length);
|
||||
// }
|
||||
//
|
||||
import "C"
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -43,13 +269,45 @@ import (
|
||||
// Journal entry field strings which correspond to:
|
||||
// http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html
|
||||
const (
|
||||
SD_JOURNAL_FIELD_SYSTEMD_UNIT = "_SYSTEMD_UNIT"
|
||||
SD_JOURNAL_FIELD_MESSAGE = "MESSAGE"
|
||||
SD_JOURNAL_FIELD_PID = "_PID"
|
||||
SD_JOURNAL_FIELD_UID = "_UID"
|
||||
SD_JOURNAL_FIELD_GID = "_GID"
|
||||
SD_JOURNAL_FIELD_HOSTNAME = "_HOSTNAME"
|
||||
SD_JOURNAL_FIELD_MACHINE_ID = "_MACHINE_ID"
|
||||
// User Journal Fields
|
||||
SD_JOURNAL_FIELD_MESSAGE = "MESSAGE"
|
||||
SD_JOURNAL_FIELD_MESSAGE_ID = "MESSAGE_ID"
|
||||
SD_JOURNAL_FIELD_PRIORITY = "PRIORITY"
|
||||
SD_JOURNAL_FIELD_CODE_FILE = "CODE_FILE"
|
||||
SD_JOURNAL_FIELD_CODE_LINE = "CODE_LINE"
|
||||
SD_JOURNAL_FIELD_CODE_FUNC = "CODE_FUNC"
|
||||
SD_JOURNAL_FIELD_ERRNO = "ERRNO"
|
||||
SD_JOURNAL_FIELD_SYSLOG_FACILITY = "SYSLOG_FACILITY"
|
||||
SD_JOURNAL_FIELD_SYSLOG_IDENTIFIER = "SYSLOG_IDENTIFIER"
|
||||
SD_JOURNAL_FIELD_SYSLOG_PID = "SYSLOG_PID"
|
||||
|
||||
// Trusted Journal Fields
|
||||
SD_JOURNAL_FIELD_PID = "_PID"
|
||||
SD_JOURNAL_FIELD_UID = "_UID"
|
||||
SD_JOURNAL_FIELD_GID = "_GID"
|
||||
SD_JOURNAL_FIELD_COMM = "_COMM"
|
||||
SD_JOURNAL_FIELD_EXE = "_EXE"
|
||||
SD_JOURNAL_FIELD_CMDLINE = "_CMDLINE"
|
||||
SD_JOURNAL_FIELD_CAP_EFFECTIVE = "_CAP_EFFECTIVE"
|
||||
SD_JOURNAL_FIELD_AUDIT_SESSION = "_AUDIT_SESSION"
|
||||
SD_JOURNAL_FIELD_AUDIT_LOGINUID = "_AUDIT_LOGINUID"
|
||||
SD_JOURNAL_FIELD_SYSTEMD_CGROUP = "_SYSTEMD_CGROUP"
|
||||
SD_JOURNAL_FIELD_SYSTEMD_SESSION = "_SYSTEMD_SESSION"
|
||||
SD_JOURNAL_FIELD_SYSTEMD_UNIT = "_SYSTEMD_UNIT"
|
||||
SD_JOURNAL_FIELD_SYSTEMD_USER_UNIT = "_SYSTEMD_USER_UNIT"
|
||||
SD_JOURNAL_FIELD_SYSTEMD_OWNER_UID = "_SYSTEMD_OWNER_UID"
|
||||
SD_JOURNAL_FIELD_SYSTEMD_SLICE = "_SYSTEMD_SLICE"
|
||||
SD_JOURNAL_FIELD_SELINUX_CONTEXT = "_SELINUX_CONTEXT"
|
||||
SD_JOURNAL_FIELD_SOURCE_REALTIME_TIMESTAMP = "_SOURCE_REALTIME_TIMESTAMP"
|
||||
SD_JOURNAL_FIELD_BOOT_ID = "_BOOT_ID"
|
||||
SD_JOURNAL_FIELD_MACHINE_ID = "_MACHINE_ID"
|
||||
SD_JOURNAL_FIELD_HOSTNAME = "_HOSTNAME"
|
||||
SD_JOURNAL_FIELD_TRANSPORT = "_TRANSPORT"
|
||||
|
||||
// Address Fields
|
||||
SD_JOURNAL_FIELD_CURSOR = "__CURSOR"
|
||||
SD_JOURNAL_FIELD_REALTIME_TIMESTAMP = "__REALTIME_TIMESTAMP"
|
||||
SD_JOURNAL_FIELD_MONOTONIC_TIMESTAMP = "__MONOTONIC_TIMESTAMP"
|
||||
)
|
||||
|
||||
// Journal event constants
|
||||
@@ -73,6 +331,14 @@ type Journal struct {
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// JournalEntry represents all fields of a journal entry plus address fields.
|
||||
type JournalEntry struct {
|
||||
Fields map[string]string
|
||||
Cursor string
|
||||
RealtimeTimestamp uint64
|
||||
MonotonicTimestamp uint64
|
||||
}
|
||||
|
||||
// Match is a convenience wrapper to describe filters supplied to AddMatch.
|
||||
type Match struct {
|
||||
Field string
|
||||
@@ -85,12 +351,18 @@ func (m *Match) String() string {
|
||||
}
|
||||
|
||||
// NewJournal returns a new Journal instance pointing to the local journal
|
||||
func NewJournal() (*Journal, error) {
|
||||
j := &Journal{}
|
||||
r := C.sd_journal_open(&j.cjournal, C.SD_JOURNAL_LOCAL_ONLY)
|
||||
func NewJournal() (j *Journal, err error) {
|
||||
j = &Journal{}
|
||||
|
||||
sd_journal_open, err := getFunction("sd_journal_open")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := C.my_sd_journal_open(sd_journal_open, &j.cjournal, C.SD_JOURNAL_LOCAL_ONLY)
|
||||
|
||||
if r < 0 {
|
||||
return nil, fmt.Errorf("failed to open journal: %d", r)
|
||||
return nil, fmt.Errorf("failed to open journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return j, nil
|
||||
@@ -99,8 +371,10 @@ func NewJournal() (*Journal, error) {
|
||||
// NewJournalFromDir returns a new Journal instance pointing to a journal residing
|
||||
// in a given directory. The supplied path may be relative or absolute; if
|
||||
// relative, it will be converted to an absolute path before being opened.
|
||||
func NewJournalFromDir(path string) (*Journal, error) {
|
||||
path, err := filepath.Abs(path)
|
||||
func NewJournalFromDir(path string) (j *Journal, err error) {
|
||||
j = &Journal{}
|
||||
|
||||
sd_journal_open_directory, err := getFunction("sd_journal_open_directory")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,10 +382,9 @@ func NewJournalFromDir(path string) (*Journal, error) {
|
||||
p := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(p))
|
||||
|
||||
j := &Journal{}
|
||||
r := C.sd_journal_open_directory(&j.cjournal, p, 0)
|
||||
r := C.my_sd_journal_open_directory(sd_journal_open_directory, &j.cjournal, p, 0)
|
||||
if r < 0 {
|
||||
return nil, fmt.Errorf("failed to open journal in directory %q: %d", path, r)
|
||||
return nil, fmt.Errorf("failed to open journal in directory %q: %d", path, syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return j, nil
|
||||
@@ -119,8 +392,13 @@ func NewJournalFromDir(path string) (*Journal, error) {
|
||||
|
||||
// Close closes a journal opened with NewJournal.
|
||||
func (j *Journal) Close() error {
|
||||
sd_journal_close, err := getFunction("sd_journal_close")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
C.sd_journal_close(j.cjournal)
|
||||
C.my_sd_journal_close(sd_journal_close, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
return nil
|
||||
@@ -128,15 +406,20 @@ func (j *Journal) Close() error {
|
||||
|
||||
// AddMatch adds a match by which to filter the entries of the journal.
|
||||
func (j *Journal) AddMatch(match string) error {
|
||||
sd_journal_add_match, err := getFunction("sd_journal_add_match")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := C.CString(match)
|
||||
defer C.free(unsafe.Pointer(m))
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_add_match(j.cjournal, unsafe.Pointer(m), C.size_t(len(match)))
|
||||
r := C.my_sd_journal_add_match(sd_journal_add_match, j.cjournal, unsafe.Pointer(m), C.size_t(len(match)))
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to add match: %d", r)
|
||||
return fmt.Errorf("failed to add match: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -144,12 +427,17 @@ func (j *Journal) AddMatch(match string) error {
|
||||
|
||||
// AddDisjunction inserts a logical OR in the match list.
|
||||
func (j *Journal) AddDisjunction() error {
|
||||
sd_journal_add_disjunction, err := getFunction("sd_journal_add_disjunction")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_add_disjunction(j.cjournal)
|
||||
r := C.my_sd_journal_add_disjunction(sd_journal_add_disjunction, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to add a disjunction in the match list: %d", r)
|
||||
return fmt.Errorf("failed to add a disjunction in the match list: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -157,12 +445,17 @@ func (j *Journal) AddDisjunction() error {
|
||||
|
||||
// AddConjunction inserts a logical AND in the match list.
|
||||
func (j *Journal) AddConjunction() error {
|
||||
sd_journal_add_conjunction, err := getFunction("sd_journal_add_conjunction")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_add_conjunction(j.cjournal)
|
||||
r := C.my_sd_journal_add_conjunction(sd_journal_add_conjunction, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to add a conjunction in the match list: %d", r)
|
||||
return fmt.Errorf("failed to add a conjunction in the match list: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -170,19 +463,29 @@ func (j *Journal) AddConjunction() error {
|
||||
|
||||
// FlushMatches flushes all matches, disjunctions and conjunctions.
|
||||
func (j *Journal) FlushMatches() {
|
||||
sd_journal_flush_matches, err := getFunction("sd_journal_flush_matches")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
C.sd_journal_flush_matches(j.cjournal)
|
||||
C.my_sd_journal_flush_matches(sd_journal_flush_matches, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
}
|
||||
|
||||
// Next advances the read pointer into the journal by one entry.
|
||||
func (j *Journal) Next() (int, error) {
|
||||
sd_journal_next, err := getFunction("sd_journal_next")
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_next(j.cjournal)
|
||||
r := C.my_sd_journal_next(sd_journal_next, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return int(r), fmt.Errorf("failed to iterate journal: %d", r)
|
||||
return int(r), fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return int(r), nil
|
||||
@@ -191,12 +494,17 @@ func (j *Journal) Next() (int, error) {
|
||||
// NextSkip advances the read pointer by multiple entries at once,
|
||||
// as specified by the skip parameter.
|
||||
func (j *Journal) NextSkip(skip uint64) (uint64, error) {
|
||||
sd_journal_next_skip, err := getFunction("sd_journal_next_skip")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_next_skip(j.cjournal, C.uint64_t(skip))
|
||||
r := C.my_sd_journal_next_skip(sd_journal_next_skip, j.cjournal, C.uint64_t(skip))
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return uint64(r), fmt.Errorf("failed to iterate journal: %d", r)
|
||||
return uint64(r), fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return uint64(r), nil
|
||||
@@ -204,12 +512,17 @@ func (j *Journal) NextSkip(skip uint64) (uint64, error) {
|
||||
|
||||
// Previous sets the read pointer into the journal back by one entry.
|
||||
func (j *Journal) Previous() (uint64, error) {
|
||||
sd_journal_previous, err := getFunction("sd_journal_previous")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_previous(j.cjournal)
|
||||
r := C.my_sd_journal_previous(sd_journal_previous, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return uint64(r), fmt.Errorf("failed to iterate journal: %d", r)
|
||||
return uint64(r), fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return uint64(r), nil
|
||||
@@ -218,20 +531,28 @@ func (j *Journal) Previous() (uint64, error) {
|
||||
// PreviousSkip sets back the read pointer by multiple entries at once,
|
||||
// as specified by the skip parameter.
|
||||
func (j *Journal) PreviousSkip(skip uint64) (uint64, error) {
|
||||
sd_journal_previous_skip, err := getFunction("sd_journal_previous_skip")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_previous_skip(j.cjournal, C.uint64_t(skip))
|
||||
r := C.my_sd_journal_previous_skip(sd_journal_previous_skip, j.cjournal, C.uint64_t(skip))
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return uint64(r), fmt.Errorf("failed to iterate journal: %d", r)
|
||||
return uint64(r), fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return uint64(r), nil
|
||||
}
|
||||
|
||||
// GetData gets the data object associated with a specific field from the
|
||||
// current journal entry.
|
||||
func (j *Journal) GetData(field string) (string, error) {
|
||||
func (j *Journal) getData(field string) (unsafe.Pointer, C.int, error) {
|
||||
sd_journal_get_data, err := getFunction("sd_journal_get_data")
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
f := C.CString(field)
|
||||
defer C.free(unsafe.Pointer(f))
|
||||
|
||||
@@ -239,16 +560,25 @@ func (j *Journal) GetData(field string) (string, error) {
|
||||
var l C.size_t
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_get_data(j.cjournal, f, &d, &l)
|
||||
r := C.my_sd_journal_get_data(sd_journal_get_data, j.cjournal, f, &d, &l)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return "", fmt.Errorf("failed to read message: %d", r)
|
||||
return nil, 0, fmt.Errorf("failed to read message: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
msg := C.GoStringN((*C.char)(d), C.int(l))
|
||||
return d, C.int(l), nil
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
// GetData gets the data object associated with a specific field from the
|
||||
// current journal entry.
|
||||
func (j *Journal) GetData(field string) (string, error) {
|
||||
d, l, err := j.getData(field)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return C.GoStringN((*C.char)(d), l), nil
|
||||
}
|
||||
|
||||
// GetDataValue gets the data object associated with a specific field from the
|
||||
@@ -258,20 +588,138 @@ func (j *Journal) GetDataValue(field string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.SplitN(val, "=", 2)[1], nil
|
||||
}
|
||||
|
||||
// GetDataBytes gets the data object associated with a specific field from the
|
||||
// current journal entry.
|
||||
func (j *Journal) GetDataBytes(field string) ([]byte, error) {
|
||||
d, l, err := j.getData(field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return C.GoBytes(d, l), nil
|
||||
}
|
||||
|
||||
// GetDataValueBytes gets the data object associated with a specific field from the
|
||||
// current journal entry, returning only the value of the object.
|
||||
func (j *Journal) GetDataValueBytes(field string) ([]byte, error) {
|
||||
val, err := j.GetDataBytes(field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.SplitN(val, []byte("="), 2)[1], nil
|
||||
}
|
||||
|
||||
// GetEntry returns a full representation of a journal entry with
|
||||
// all key-value pairs of data as well as address fields (cursor, realtime
|
||||
// timestamp and monotonic timestamp)
|
||||
func (j *Journal) GetEntry() (*JournalEntry, error) {
|
||||
sd_journal_get_realtime_usec, err := getFunction("sd_journal_get_realtime_usec")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sd_journal_get_monotonic_usec, err := getFunction("sd_journal_get_monotonic_usec")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sd_journal_get_cursor, err := getFunction("sd_journal_get_cursor")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sd_journal_restart_data, err := getFunction("sd_journal_restart_data")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sd_journal_enumerate_data, err := getFunction("sd_journal_enumerate_data")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
defer j.mu.Unlock()
|
||||
|
||||
var r C.int
|
||||
entry := &JournalEntry{Fields: make(map[string]string)}
|
||||
|
||||
var realtimeUsec C.uint64_t
|
||||
r = C.my_sd_journal_get_realtime_usec(sd_journal_get_realtime_usec, j.cjournal, &realtimeUsec)
|
||||
if r < 0 {
|
||||
return nil, fmt.Errorf("failed to get realtime timestamp: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
entry.RealtimeTimestamp = uint64(realtimeUsec)
|
||||
|
||||
var monotonicUsec C.uint64_t
|
||||
var boot_id C.sd_id128_t
|
||||
|
||||
r = C.my_sd_journal_get_monotonic_usec(sd_journal_get_monotonic_usec, j.cjournal, &monotonicUsec, &boot_id)
|
||||
if r < 0 {
|
||||
return nil, fmt.Errorf("failed to get monotonic timestamp: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
entry.MonotonicTimestamp = uint64(monotonicUsec)
|
||||
|
||||
var c *C.char
|
||||
// since the pointer is mutated by sd_journal_get_cursor, need to wait
|
||||
// until after the call to free the memory
|
||||
r = C.my_sd_journal_get_cursor(sd_journal_get_cursor, j.cjournal, &c)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
if r < 0 {
|
||||
return nil, fmt.Errorf("failed to get cursor: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
entry.Cursor = C.GoString(c)
|
||||
|
||||
// Implements the JOURNAL_FOREACH_DATA_RETVAL macro from journal-internal.h
|
||||
var d unsafe.Pointer
|
||||
var l C.size_t
|
||||
C.my_sd_journal_restart_data(sd_journal_restart_data, j.cjournal)
|
||||
for {
|
||||
r = C.my_sd_journal_enumerate_data(sd_journal_enumerate_data, j.cjournal, &d, &l)
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if r < 0 {
|
||||
return nil, fmt.Errorf("failed to read message field: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
msg := C.GoStringN((*C.char)(d), C.int(l))
|
||||
kv := strings.SplitN(msg, "=", 2)
|
||||
if len(kv) < 2 {
|
||||
return nil, fmt.Errorf("failed to parse field")
|
||||
}
|
||||
|
||||
entry.Fields[kv[0]] = kv[1]
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// SetDataThresold sets the data field size threshold for data returned by
|
||||
// GetData. To retrieve the complete data fields this threshold should be
|
||||
// turned off by setting it to 0, so that the library always returns the
|
||||
// complete data objects.
|
||||
func (j *Journal) SetDataThreshold(threshold uint64) error {
|
||||
sd_journal_set_data_threshold, err := getFunction("sd_journal_set_data_threshold")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_set_data_threshold(j.cjournal, C.size_t(threshold))
|
||||
r := C.my_sd_journal_set_data_threshold(sd_journal_set_data_threshold, j.cjournal, C.size_t(threshold))
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to set data threshold: %d", r)
|
||||
return fmt.Errorf("failed to set data threshold: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -282,26 +730,123 @@ func (j *Journal) SetDataThreshold(threshold uint64) error {
|
||||
func (j *Journal) GetRealtimeUsec() (uint64, error) {
|
||||
var usec C.uint64_t
|
||||
|
||||
sd_journal_get_realtime_usec, err := getFunction("sd_journal_get_realtime_usec")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_get_realtime_usec(j.cjournal, &usec)
|
||||
r := C.my_sd_journal_get_realtime_usec(sd_journal_get_realtime_usec, j.cjournal, &usec)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return 0, fmt.Errorf("error getting timestamp for entry: %d", r)
|
||||
return 0, fmt.Errorf("failed to get realtime timestamp: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return uint64(usec), nil
|
||||
}
|
||||
|
||||
// SeekTail may be used to seek to the end of the journal, i.e. the most recent
|
||||
// available entry.
|
||||
func (j *Journal) SeekTail() error {
|
||||
// GetMonotonicUsec gets the monotonic timestamp of the current journal entry.
|
||||
func (j *Journal) GetMonotonicUsec() (uint64, error) {
|
||||
var usec C.uint64_t
|
||||
var boot_id C.sd_id128_t
|
||||
|
||||
sd_journal_get_monotonic_usec, err := getFunction("sd_journal_get_monotonic_usec")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_seek_tail(j.cjournal)
|
||||
r := C.my_sd_journal_get_monotonic_usec(sd_journal_get_monotonic_usec, j.cjournal, &usec, &boot_id)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to seek to tail of journal: %d", r)
|
||||
return 0, fmt.Errorf("failed to get monotonic timestamp: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return uint64(usec), nil
|
||||
}
|
||||
|
||||
// GetCursor gets the cursor of the current journal entry.
|
||||
func (j *Journal) GetCursor() (string, error) {
|
||||
sd_journal_get_cursor, err := getFunction("sd_journal_get_cursor")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var d *C.char
|
||||
// since the pointer is mutated by sd_journal_get_cursor, need to wait
|
||||
// until after the call to free the memory
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.my_sd_journal_get_cursor(sd_journal_get_cursor, j.cjournal, &d)
|
||||
j.mu.Unlock()
|
||||
defer C.free(unsafe.Pointer(d))
|
||||
|
||||
if r < 0 {
|
||||
return "", fmt.Errorf("failed to get cursor: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
cursor := C.GoString(d)
|
||||
|
||||
return cursor, nil
|
||||
}
|
||||
|
||||
// TestCursor checks whether the current position in the journal matches the
|
||||
// specified cursor
|
||||
func (j *Journal) TestCursor(cursor string) error {
|
||||
sd_journal_test_cursor, err := getFunction("sd_journal_test_cursor")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := C.CString(cursor)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.my_sd_journal_test_cursor(sd_journal_test_cursor, j.cjournal, c)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to test to cursor %q: %d", cursor, syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SeekHead seeks to the beginning of the journal, i.e. the oldest available
|
||||
// entry.
|
||||
func (j *Journal) SeekHead() error {
|
||||
sd_journal_seek_head, err := getFunction("sd_journal_seek_head")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.my_sd_journal_seek_head(sd_journal_seek_head, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to seek to head of journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SeekTail may be used to seek to the end of the journal, i.e. the most recent
|
||||
// available entry.
|
||||
func (j *Journal) SeekTail() error {
|
||||
sd_journal_seek_tail, err := getFunction("sd_journal_seek_tail")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.my_sd_journal_seek_tail(sd_journal_seek_tail, j.cjournal)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to seek to tail of journal: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -310,12 +855,38 @@ func (j *Journal) SeekTail() error {
|
||||
// SeekRealtimeUsec seeks to the entry with the specified realtime (wallclock)
|
||||
// timestamp, i.e. CLOCK_REALTIME.
|
||||
func (j *Journal) SeekRealtimeUsec(usec uint64) error {
|
||||
sd_journal_seek_realtime_usec, err := getFunction("sd_journal_seek_realtime_usec")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_seek_realtime_usec(j.cjournal, C.uint64_t(usec))
|
||||
r := C.my_sd_journal_seek_realtime_usec(sd_journal_seek_realtime_usec, j.cjournal, C.uint64_t(usec))
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to seek to %d: %d", usec, r)
|
||||
return fmt.Errorf("failed to seek to %d: %d", usec, syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SeekCursor seeks to a concrete journal cursor.
|
||||
func (j *Journal) SeekCursor(cursor string) error {
|
||||
sd_journal_seek_cursor, err := getFunction("sd_journal_seek_cursor")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := C.CString(cursor)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.my_sd_journal_seek_cursor(sd_journal_seek_cursor, j.cjournal, c)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return fmt.Errorf("failed to seek to cursor %q: %d", cursor, syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -327,6 +898,12 @@ func (j *Journal) SeekRealtimeUsec(usec uint64) error {
|
||||
// wait indefinitely for a journal change.
|
||||
func (j *Journal) Wait(timeout time.Duration) int {
|
||||
var to uint64
|
||||
|
||||
sd_journal_wait, err := getFunction("sd_journal_wait")
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
if timeout == IndefiniteWait {
|
||||
// sd_journal_wait(3) calls for a (uint64_t) -1 to be passed to signify
|
||||
// indefinite wait, but using a -1 overflows our C.uint64_t, so we use an
|
||||
@@ -336,7 +913,7 @@ func (j *Journal) Wait(timeout time.Duration) int {
|
||||
to = uint64(time.Now().Add(timeout).Unix() / 1000)
|
||||
}
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_wait(j.cjournal, C.uint64_t(to))
|
||||
r := C.my_sd_journal_wait(sd_journal_wait, j.cjournal, C.uint64_t(to))
|
||||
j.mu.Unlock()
|
||||
|
||||
return int(r)
|
||||
@@ -345,12 +922,18 @@ func (j *Journal) Wait(timeout time.Duration) int {
|
||||
// GetUsage returns the journal disk space usage, in bytes.
|
||||
func (j *Journal) GetUsage() (uint64, error) {
|
||||
var out C.uint64_t
|
||||
|
||||
sd_journal_get_usage, err := getFunction("sd_journal_get_usage")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
j.mu.Lock()
|
||||
r := C.sd_journal_get_usage(j.cjournal, &out)
|
||||
r := C.my_sd_journal_get_usage(sd_journal_get_usage, j.cjournal, &out)
|
||||
j.mu.Unlock()
|
||||
|
||||
if r < 0 {
|
||||
return 0, fmt.Errorf("failed to get journal disk space usage: %d", r)
|
||||
return 0, fmt.Errorf("failed to get journal disk space usage: %d", syscall.Errno(-r))
|
||||
}
|
||||
|
||||
return uint64(out), nil
|
||||
|
||||
257
vendor/github.com/coreos/go-systemd/sdjournal/journal_test.go
generated
vendored
Normal file → Executable file
257
vendor/github.com/coreos/go-systemd/sdjournal/journal_test.go
generated
vendored
Normal file → Executable file
@@ -16,7 +16,13 @@
|
||||
package sdjournal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -53,7 +59,7 @@ func TestJournalFollow(t *testing.T) {
|
||||
case <-done:
|
||||
return
|
||||
default:
|
||||
if err = journal.Print(journal.PriInfo, "test message %s", time.Now()); err != nil {
|
||||
if err := journal.Print(journal.PriInfo, "test message %s", time.Now()); err != nil {
|
||||
t.Fatalf("Error writing to journal: %s", err)
|
||||
}
|
||||
|
||||
@@ -88,3 +94,252 @@ func TestJournalGetUsage(t *testing.T) {
|
||||
t.Fatalf("Error getting journal size: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJournalCursorGetSeekAndTest(t *testing.T) {
|
||||
j, err := NewJournal()
|
||||
if err != nil {
|
||||
t.Fatalf("Error opening journal: %s", err)
|
||||
}
|
||||
|
||||
if j == nil {
|
||||
t.Fatal("Got a nil journal")
|
||||
}
|
||||
|
||||
defer j.Close()
|
||||
|
||||
waitAndNext := func(j *Journal) error {
|
||||
r := j.Wait(time.Duration(1) * time.Second)
|
||||
if r < 0 {
|
||||
return errors.New("Error waiting to journal")
|
||||
}
|
||||
|
||||
n, err := j.Next()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading to journal: %s", err)
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return fmt.Errorf("Error reading to journal: %s", io.EOF)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
err = journal.Print(journal.PriInfo, "test message for cursor %s", time.Now())
|
||||
if err != nil {
|
||||
t.Fatalf("Error writing to journal: %s", err)
|
||||
}
|
||||
|
||||
if err = waitAndNext(j); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
c, err := j.GetCursor()
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting cursor from journal: %s", err)
|
||||
}
|
||||
|
||||
err = j.SeekCursor(c)
|
||||
if err != nil {
|
||||
t.Fatalf("Error seeking cursor to journal: %s", err)
|
||||
}
|
||||
|
||||
if err = waitAndNext(j); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
err = j.TestCursor(c)
|
||||
if err != nil {
|
||||
t.Fatalf("Error testing cursor to journal: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewJournalFromDir(t *testing.T) {
|
||||
// test for error handling
|
||||
dir := "/ClearlyNonExistingPath/"
|
||||
j, err := NewJournalFromDir(dir)
|
||||
if err == nil {
|
||||
defer j.Close()
|
||||
t.Fatalf("Error expected when opening dummy path (%s)", dir)
|
||||
}
|
||||
// test for main code path
|
||||
dir, err = ioutil.TempDir("", "go-systemd-test")
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating tempdir: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
j, err = NewJournalFromDir(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("Error opening journal: %s", err)
|
||||
}
|
||||
if j == nil {
|
||||
t.Fatal("Got a nil journal")
|
||||
}
|
||||
j.Close()
|
||||
}
|
||||
|
||||
func setupJournalRoundtrip() (*Journal, map[string]string, error) {
|
||||
j, err := NewJournal()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error opening journal: %s", err)
|
||||
}
|
||||
|
||||
if j == nil {
|
||||
return nil, nil, fmt.Errorf("Got a nil journal")
|
||||
}
|
||||
|
||||
j.FlushMatches()
|
||||
|
||||
matchField := "TESTJOURNALENTRY"
|
||||
matchValue := fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
m := Match{Field: matchField, Value: matchValue}
|
||||
err = j.AddMatch(m.String())
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error adding matches to journal: %s", err)
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("test journal get entry message %s", time.Now())
|
||||
data := map[string]string{matchField: matchValue}
|
||||
err = journal.Send(msg, journal.PriInfo, data)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error writing to journal: %s", err)
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
|
||||
n, err := j.Next()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error reading from journal: %s", err)
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return nil, nil, fmt.Errorf("Error reading from journal: %s", io.EOF)
|
||||
}
|
||||
|
||||
data["MESSAGE"] = msg
|
||||
|
||||
return j, data, nil
|
||||
}
|
||||
|
||||
func TestJournalGetData(t *testing.T) {
|
||||
j, wantEntry, err := setupJournalRoundtrip()
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
defer j.Close()
|
||||
|
||||
for k, v := range wantEntry {
|
||||
data := fmt.Sprintf("%s=%s", k, v)
|
||||
|
||||
dataStr, err := j.GetData(k)
|
||||
if err != nil {
|
||||
t.Fatalf("GetData() error: %v", err)
|
||||
}
|
||||
|
||||
if dataStr != data {
|
||||
t.Fatalf("Invalid data for \"%s\": got %s, want %s", k, dataStr, data)
|
||||
}
|
||||
|
||||
dataBytes, err := j.GetDataBytes(k)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDataBytes() error: %v", err)
|
||||
}
|
||||
|
||||
if string(dataBytes) != data {
|
||||
t.Fatalf("Invalid data bytes for \"%s\": got %s, want %s", k, string(dataBytes), data)
|
||||
}
|
||||
|
||||
valStr, err := j.GetDataValue(k)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDataValue() error: %v", err)
|
||||
}
|
||||
|
||||
if valStr != v {
|
||||
t.Fatalf("Invalid data value for \"%s\": got %s, want %s", k, valStr, v)
|
||||
}
|
||||
|
||||
valBytes, err := j.GetDataValueBytes(k)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDataValueBytes() error: %v", err)
|
||||
}
|
||||
|
||||
if string(valBytes) != v {
|
||||
t.Fatalf("Invalid data value bytes for \"%s\": got %s, want %s", k, string(valBytes), v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJournalGetEntry(t *testing.T) {
|
||||
j, wantEntry, err := setupJournalRoundtrip()
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
defer j.Close()
|
||||
|
||||
entry, err := j.GetEntry()
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting the entry to journal: %s", err)
|
||||
}
|
||||
|
||||
for k, wantV := range wantEntry {
|
||||
gotV := entry.Fields[k]
|
||||
if gotV != wantV {
|
||||
t.Fatalf("Bad result for entry.Fields[\"%s\"]: got %s, want %s", k, gotV, wantV)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for incorrect read into small buffers,
|
||||
// see https://github.com/coreos/go-systemd/issues/172
|
||||
func TestJournalReaderSmallReadBuffer(t *testing.T) {
|
||||
// Write a long entry ...
|
||||
delim := "%%%%%%"
|
||||
longEntry := strings.Repeat("a", 256)
|
||||
matchField := "TESTJOURNALREADERSMALLBUF"
|
||||
matchValue := fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
r, err := NewJournalReader(JournalReaderConfig{
|
||||
Since: time.Duration(-15) * time.Second,
|
||||
Matches: []Match{
|
||||
{
|
||||
Field: matchField,
|
||||
Value: matchValue,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error opening journal: %s", err)
|
||||
}
|
||||
if r == nil {
|
||||
t.Fatal("Got a nil reader")
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
want := fmt.Sprintf("%slongentry %s%s", delim, longEntry, delim)
|
||||
err = journal.Send(want, journal.PriInfo, map[string]string{matchField: matchValue})
|
||||
if err != nil {
|
||||
t.Fatal("Error writing to journal", err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
||||
// ... and try to read it back piece by piece via a small buffer
|
||||
finalBuff := new(bytes.Buffer)
|
||||
var e error
|
||||
for c := -1; c != 0 && e == nil; {
|
||||
smallBuf := make([]byte, 5)
|
||||
c, e = r.Read(smallBuf)
|
||||
if c > len(smallBuf) {
|
||||
t.Fatalf("Got unexpected read length: %d vs %d", c, len(smallBuf))
|
||||
}
|
||||
_, _ = finalBuff.Write(smallBuf)
|
||||
}
|
||||
b := finalBuff.String()
|
||||
got := strings.Split(b, delim)
|
||||
if len(got) != 3 {
|
||||
t.Fatalf("Got unexpected entry %s", b)
|
||||
}
|
||||
if got[1] != strings.Trim(want, delim) {
|
||||
t.Fatalf("Got unexpected message %s", got[1])
|
||||
}
|
||||
}
|
||||
|
||||
99
vendor/github.com/coreos/go-systemd/sdjournal/read.go
generated
vendored
99
vendor/github.com/coreos/go-systemd/sdjournal/read.go
generated
vendored
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -29,10 +30,12 @@ var (
|
||||
|
||||
// JournalReaderConfig represents options to drive the behavior of a JournalReader.
|
||||
type JournalReaderConfig struct {
|
||||
// The Since and NumFromTail options are mutually exclusive and determine
|
||||
// where the reading begins within the journal.
|
||||
// The Since, NumFromTail and Cursor options are mutually exclusive and
|
||||
// determine where the reading begins within the journal. The order in which
|
||||
// options are written is exactly the order of precedence.
|
||||
Since time.Duration // start relative to a Duration from now
|
||||
NumFromTail uint64 // start relative to the tail
|
||||
Cursor string // start relative to the cursor
|
||||
|
||||
// Show only journal entries whose fields match the supplied values. If
|
||||
// the array is empty, entries will not be filtered.
|
||||
@@ -44,9 +47,10 @@ type JournalReaderConfig struct {
|
||||
}
|
||||
|
||||
// JournalReader is an io.ReadCloser which provides a simple interface for iterating through the
|
||||
// systemd journal.
|
||||
// systemd journal. A JournalReader is not safe for concurrent use by multiple goroutines.
|
||||
type JournalReader struct {
|
||||
journal *Journal
|
||||
journal *Journal
|
||||
msgReader *strings.Reader
|
||||
}
|
||||
|
||||
// NewJournalReader creates a new JournalReader with configuration options that are similar to the
|
||||
@@ -86,7 +90,20 @@ func NewJournalReader(config JournalReaderConfig) (*JournalReader, error) {
|
||||
// Move the read pointer into position near the tail. Go one further than
|
||||
// the option so that the initial cursor advancement positions us at the
|
||||
// correct starting point.
|
||||
if _, err := r.journal.PreviousSkip(config.NumFromTail + 1); err != nil {
|
||||
skip, err := r.journal.PreviousSkip(config.NumFromTail + 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If we skipped fewer lines than expected, we have reached journal start.
|
||||
// Thus, we seek to head so that next invocation can read the first line.
|
||||
if skip != config.NumFromTail+1 {
|
||||
if err := r.journal.SeekHead(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if config.Cursor != "" {
|
||||
// Start based on a custom cursor
|
||||
if err := r.journal.SeekCursor(config.Cursor); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -94,41 +111,73 @@ func NewJournalReader(config JournalReaderConfig) (*JournalReader, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Read reads entries from the journal. Read follows the Reader interface so
|
||||
// it must be able to read a specific amount of bytes. Journald on the other
|
||||
// hand only allows us to read full entries of arbitrary size (without byte
|
||||
// granularity). JournalReader is therefore internally buffering entries that
|
||||
// don't fit in the read buffer. Callers should keep calling until 0 and/or an
|
||||
// error is returned.
|
||||
func (r *JournalReader) Read(b []byte) (int, error) {
|
||||
var err error
|
||||
var c int
|
||||
|
||||
// Advance the journal cursor
|
||||
c, err = r.journal.Next()
|
||||
if r.msgReader == nil {
|
||||
var c int
|
||||
|
||||
// An unexpected error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Advance the journal cursor. It has to be called at least one time
|
||||
// before reading
|
||||
c, err = r.journal.Next()
|
||||
|
||||
// EOF detection
|
||||
if c == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
// An unexpected error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Build a message
|
||||
var msg string
|
||||
msg, err = r.buildMessage()
|
||||
// EOF detection
|
||||
if c == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
// Build a message
|
||||
var msg string
|
||||
msg, err = r.buildMessage()
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
r.msgReader = strings.NewReader(msg)
|
||||
}
|
||||
|
||||
// Copy and return the message
|
||||
copy(b, []byte(msg))
|
||||
var sz int
|
||||
sz, err = r.msgReader.Read(b)
|
||||
if err == io.EOF {
|
||||
// The current entry has been fully read. Don't propagate this
|
||||
// EOF, so the next entry can be read at the next Read()
|
||||
// iteration.
|
||||
r.msgReader = nil
|
||||
return sz, nil
|
||||
}
|
||||
if err != nil {
|
||||
return sz, err
|
||||
}
|
||||
if r.msgReader.Len() == 0 {
|
||||
r.msgReader = nil
|
||||
}
|
||||
|
||||
return len(msg), nil
|
||||
return sz, nil
|
||||
}
|
||||
|
||||
// Close closes the JournalReader's handle to the journal.
|
||||
func (r *JournalReader) Close() error {
|
||||
return r.journal.Close()
|
||||
}
|
||||
|
||||
// Rewind attempts to rewind the JournalReader to the first entry.
|
||||
func (r *JournalReader) Rewind() error {
|
||||
r.msgReader = nil
|
||||
return r.journal.SeekHead()
|
||||
}
|
||||
|
||||
// Follow synchronously follows the JournalReader, writing each new journal entry to writer. The
|
||||
// follow will continue until a single time.Time is received on the until channel.
|
||||
func (r *JournalReader) Follow(until <-chan time.Time, writer io.Writer) (err error) {
|
||||
@@ -148,7 +197,9 @@ process:
|
||||
return ErrExpired
|
||||
default:
|
||||
if c > 0 {
|
||||
writer.Write(msg[:c])
|
||||
if _, err = writer.Write(msg[:c]); err != nil {
|
||||
break process
|
||||
}
|
||||
continue process
|
||||
}
|
||||
}
|
||||
|
||||
5
vendor/github.com/coreos/go-systemd/test
generated
vendored
5
vendor/github.com/coreos/go-systemd/test
generated
vendored
@@ -24,9 +24,10 @@ if [ -z "$GOPATH" ]; then
|
||||
fi
|
||||
export GOPATH=${PWD}/gopath
|
||||
go get -u github.com/godbus/dbus
|
||||
go get -u github.com/coreos/pkg/dlopen
|
||||
fi
|
||||
|
||||
TESTABLE="activation journal login1 machine1 unit"
|
||||
TESTABLE="activation daemon journal login1 machine1 unit"
|
||||
FORMATTABLE="$TESTABLE sdjournal dbus"
|
||||
if [ -e "/run/systemd/system/" ]; then
|
||||
TESTABLE="${TESTABLE} sdjournal"
|
||||
@@ -57,7 +58,7 @@ split=(${TEST// / })
|
||||
TEST=${split[@]/#/${REPO_PATH}/}
|
||||
|
||||
echo "Running tests..."
|
||||
go test ${COVER} $@ ${TEST}
|
||||
go test -v ${COVER} $@ ${TEST}
|
||||
|
||||
echo "Checking gofmt..."
|
||||
fmtRes=$(gofmt -l $FMT)
|
||||
|
||||
200
vendor/github.com/coreos/go-systemd/util/util.go
generated
vendored
200
vendor/github.com/coreos/go-systemd/util/util.go
generated
vendored
@@ -18,133 +18,23 @@
|
||||
// than linking against them.
|
||||
package util
|
||||
|
||||
// #cgo LDFLAGS: -ldl
|
||||
// #include <stdlib.h>
|
||||
// #include <dlfcn.h>
|
||||
// #include <sys/types.h>
|
||||
// #include <unistd.h>
|
||||
//
|
||||
// int
|
||||
// my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
|
||||
// {
|
||||
// int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
|
||||
//
|
||||
// sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
|
||||
// return sd_pid_get_owner_uid(pid, uid);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_pid_get_unit(void *f, pid_t pid, char **unit)
|
||||
// {
|
||||
// int (*sd_pid_get_unit)(pid_t, char **);
|
||||
//
|
||||
// sd_pid_get_unit = (int (*)(pid_t, char **))f;
|
||||
// return sd_pid_get_unit(pid, unit);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
|
||||
// {
|
||||
// int (*sd_pid_get_slice)(pid_t, char **);
|
||||
//
|
||||
// sd_pid_get_slice = (int (*)(pid_t, char **))f;
|
||||
// return sd_pid_get_slice(pid, slice);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// am_session_leader()
|
||||
// {
|
||||
// return (getsid(0) == getpid());
|
||||
// }
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var ErrSoNotFound = errors.New("unable to open a handle to libsystemd")
|
||||
|
||||
// libHandle represents an open handle to the systemd C library
|
||||
type libHandle struct {
|
||||
handle unsafe.Pointer
|
||||
libname string
|
||||
}
|
||||
|
||||
func (h *libHandle) Close() error {
|
||||
if r := C.dlclose(h.handle); r != 0 {
|
||||
return fmt.Errorf("error closing %v: %d", h.libname, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getHandle tries to get a handle to a systemd library (.so), attempting to
|
||||
// access it by several different names and returning the first that is
|
||||
// successfully opened. Callers are responsible for closing the handler.
|
||||
// If no library can be successfully opened, an error is returned.
|
||||
func getHandle() (*libHandle, error) {
|
||||
for _, name := range []string{
|
||||
// systemd < 209
|
||||
"libsystemd-login.so",
|
||||
"libsystemd-login.so.0",
|
||||
|
||||
// systemd >= 209 merged libsystemd-login into libsystemd proper
|
||||
"libsystemd.so",
|
||||
"libsystemd.so.0",
|
||||
} {
|
||||
libname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(libname))
|
||||
handle := C.dlopen(libname, C.RTLD_LAZY)
|
||||
if handle != nil {
|
||||
h := &libHandle{
|
||||
handle: handle,
|
||||
libname: name,
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrSoNotFound
|
||||
}
|
||||
var (
|
||||
ErrNoCGO = fmt.Errorf("go-systemd built with CGO disabled")
|
||||
)
|
||||
|
||||
// GetRunningSlice attempts to retrieve the name of the systemd slice in which
|
||||
// the current process is running.
|
||||
// This function is a wrapper around the libsystemd C library; if it cannot be
|
||||
// opened, an error is returned.
|
||||
func GetRunningSlice() (slice string, err error) {
|
||||
var h *libHandle
|
||||
h, err = getHandle()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err1 := h.Close(); err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
sym := C.CString("sd_pid_get_slice")
|
||||
defer C.free(unsafe.Pointer(sym))
|
||||
sd_pid_get_slice := C.dlsym(h.handle, sym)
|
||||
if sd_pid_get_slice == nil {
|
||||
err = fmt.Errorf("error resolving sd_pid_get_slice function")
|
||||
return
|
||||
}
|
||||
|
||||
var s string
|
||||
sl := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(sl))
|
||||
|
||||
ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
|
||||
if ret < 0 {
|
||||
err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
|
||||
return
|
||||
}
|
||||
|
||||
return C.GoString(sl), nil
|
||||
func GetRunningSlice() (string, error) {
|
||||
return getRunningSlice()
|
||||
}
|
||||
|
||||
// RunningFromSystemService tries to detect whether the current process has
|
||||
@@ -162,87 +52,17 @@ func GetRunningSlice() (slice string, err error) {
|
||||
//
|
||||
// This function is a wrapper around the libsystemd C library; if this is
|
||||
// unable to successfully open a handle to the library for any reason (e.g. it
|
||||
// cannot be found), an errr will be returned
|
||||
func RunningFromSystemService() (ret bool, err error) {
|
||||
var h *libHandle
|
||||
h, err = getHandle()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err1 := h.Close(); err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
sym := C.CString("sd_pid_get_owner_uid")
|
||||
defer C.free(unsafe.Pointer(sym))
|
||||
sd_pid_get_owner_uid := C.dlsym(h.handle, sym)
|
||||
if sd_pid_get_owner_uid == nil {
|
||||
err = fmt.Errorf("error resolving sd_pid_get_owner_uid function")
|
||||
return
|
||||
}
|
||||
|
||||
var uid C.uid_t
|
||||
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
|
||||
serrno := syscall.Errno(-errno)
|
||||
// when we're running from a unit file, sd_pid_get_owner_uid returns
|
||||
// ENOENT (systemd <220) or ENXIO (systemd >=220)
|
||||
switch {
|
||||
case errno >= 0:
|
||||
ret = false
|
||||
case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
|
||||
// Since the implementation of sessions in systemd relies on
|
||||
// the `pam_systemd` module, using the sd_pid_get_owner_uid
|
||||
// heuristic alone can result in false positives if that module
|
||||
// (or PAM itself) is not present or properly configured on the
|
||||
// system. As such, we also check if we're the session leader,
|
||||
// which should be the case if we're invoked from a unit file,
|
||||
// but not if e.g. we're invoked from the command line from a
|
||||
// user's login session
|
||||
ret = C.am_session_leader() == 1
|
||||
default:
|
||||
err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
|
||||
}
|
||||
return
|
||||
// cannot be found), an error will be returned.
|
||||
func RunningFromSystemService() (bool, error) {
|
||||
return runningFromSystemService()
|
||||
}
|
||||
|
||||
// CurrentUnitName attempts to retrieve the name of the systemd system unit
|
||||
// from which the calling process has been invoked. It wraps the systemd
|
||||
// `sd_pid_get_unit` call, with the same caveat: for processes not part of a
|
||||
// systemd system unit, this function will return an error.
|
||||
func CurrentUnitName() (unit string, err error) {
|
||||
var h *libHandle
|
||||
h, err = getHandle()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err1 := h.Close(); err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
sym := C.CString("sd_pid_get_unit")
|
||||
defer C.free(unsafe.Pointer(sym))
|
||||
sd_pid_get_unit := C.dlsym(h.handle, sym)
|
||||
if sd_pid_get_unit == nil {
|
||||
err = fmt.Errorf("error resolving sd_pid_get_unit function")
|
||||
return
|
||||
}
|
||||
|
||||
var s string
|
||||
u := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(u))
|
||||
|
||||
ret := C.my_sd_pid_get_unit(sd_pid_get_unit, 0, &u)
|
||||
if ret < 0 {
|
||||
err = fmt.Errorf("error calling sd_pid_get_unit: %v", syscall.Errno(-ret))
|
||||
return
|
||||
}
|
||||
|
||||
unit = C.GoString(u)
|
||||
return
|
||||
func CurrentUnitName() (string, error) {
|
||||
return currentUnitName()
|
||||
}
|
||||
|
||||
// IsRunningSystemd checks whether the host was booted with systemd as its init
|
||||
|
||||
174
vendor/github.com/coreos/go-systemd/util/util_cgo.go
generated
vendored
Normal file
174
vendor/github.com/coreos/go-systemd/util/util_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// +build cgo
|
||||
|
||||
package util
|
||||
|
||||
// #include <stdlib.h>
|
||||
// #include <sys/types.h>
|
||||
// #include <unistd.h>
|
||||
//
|
||||
// int
|
||||
// my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
|
||||
// {
|
||||
// int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
|
||||
//
|
||||
// sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
|
||||
// return sd_pid_get_owner_uid(pid, uid);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_pid_get_unit(void *f, pid_t pid, char **unit)
|
||||
// {
|
||||
// int (*sd_pid_get_unit)(pid_t, char **);
|
||||
//
|
||||
// sd_pid_get_unit = (int (*)(pid_t, char **))f;
|
||||
// return sd_pid_get_unit(pid, unit);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
|
||||
// {
|
||||
// int (*sd_pid_get_slice)(pid_t, char **);
|
||||
//
|
||||
// sd_pid_get_slice = (int (*)(pid_t, char **))f;
|
||||
// return sd_pid_get_slice(pid, slice);
|
||||
// }
|
||||
//
|
||||
// int
|
||||
// am_session_leader()
|
||||
// {
|
||||
// return (getsid(0) == getpid());
|
||||
// }
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/coreos/pkg/dlopen"
|
||||
)
|
||||
|
||||
var libsystemdNames = []string{
|
||||
// systemd < 209
|
||||
"libsystemd-login.so.0",
|
||||
"libsystemd-login.so",
|
||||
|
||||
// systemd >= 209 merged libsystemd-login into libsystemd proper
|
||||
"libsystemd.so.0",
|
||||
"libsystemd.so",
|
||||
}
|
||||
|
||||
func getRunningSlice() (slice string, err error) {
|
||||
var h *dlopen.LibHandle
|
||||
h, err = dlopen.GetHandle(libsystemdNames)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err1 := h.Close(); err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
sd_pid_get_slice, err := h.GetSymbolPointer("sd_pid_get_slice")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var s string
|
||||
sl := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(sl))
|
||||
|
||||
ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
|
||||
if ret < 0 {
|
||||
err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
|
||||
return
|
||||
}
|
||||
|
||||
return C.GoString(sl), nil
|
||||
}
|
||||
|
||||
func runningFromSystemService() (ret bool, err error) {
|
||||
var h *dlopen.LibHandle
|
||||
h, err = dlopen.GetHandle(libsystemdNames)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err1 := h.Close(); err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
sd_pid_get_owner_uid, err := h.GetSymbolPointer("sd_pid_get_owner_uid")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var uid C.uid_t
|
||||
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
|
||||
serrno := syscall.Errno(-errno)
|
||||
// when we're running from a unit file, sd_pid_get_owner_uid returns
|
||||
// ENOENT (systemd <220) or ENXIO (systemd >=220)
|
||||
switch {
|
||||
case errno >= 0:
|
||||
ret = false
|
||||
case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
|
||||
// Since the implementation of sessions in systemd relies on
|
||||
// the `pam_systemd` module, using the sd_pid_get_owner_uid
|
||||
// heuristic alone can result in false positives if that module
|
||||
// (or PAM itself) is not present or properly configured on the
|
||||
// system. As such, we also check if we're the session leader,
|
||||
// which should be the case if we're invoked from a unit file,
|
||||
// but not if e.g. we're invoked from the command line from a
|
||||
// user's login session
|
||||
ret = C.am_session_leader() == 1
|
||||
default:
|
||||
err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func currentUnitName() (unit string, err error) {
|
||||
var h *dlopen.LibHandle
|
||||
h, err = dlopen.GetHandle(libsystemdNames)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err1 := h.Close(); err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
sd_pid_get_unit, err := h.GetSymbolPointer("sd_pid_get_unit")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var s string
|
||||
u := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(u))
|
||||
|
||||
ret := C.my_sd_pid_get_unit(sd_pid_get_unit, 0, &u)
|
||||
if ret < 0 {
|
||||
err = fmt.Errorf("error calling sd_pid_get_unit: %v", syscall.Errno(-ret))
|
||||
return
|
||||
}
|
||||
|
||||
unit = C.GoString(u)
|
||||
return
|
||||
}
|
||||
23
vendor/github.com/coreos/go-systemd/util/util_stub.go
generated
vendored
Normal file
23
vendor/github.com/coreos/go-systemd/util/util_stub.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// +build !cgo
|
||||
|
||||
package util
|
||||
|
||||
func getRunningSlice() (string, error) { return "", ErrNoCGO }
|
||||
|
||||
func runningFromSystemService() (bool, error) { return false, ErrNoCGO }
|
||||
|
||||
func currentUnitName() (string, error) { return "", ErrNoCGO }
|
||||
Reference in New Issue
Block a user