vendor: remove dep and use vndr
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
16f44674a4
commit
148e72d81e
16131 changed files with 73815 additions and 4235138 deletions
27
vendor/github.com/coreos/go-systemd/.travis.yml
generated
vendored
27
vendor/github.com/coreos/go-systemd/.travis.yml
generated
vendored
|
@ -1,27 +0,0 @@
|
|||
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:
|
||||
- docker run -d --cidfile=/tmp/cidfile --privileged -e GOPATH=${GOPATH} -v ${PWD}:${BUILD_DIR} go-systemd/container-tests /bin/systemd --system
|
||||
|
||||
script:
|
||||
- docker exec `cat /tmp/cidfile` /bin/bash -c "cd ${BUILD_DIR} && ./test"
|
||||
|
||||
after_script:
|
||||
- docker kill `cat /tmp/cidfile`
|
77
vendor/github.com/coreos/go-systemd/CONTRIBUTING.md
generated
vendored
77
vendor/github.com/coreos/go-systemd/CONTRIBUTING.md
generated
vendored
|
@ -1,77 +0,0 @@
|
|||
# How to Contribute
|
||||
|
||||
CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via
|
||||
GitHub pull requests. This document outlines some of the conventions on
|
||||
development workflow, commit message formatting, contact points and other
|
||||
resources to make it easier to get your contribution accepted.
|
||||
|
||||
# Certificate of Origin
|
||||
|
||||
By contributing to this project you agree to the Developer Certificate of
|
||||
Origin (DCO). This document was created by the Linux Kernel community and is a
|
||||
simple statement that you, as a contributor, have the legal right to make the
|
||||
contribution. See the [DCO](DCO) file for details.
|
||||
|
||||
# Email and Chat
|
||||
|
||||
The project currently uses the general CoreOS email list and IRC channel:
|
||||
- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)
|
||||
- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org
|
||||
|
||||
Please avoid emailing maintainers found in the MAINTAINERS file directly. They
|
||||
are very busy and read the mailing lists.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- Fork the repository on GitHub
|
||||
- Read the [README](README.md) for build and test instructions
|
||||
- Play with the project, submit bugs, submit patches!
|
||||
|
||||
## Contribution Flow
|
||||
|
||||
This is a rough outline of what a contributor's workflow looks like:
|
||||
|
||||
- Create a topic branch from where you want to base your work (usually master).
|
||||
- Make commits of logical units.
|
||||
- Make sure your commit messages are in the proper format (see below).
|
||||
- Push your changes to a topic branch in your fork of the repository.
|
||||
- Make sure the tests pass, and add any new tests as appropriate.
|
||||
- Submit a pull request to the original repository.
|
||||
|
||||
Thanks for your contributions!
|
||||
|
||||
### Coding Style
|
||||
|
||||
CoreOS projects written in Go follow a set of style guidelines that we've documented
|
||||
[here](https://github.com/coreos/docs/tree/master/golang). Please follow them when
|
||||
working on your contributions.
|
||||
|
||||
### Format of the Commit Message
|
||||
|
||||
We follow a rough convention for commit messages that is designed to answer two
|
||||
questions: what changed and why. The subject line should feature the what and
|
||||
the body of the commit should describe the why.
|
||||
|
||||
```
|
||||
scripts: add the test-cluster command
|
||||
|
||||
this uses tmux to setup a test cluster that you can easily kill and
|
||||
start for debugging.
|
||||
|
||||
Fixes #38
|
||||
```
|
||||
|
||||
The format can be described more formally as follows:
|
||||
|
||||
```
|
||||
<subsystem>: <what changed>
|
||||
<BLANK LINE>
|
||||
<why this change was made>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The first line is the subject and should be no longer than 70 characters, the
|
||||
second line is always blank, and other lines should be wrapped at 80 characters.
|
||||
This allows the message to be easier to read on GitHub as well as in various
|
||||
git tools.
|
36
vendor/github.com/coreos/go-systemd/DCO
generated
vendored
36
vendor/github.com/coreos/go-systemd/DCO
generated
vendored
|
@ -1,36 +0,0 @@
|
|||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
660 York Street, Suite 102,
|
||||
San Francisco, CA 94110 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
52
vendor/github.com/coreos/go-systemd/activation/files.go
generated
vendored
52
vendor/github.com/coreos/go-systemd/activation/files.go
generated
vendored
|
@ -1,52 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package activation implements primitives for systemd socket activation.
|
||||
package activation
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// based on: https://gist.github.com/alberts/4640792
|
||||
const (
|
||||
listenFdsStart = 3
|
||||
)
|
||||
|
||||
func Files(unsetEnv bool) []*os.File {
|
||||
if unsetEnv {
|
||||
defer os.Unsetenv("LISTEN_PID")
|
||||
defer os.Unsetenv("LISTEN_FDS")
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
|
||||
if err != nil || pid != os.Getpid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
|
||||
if err != nil || nfds == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
files := make([]*os.File, 0, nfds)
|
||||
for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
|
||||
syscall.CloseOnExec(fd)
|
||||
files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd)))
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
82
vendor/github.com/coreos/go-systemd/activation/files_test.go
generated
vendored
82
vendor/github.com/coreos/go-systemd/activation/files_test.go
generated
vendored
|
@ -1,82 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// correctStringWritten fails the text if the correct string wasn't written
|
||||
// to the other side of the pipe.
|
||||
func correctStringWritten(t *testing.T, r *os.File, expected string) bool {
|
||||
bytes := make([]byte, len(expected))
|
||||
io.ReadAtLeast(r, bytes, len(expected))
|
||||
|
||||
if string(bytes) != expected {
|
||||
t.Fatalf("Unexpected string %s", string(bytes))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// TestActivation forks out a copy of activation.go example and reads back two
|
||||
// strings from the pipes that are passed in.
|
||||
func TestActivation(t *testing.T) {
|
||||
cmd := exec.Command("go", "run", "../examples/activation/activation.go")
|
||||
|
||||
r1, w1, _ := os.Pipe()
|
||||
r2, w2, _ := os.Pipe()
|
||||
cmd.ExtraFiles = []*os.File{
|
||||
w1,
|
||||
w2,
|
||||
}
|
||||
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, "LISTEN_FDS=2", "FIX_LISTEN_PID=1")
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
correctStringWritten(t, r1, "Hello world")
|
||||
correctStringWritten(t, r2, "Goodbye world")
|
||||
}
|
||||
|
||||
func TestActivationNoFix(t *testing.T) {
|
||||
cmd := exec.Command("go", "run", "../examples/activation/activation.go")
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, "LISTEN_FDS=2")
|
||||
|
||||
out, _ := cmd.CombinedOutput()
|
||||
if bytes.Contains(out, []byte("No files")) == false {
|
||||
t.Fatalf("Child didn't error out as expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestActivationNoFiles(t *testing.T) {
|
||||
cmd := exec.Command("go", "run", "../examples/activation/activation.go")
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, "LISTEN_FDS=0", "FIX_LISTEN_PID=1")
|
||||
|
||||
out, _ := cmd.CombinedOutput()
|
||||
if bytes.Contains(out, []byte("No files")) == false {
|
||||
t.Fatalf("Child didn't error out as expected")
|
||||
}
|
||||
}
|
60
vendor/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
60
vendor/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
|
@ -1,60 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Listeners returns a slice containing a net.Listener for each matching socket type
|
||||
// passed to this process.
|
||||
//
|
||||
// The order of the file descriptors is preserved in the returned slice.
|
||||
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
||||
// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
|
||||
func Listeners(unsetEnv bool) ([]net.Listener, error) {
|
||||
files := Files(unsetEnv)
|
||||
listeners := make([]net.Listener, len(files))
|
||||
|
||||
for i, f := range files {
|
||||
if pc, err := net.FileListener(f); err == nil {
|
||||
listeners[i] = pc
|
||||
}
|
||||
}
|
||||
return listeners, nil
|
||||
}
|
||||
|
||||
// TLSListeners returns a slice containing a net.listener for each matching TCP socket type
|
||||
// passed to this process.
|
||||
// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig.
|
||||
func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error) {
|
||||
listeners, err := Listeners(unsetEnv)
|
||||
|
||||
if listeners == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tlsConfig != nil && err == nil {
|
||||
for i, l := range listeners {
|
||||
// Activate TLS only for TCP sockets
|
||||
if l.Addr().Network() == "tcp" {
|
||||
listeners[i] = tls.NewListener(l, tlsConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return listeners, err
|
||||
}
|
86
vendor/github.com/coreos/go-systemd/activation/listeners_test.go
generated
vendored
86
vendor/github.com/coreos/go-systemd/activation/listeners_test.go
generated
vendored
|
@ -1,86 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// correctStringWritten fails the text if the correct string wasn't written
|
||||
// to the other side of the pipe.
|
||||
func correctStringWrittenNet(t *testing.T, r net.Conn, expected string) bool {
|
||||
bytes := make([]byte, len(expected))
|
||||
io.ReadAtLeast(r, bytes, len(expected))
|
||||
|
||||
if string(bytes) != expected {
|
||||
t.Fatalf("Unexpected string %s", string(bytes))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// TestActivation forks out a copy of activation.go example and reads back two
|
||||
// strings from the pipes that are passed in.
|
||||
func TestListeners(t *testing.T) {
|
||||
cmd := exec.Command("go", "run", "../examples/activation/listen.go")
|
||||
|
||||
l1, err := net.Listen("tcp", ":9999")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
l2, err := net.Listen("tcp", ":1234")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
t1 := l1.(*net.TCPListener)
|
||||
t2 := l2.(*net.TCPListener)
|
||||
|
||||
f1, _ := t1.File()
|
||||
f2, _ := t2.File()
|
||||
|
||||
cmd.ExtraFiles = []*os.File{
|
||||
f1,
|
||||
f2,
|
||||
}
|
||||
|
||||
r1, err := net.Dial("tcp", "127.0.0.1:9999")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
r1.Write([]byte("Hi"))
|
||||
|
||||
r2, err := net.Dial("tcp", "127.0.0.1:1234")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
r2.Write([]byte("Hi"))
|
||||
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, "LISTEN_FDS=2", "FIX_LISTEN_PID=1")
|
||||
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
println(string(out))
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
correctStringWrittenNet(t, r1, "Hello world")
|
||||
correctStringWrittenNet(t, r2, "Goodbye world")
|
||||
}
|
37
vendor/github.com/coreos/go-systemd/activation/packetconns.go
generated
vendored
37
vendor/github.com/coreos/go-systemd/activation/packetconns.go
generated
vendored
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// PacketConns returns a slice containing a net.PacketConn for each matching socket type
|
||||
// passed to this process.
|
||||
//
|
||||
// The order of the file descriptors is preserved in the returned slice.
|
||||
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
||||
// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
|
||||
func PacketConns(unsetEnv bool) ([]net.PacketConn, error) {
|
||||
files := Files(unsetEnv)
|
||||
conns := make([]net.PacketConn, len(files))
|
||||
|
||||
for i, f := range files {
|
||||
if pc, err := net.FilePacketConn(f); err == nil {
|
||||
conns[i] = pc
|
||||
}
|
||||
}
|
||||
return conns, nil
|
||||
}
|
68
vendor/github.com/coreos/go-systemd/activation/packetconns_test.go
generated
vendored
68
vendor/github.com/coreos/go-systemd/activation/packetconns_test.go
generated
vendored
|
@ -1,68 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestActivation forks out a copy of activation.go example and reads back two
|
||||
// strings from the pipes that are passed in.
|
||||
func TestPacketConns(t *testing.T) {
|
||||
cmd := exec.Command("go", "run", "../examples/activation/udpconn.go")
|
||||
|
||||
u1, err := net.ListenUDP("udp", &net.UDPAddr{Port: 9999})
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
u2, err := net.ListenUDP("udp", &net.UDPAddr{Port: 1234})
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
f1, _ := u1.File()
|
||||
f2, _ := u2.File()
|
||||
|
||||
cmd.ExtraFiles = []*os.File{
|
||||
f1,
|
||||
f2,
|
||||
}
|
||||
|
||||
r1, err := net.Dial("udp", "127.0.0.1:9999")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
r1.Write([]byte("Hi"))
|
||||
|
||||
r2, err := net.Dial("udp", "127.0.0.1:1234")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
r2.Write([]byte("Hi"))
|
||||
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, "LISTEN_FDS=2", "FIX_LISTEN_PID=1")
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("Cmd output '%s', err: '%s'\n", out, err)
|
||||
}
|
||||
|
||||
correctStringWrittenNet(t, r1, "Hello world")
|
||||
correctStringWrittenNet(t, r2, "Goodbye world")
|
||||
}
|
79
vendor/github.com/coreos/go-systemd/daemon/sdnotify_test.go
generated
vendored
79
vendor/github.com/coreos/go-systemd/daemon/sdnotify_test.go
generated
vendored
|
@ -1,79 +0,0 @@
|
|||
// 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 (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestSdNotify
|
||||
func TestSdNotify(t *testing.T) {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
unsetEnv bool
|
||||
envSocket string
|
||||
|
||||
wsent bool
|
||||
werr bool
|
||||
}{
|
||||
// (true, nil) - notification supported, data has been sent
|
||||
{false, notifySocket, true, false},
|
||||
// (false, err) - notification supported, but failure happened
|
||||
{true, testDir + "/missing.sock", false, true},
|
||||
// (false, nil) - notification not supported
|
||||
{true, "", false, false},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
must(os.Unsetenv("NOTIFY_SOCKET"))
|
||||
if tt.envSocket != "" {
|
||||
must(os.Setenv("NOTIFY_SOCKET", tt.envSocket))
|
||||
}
|
||||
sent, err := SdNotify(tt.unsetEnv, fmt.Sprintf("TestSdNotify test message #%d", i))
|
||||
|
||||
if sent != tt.wsent {
|
||||
t.Errorf("#%d: expected send result %t, got %t", i, tt.wsent, sent)
|
||||
}
|
||||
if tt.werr && err == nil {
|
||||
t.Errorf("#%d: want non-nil err, got nil", i)
|
||||
} else if !tt.werr && err != nil {
|
||||
t.Errorf("#%d: want nil err, got %v", i, err)
|
||||
}
|
||||
if tt.unsetEnv && tt.envSocket != "" && os.Getenv("NOTIFY_SOCKET") != "" {
|
||||
t.Errorf("#%d: environment variable not cleaned up", i)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
85
vendor/github.com/coreos/go-systemd/daemon/watchdog_test.go
generated
vendored
85
vendor/github.com/coreos/go-systemd/daemon/watchdog_test.go
generated
vendored
|
@ -1,85 +0,0 @@
|
|||
// 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 (
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSdWatchdogEnabled(t *testing.T) {
|
||||
mypid := strconv.Itoa(os.Getpid())
|
||||
tests := []struct {
|
||||
usec string // empty => unset
|
||||
pid string // empty => unset
|
||||
unsetEnv bool // arbitrarily set across testcases
|
||||
|
||||
werr bool
|
||||
wdelay time.Duration
|
||||
}{
|
||||
// Success cases
|
||||
{"100", mypid, true, false, 100 * time.Microsecond},
|
||||
{"50", mypid, true, false, 50 * time.Microsecond},
|
||||
{"1", mypid, false, false, 1 * time.Microsecond},
|
||||
{"1", "", true, false, 1 * time.Microsecond},
|
||||
|
||||
// No-op cases
|
||||
{"", mypid, true, false, 0}, // WATCHDOG_USEC not set
|
||||
{"1", "0", false, false, 0}, // WATCHDOG_PID doesn't match
|
||||
{"", "", true, false, 0}, // Both not set
|
||||
|
||||
// Failure cases
|
||||
{"-1", mypid, true, true, 0}, // Negative USEC
|
||||
{"string", "1", false, true, 0}, // Non-integer USEC value
|
||||
{"1", "string", true, true, 0}, // Non-integer PID value
|
||||
{"stringa", "stringb", false, true, 0}, // E v e r y t h i n g
|
||||
{"-10239", "-eleventythree", true, true, 0}, // i s w r o n g
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
if tt.usec != "" {
|
||||
must(os.Setenv("WATCHDOG_USEC", tt.usec))
|
||||
} else {
|
||||
must(os.Unsetenv("WATCHDOG_USEC"))
|
||||
}
|
||||
if tt.pid != "" {
|
||||
must(os.Setenv("WATCHDOG_PID", tt.pid))
|
||||
} else {
|
||||
must(os.Unsetenv("WATCHDOG_PID"))
|
||||
}
|
||||
|
||||
delay, err := SdWatchdogEnabled(tt.unsetEnv)
|
||||
|
||||
if tt.werr && err == nil {
|
||||
t.Errorf("#%d: want non-nil err, got nil", i)
|
||||
} else if !tt.werr && err != nil {
|
||||
t.Errorf("#%d: want nil err, got %v", i, err)
|
||||
}
|
||||
if tt.wdelay != delay {
|
||||
t.Errorf("#%d: want delay=%d, got %d", i, tt.wdelay, delay)
|
||||
}
|
||||
if tt.unsetEnv && (os.Getenv("WATCHDOG_PID") != "" || os.Getenv("WATCHDOG_USEC") != "") {
|
||||
t.Errorf("#%d: environment variables not cleaned up", i)
|
||||
}
|
||||
}
|
||||
}
|
77
vendor/github.com/coreos/go-systemd/dbus/dbus_test.go
generated
vendored
77
vendor/github.com/coreos/go-systemd/dbus/dbus_test.go
generated
vendored
|
@ -1,77 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNeedsEscape(t *testing.T) {
|
||||
// Anything not 0-9a-zA-Z should always be escaped
|
||||
for want, vals := range map[bool][]byte{
|
||||
false: []byte{'a', 'b', 'z', 'A', 'Q', '1', '4', '9'},
|
||||
true: []byte{'#', '%', '$', '!', '.', '_', '-', '%', '\\'},
|
||||
} {
|
||||
for i := 1; i < 10; i++ {
|
||||
for _, b := range vals {
|
||||
got := needsEscape(i, b)
|
||||
if got != want {
|
||||
t.Errorf("needsEscape(%d, %c) returned %t, want %t", i, b, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 0-9 in position 0 should be escaped
|
||||
for want, vals := range map[bool][]byte{
|
||||
false: []byte{'A', 'a', 'e', 'x', 'Q', 'Z'},
|
||||
true: []byte{'0', '4', '5', '9'},
|
||||
} {
|
||||
for _, b := range vals {
|
||||
got := needsEscape(0, b)
|
||||
if got != want {
|
||||
t.Errorf("needsEscape(0, %c) returned %t, want %t", b, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestPathBusEscape(t *testing.T) {
|
||||
for in, want := range map[string]string{
|
||||
"": "_",
|
||||
"foo.service": "foo_2eservice",
|
||||
"foobar": "foobar",
|
||||
"woof@woof.service": "woof_40woof_2eservice",
|
||||
"0123456": "_30123456",
|
||||
"account_db.service": "account_5fdb_2eservice",
|
||||
"got-dashes": "got_2ddashes",
|
||||
} {
|
||||
got := PathBusEscape(in)
|
||||
if got != want {
|
||||
t.Errorf("bad result for PathBusEscape(%s): got %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestNew ensures that New() works without errors.
|
||||
func TestNew(t *testing.T) {
|
||||
_, err := New()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
996
vendor/github.com/coreos/go-systemd/dbus/methods_test.go
generated
vendored
996
vendor/github.com/coreos/go-systemd/dbus/methods_test.go
generated
vendored
|
@ -1,996 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
)
|
||||
|
||||
func setupConn(t *testing.T) *Conn {
|
||||
conn, err := New()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
func findFixture(target string, t *testing.T) string {
|
||||
abs, err := filepath.Abs("../fixtures/" + target)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return abs
|
||||
}
|
||||
|
||||
func setupUnit(target string, conn *Conn, t *testing.T) {
|
||||
// Blindly stop the unit in case it is running
|
||||
conn.StopUnit(target, "replace", nil)
|
||||
|
||||
// Blindly remove the symlink in case it exists
|
||||
targetRun := filepath.Join("/run/systemd/system/", target)
|
||||
os.Remove(targetRun)
|
||||
}
|
||||
|
||||
func linkUnit(target string, conn *Conn, t *testing.T) {
|
||||
abs := findFixture(target, t)
|
||||
fixture := []string{abs}
|
||||
|
||||
changes, err := conn.LinkUnitFiles(fixture, true, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(changes) < 1 {
|
||||
t.Fatalf("Expected one change, got %v", changes)
|
||||
}
|
||||
|
||||
runPath := filepath.Join("/run/systemd/system/", target)
|
||||
if changes[0].Filename != runPath {
|
||||
t.Fatal("Unexpected target filename")
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
conn := setupConn(t)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
// 2. Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err := conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 3. Stop the unit
|
||||
_, err = conn.StopUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// wait for StopUnit job to complete
|
||||
<-reschan
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target)
|
||||
|
||||
if unit != nil {
|
||||
t.Fatalf("Test unit found in list, should be stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that basic unit restarting works.
|
||||
func TestRestartUnit(t *testing.T) {
|
||||
target := "start-stop.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
// Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err := conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// Restart the unit
|
||||
reschan = make(chan string)
|
||||
_, err = conn.RestartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job = <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
// Stop the unit
|
||||
_, err = conn.StopUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// wait for StopUnit job to complete
|
||||
<-reschan
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target)
|
||||
if unit != nil {
|
||||
t.Fatalf("Test unit found in list, should be stopped")
|
||||
}
|
||||
|
||||
// Try to restart the unit.
|
||||
// It should still succeed, even if the unit is inactive.
|
||||
reschan = make(chan string)
|
||||
_, err = conn.TryRestartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// wait for StopUnit job to complete
|
||||
<-reschan
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target)
|
||||
if unit != nil {
|
||||
t.Fatalf("Test unit found in list, should be stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that basic unit reloading works.
|
||||
func TestReloadUnit(t *testing.T) {
|
||||
target := "reload.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
err := conn.Subscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
subSet := conn.NewSubscriptionSet()
|
||||
evChan, errChan := subSet.Subscribe()
|
||||
|
||||
subSet.Add(target)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
// Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err = conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// Reload the unit
|
||||
reschan = make(chan string)
|
||||
|
||||
_, err = conn.ReloadUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job = <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
timeout := make(chan bool, 1)
|
||||
go func() {
|
||||
time.Sleep(3 * time.Second)
|
||||
close(timeout)
|
||||
}()
|
||||
|
||||
// Wait for the event, expecting the target UnitStatus meets all of the
|
||||
// following conditions:
|
||||
// * target is non-nil
|
||||
// * target's ActiveState is active.
|
||||
waitevent:
|
||||
for {
|
||||
select {
|
||||
case changes := <-evChan:
|
||||
tch, ok := changes[target]
|
||||
if !ok {
|
||||
continue waitevent
|
||||
}
|
||||
if tch != nil && tch.Name == target && tch.ActiveState == "active" {
|
||||
break waitevent
|
||||
}
|
||||
case err = <-errChan:
|
||||
t.Fatal(err)
|
||||
case <-timeout:
|
||||
t.Fatal("Reached timeout")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that basic unit reload-or-restarting works.
|
||||
func TestReloadOrRestartUnit(t *testing.T) {
|
||||
target := "reload.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
// Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err := conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// Reload or restart the unit
|
||||
reschan = make(chan string)
|
||||
_, err = conn.ReloadOrRestartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job = <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
// Stop the unit
|
||||
_, err = conn.StopUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// wait for StopUnit job to complete
|
||||
<-reschan
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit = getUnitStatus(units, target)
|
||||
if unit != nil && unit.ActiveState == "active" {
|
||||
t.Fatalf("Test unit still active, should be inactive.")
|
||||
}
|
||||
|
||||
// Reload or try to restart the unit
|
||||
// It should still succeed, even if the unit is inactive.
|
||||
reschan = make(chan string)
|
||||
_, err = conn.ReloadOrTryRestartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job = <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
}
|
||||
|
||||
// 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"
|
||||
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. Disable the unit
|
||||
dChanges, err := conn.DisableUnitFiles([]string{target}, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(dChanges) != 1 {
|
||||
t.Fatalf("Changes should include the path, %v", dChanges)
|
||||
}
|
||||
if dChanges[0].Filename != runPath {
|
||||
t.Fatalf("Change should include correct filename, %+v", dChanges[0])
|
||||
}
|
||||
if dChanges[0].Destination != "" {
|
||||
t.Fatalf("Change destination should be empty, %+v", dChanges[0])
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetUnitProperties reads the `-.mount` which should exist on all systemd
|
||||
// systems and ensures that one of its properties is valid.
|
||||
func TestGetUnitProperties(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
unit := "-.mount"
|
||||
|
||||
info, err := conn.GetUnitProperties(unit)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
desc, _ := info["Description"].(string)
|
||||
|
||||
prop, err := conn.GetUnitProperty(unit, "Description")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if prop.Name != "Description" {
|
||||
t.Fatal("unexpected property name")
|
||||
}
|
||||
|
||||
val := prop.Value.Value().(string)
|
||||
if !reflect.DeepEqual(val, desc) {
|
||||
t.Fatal("unexpected property value")
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetUnitPropertiesRejectsInvalidName attempts to get the properties for a
|
||||
// unit with an invalid name. This test should be run with --test.timeout set,
|
||||
// as a fail will manifest as GetUnitProperties hanging indefinitely.
|
||||
func TestGetUnitPropertiesRejectsInvalidName(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
unit := "//invalid#$^/"
|
||||
|
||||
_, err := conn.GetUnitProperties(unit)
|
||||
if err == nil {
|
||||
t.Fatal("Expected an error, got nil")
|
||||
}
|
||||
|
||||
_, err = conn.GetUnitProperty(unit, "Wants")
|
||||
if err == nil {
|
||||
t.Fatal("Expected an error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// 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 := "-.mount"
|
||||
|
||||
if err := conn.SetUnitProperties(unit, true, Property{"CPUShares", dbus.MakeVariant(uint64(1023))}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
info, err := conn.GetUnitTypeProperties(unit, "Mount")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value, _ := info["CPUShares"].(uint64)
|
||||
if value != 1023 {
|
||||
t.Fatal("CPUShares of unit is not 1023:", value)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that basic transient unit starting and stopping works.
|
||||
func TestStartStopTransientUnit(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
props := []Property{
|
||||
PropExecStart([]string{"/bin/sleep", "400"}, false),
|
||||
}
|
||||
target := fmt.Sprintf("testing-transient-%d.service", rand.Int())
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 3. Stop the unit
|
||||
_, err = conn.StopUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// wait for StopUnit job to complete
|
||||
<-reschan
|
||||
|
||||
units, err = conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// Ensure that basic unit gets killed by SIGTERM
|
||||
func TestKillUnit(t *testing.T) {
|
||||
target := "start-stop.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
err := conn.Subscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
subSet := conn.NewSubscriptionSet()
|
||||
evChan, errChan := subSet.Subscribe()
|
||||
|
||||
subSet.Add(target)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
// Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err = conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Job is not done:", job)
|
||||
}
|
||||
|
||||
// send SIGTERM
|
||||
conn.KillUnit(target, int32(syscall.SIGTERM))
|
||||
|
||||
timeout := make(chan bool, 1)
|
||||
go func() {
|
||||
time.Sleep(3 * time.Second)
|
||||
close(timeout)
|
||||
}()
|
||||
|
||||
// Wait for the event, expecting the target UnitStatus meets one of the
|
||||
// following conditions:
|
||||
// * target is nil, meaning the unit has completely gone.
|
||||
// * target is non-nil, and its ActiveState is not active.
|
||||
waitevent:
|
||||
for {
|
||||
select {
|
||||
case changes := <-evChan:
|
||||
tch, ok := changes[target]
|
||||
if !ok {
|
||||
continue waitevent
|
||||
}
|
||||
if tch == nil || (tch != nil && tch.Name == target && tch.ActiveState != "active") {
|
||||
break waitevent
|
||||
}
|
||||
case err = <-errChan:
|
||||
t.Fatal(err)
|
||||
case <-timeout:
|
||||
t.Fatal("Reached timeout")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that a failed unit gets reset
|
||||
func TestResetFailedUnit(t *testing.T) {
|
||||
target := "start-failed.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
// Start the unit
|
||||
reschan := make(chan string)
|
||||
_, err := conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "failed" {
|
||||
t.Fatal("Job is not failed:", job)
|
||||
}
|
||||
|
||||
units, err := conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
unit := getUnitStatus(units, target)
|
||||
if unit == nil {
|
||||
t.Fatalf("Test unit not found in list")
|
||||
}
|
||||
|
||||
// reset the failed unit
|
||||
err = conn.ResetFailedUnit(target)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure that the target unit is actually gone
|
||||
units, err = conn.ListUnits()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, u := range units {
|
||||
if u.Name == target {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
t.Fatalf("Test unit still found in list. units = %v", units)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnJobListener(t *testing.T) {
|
||||
target := "start-stop.service"
|
||||
conn := setupConn(t)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
jobSize := len(conn.jobListener.jobs)
|
||||
|
||||
reschan := make(chan string)
|
||||
_, err := conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
<-reschan
|
||||
|
||||
_, err = conn.StopUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
<-reschan
|
||||
|
||||
currentJobSize := len(conn.jobListener.jobs)
|
||||
if jobSize != currentJobSize {
|
||||
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])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test a global Reload
|
||||
func TestReload(t *testing.T) {
|
||||
conn := setupConn(t)
|
||||
|
||||
err := conn.Reload()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
53
vendor/github.com/coreos/go-systemd/dbus/set_test.go
generated
vendored
53
vendor/github.com/coreos/go-systemd/dbus/set_test.go
generated
vendored
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestBasicSetActions asserts that Add & Remove behavior is correct
|
||||
func TestBasicSetActions(t *testing.T) {
|
||||
s := newSet()
|
||||
|
||||
if s.Contains("foo") {
|
||||
t.Fatal("set should not contain 'foo'")
|
||||
}
|
||||
|
||||
s.Add("foo")
|
||||
|
||||
if !s.Contains("foo") {
|
||||
t.Fatal("set should contain 'foo'")
|
||||
}
|
||||
|
||||
v := s.Values()
|
||||
if len(v) != 1 {
|
||||
t.Fatal("set.Values did not report correct number of values")
|
||||
}
|
||||
if v[0] != "foo" {
|
||||
t.Fatal("set.Values did not report value")
|
||||
}
|
||||
|
||||
s.Remove("foo")
|
||||
|
||||
if s.Contains("foo") {
|
||||
t.Fatal("set should not contain 'foo'")
|
||||
}
|
||||
|
||||
v = s.Values()
|
||||
if len(v) != 0 {
|
||||
t.Fatal("set.Values did not report correct number of values")
|
||||
}
|
||||
}
|
82
vendor/github.com/coreos/go-systemd/dbus/subscription_set_test.go
generated
vendored
82
vendor/github.com/coreos/go-systemd/dbus/subscription_set_test.go
generated
vendored
|
@ -1,82 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestSubscribeUnit exercises the basics of subscription of a particular unit.
|
||||
func TestSubscriptionSetUnit(t *testing.T) {
|
||||
target := "subscribe-events-set.service"
|
||||
|
||||
conn, err := New()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = conn.Subscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
subSet := conn.NewSubscriptionSet()
|
||||
evChan, errChan := subSet.Subscribe()
|
||||
|
||||
subSet.Add(target)
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
reschan := make(chan string)
|
||||
_, err = conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Couldn't start", target)
|
||||
}
|
||||
|
||||
timeout := make(chan bool, 1)
|
||||
go func() {
|
||||
time.Sleep(3 * time.Second)
|
||||
close(timeout)
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case changes := <-evChan:
|
||||
tCh, ok := changes[target]
|
||||
|
||||
if !ok {
|
||||
t.Fatal("Unexpected event:", changes)
|
||||
}
|
||||
|
||||
if tCh.ActiveState == "active" && tCh.Name == target {
|
||||
goto success
|
||||
}
|
||||
case err = <-errChan:
|
||||
t.Fatal(err)
|
||||
case <-timeout:
|
||||
t.Fatal("Reached timeout")
|
||||
}
|
||||
}
|
||||
|
||||
success:
|
||||
return
|
||||
}
|
105
vendor/github.com/coreos/go-systemd/dbus/subscription_test.go
generated
vendored
105
vendor/github.com/coreos/go-systemd/dbus/subscription_test.go
generated
vendored
|
@ -1,105 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestSubscribe exercises the basics of subscription
|
||||
func TestSubscribe(t *testing.T) {
|
||||
conn, err := New()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = conn.Subscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = conn.Unsubscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSubscribeUnit exercises the basics of subscription of a particular unit.
|
||||
func TestSubscribeUnit(t *testing.T) {
|
||||
target := "subscribe-events.service"
|
||||
|
||||
conn, err := New()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = conn.Subscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = conn.Unsubscribe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
evChan, errChan := conn.SubscribeUnits(time.Second)
|
||||
|
||||
setupUnit(target, conn, t)
|
||||
linkUnit(target, conn, t)
|
||||
|
||||
reschan := make(chan string)
|
||||
_, err = conn.StartUnit(target, "replace", reschan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
job := <-reschan
|
||||
if job != "done" {
|
||||
t.Fatal("Couldn't start", target)
|
||||
}
|
||||
|
||||
timeout := make(chan bool, 1)
|
||||
go func() {
|
||||
time.Sleep(3 * time.Second)
|
||||
close(timeout)
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case changes := <-evChan:
|
||||
tCh, ok := changes[target]
|
||||
|
||||
// Just continue until we see our event.
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if tCh.ActiveState == "active" && tCh.Name == target {
|
||||
goto success
|
||||
}
|
||||
case err = <-errChan:
|
||||
t.Fatal(err)
|
||||
case <-timeout:
|
||||
t.Fatal("Reached timeout")
|
||||
}
|
||||
}
|
||||
|
||||
success:
|
||||
return
|
||||
}
|
60
vendor/github.com/coreos/go-systemd/examples/activation/activation.go
generated
vendored
60
vendor/github.com/coreos/go-systemd/examples/activation/activation.go
generated
vendored
|
@ -1,60 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Activation example used by the activation unit tests.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
)
|
||||
|
||||
func fixListenPid() {
|
||||
if os.Getenv("FIX_LISTEN_PID") != "" {
|
||||
// HACK: real systemd would set LISTEN_PID before exec'ing but
|
||||
// this is too difficult in golang for the purpose of a test.
|
||||
// Do not do this in real code.
|
||||
os.Setenv("LISTEN_PID", fmt.Sprintf("%d", os.Getpid()))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fixListenPid()
|
||||
|
||||
files := activation.Files(false)
|
||||
|
||||
if len(files) == 0 {
|
||||
panic("No files")
|
||||
}
|
||||
|
||||
if os.Getenv("LISTEN_PID") == "" || os.Getenv("LISTEN_FDS") == "" {
|
||||
panic("Should not unset envs")
|
||||
}
|
||||
|
||||
files = activation.Files(true)
|
||||
|
||||
if os.Getenv("LISTEN_PID") != "" || os.Getenv("LISTEN_FDS") != "" {
|
||||
panic("Can not unset envs")
|
||||
}
|
||||
|
||||
// Write out the expected strings to the two pipes
|
||||
files[0].Write([]byte("Hello world"))
|
||||
files[1].Write([]byte("Goodbye world"))
|
||||
|
||||
return
|
||||
}
|
19
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/README.md
generated
vendored
19
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/README.md
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
## socket activated http server
|
||||
|
||||
This is a simple example of using socket activation with systemd to serve a
|
||||
simple HTTP server on http://127.0.0.1:8076
|
||||
|
||||
To try it out `go get` the httpserver and run it under the systemd-activate helper
|
||||
|
||||
```bash
|
||||
export GOPATH="$PWD"
|
||||
go get github.com/coreos/go-systemd/examples/activation/httpserver
|
||||
/usr/lib/systemd/systemd-activate -l 127.0.0.1:8076 ./bin/httpserver
|
||||
```
|
||||
|
||||
Then curl the URL and you will notice that it starts up:
|
||||
|
||||
```
|
||||
curl 127.0.0.1:8076
|
||||
hello socket activated world!
|
||||
```
|
11
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/hello.service
generated
vendored
11
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/hello.service
generated
vendored
|
@ -1,11 +0,0 @@
|
|||
[Unit]
|
||||
Description=Hello World HTTP
|
||||
Requires=network.target
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/httpserver
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
5
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/hello.socket
generated
vendored
5
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/hello.socket
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
[Socket]
|
||||
ListenStream=127.0.0.1:8076
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
42
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/httpserver.go
generated
vendored
42
vendor/github.com/coreos/go-systemd/examples/activation/httpserver/httpserver.go
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
)
|
||||
|
||||
func HelloServer(w http.ResponseWriter, req *http.Request) {
|
||||
io.WriteString(w, "hello socket activated world!\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
listeners, err := activation.Listeners(true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if len(listeners) != 1 {
|
||||
panic("Unexpected number of socket activation fds")
|
||||
}
|
||||
|
||||
http.HandleFunc("/", HelloServer)
|
||||
http.Serve(listeners[0], nil)
|
||||
}
|
66
vendor/github.com/coreos/go-systemd/examples/activation/listen.go
generated
vendored
66
vendor/github.com/coreos/go-systemd/examples/activation/listen.go
generated
vendored
|
@ -1,66 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Activation example used by the activation unit tests.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
)
|
||||
|
||||
func fixListenPid() {
|
||||
if os.Getenv("FIX_LISTEN_PID") != "" {
|
||||
// HACK: real systemd would set LISTEN_PID before exec'ing but
|
||||
// this is too difficult in golang for the purpose of a test.
|
||||
// Do not do this in real code.
|
||||
os.Setenv("LISTEN_PID", fmt.Sprintf("%d", os.Getpid()))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fixListenPid()
|
||||
|
||||
listeners, _ := activation.Listeners(false)
|
||||
|
||||
if len(listeners) == 0 {
|
||||
panic("No listeners")
|
||||
}
|
||||
|
||||
if os.Getenv("LISTEN_PID") == "" || os.Getenv("LISTEN_FDS") == "" {
|
||||
panic("Should not unset envs")
|
||||
}
|
||||
|
||||
listeners, err := activation.Listeners(true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if os.Getenv("LISTEN_PID") != "" || os.Getenv("LISTEN_FDS") != "" {
|
||||
panic("Can not unset envs")
|
||||
}
|
||||
|
||||
c0, _ := listeners[0].Accept()
|
||||
c1, _ := listeners[1].Accept()
|
||||
|
||||
// Write out the expected strings to the two pipes
|
||||
c0.Write([]byte("Hello world"))
|
||||
c1.Write([]byte("Goodbye world"))
|
||||
|
||||
return
|
||||
}
|
88
vendor/github.com/coreos/go-systemd/examples/activation/udpconn.go
generated
vendored
88
vendor/github.com/coreos/go-systemd/examples/activation/udpconn.go
generated
vendored
|
@ -1,88 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Activation example used by the activation unit tests.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
)
|
||||
|
||||
func fixListenPid() {
|
||||
if os.Getenv("FIX_LISTEN_PID") != "" {
|
||||
// HACK: real systemd would set LISTEN_PID before exec'ing but
|
||||
// this is too difficult in golang for the purpose of a test.
|
||||
// Do not do this in real code.
|
||||
os.Setenv("LISTEN_PID", fmt.Sprintf("%d", os.Getpid()))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fixListenPid()
|
||||
|
||||
pc, _ := activation.PacketConns(false)
|
||||
|
||||
if len(pc) == 0 {
|
||||
panic("No packetConns")
|
||||
}
|
||||
|
||||
if os.Getenv("LISTEN_PID") == "" || os.Getenv("LISTEN_FDS") == "" {
|
||||
panic("Should not unset envs")
|
||||
}
|
||||
|
||||
pc, err := activation.PacketConns(true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if os.Getenv("LISTEN_PID") != "" || os.Getenv("LISTEN_FDS") != "" {
|
||||
panic("Can not unset envs")
|
||||
}
|
||||
|
||||
udp1, ok := pc[0].(*net.UDPConn)
|
||||
if !ok {
|
||||
panic("packetConn 1 not UDP")
|
||||
}
|
||||
udp2, ok := pc[1].(*net.UDPConn)
|
||||
if !ok {
|
||||
panic("packetConn 2 not UDP")
|
||||
}
|
||||
|
||||
_, addr1, err := udp1.ReadFromUDP(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, addr2, err := udp2.ReadFromUDP(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Write out the expected strings to the two pipes
|
||||
_, err = udp1.WriteToUDP([]byte("Hello world"), addr1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = udp2.WriteToUDP([]byte("Goodbye world"), addr2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
5
vendor/github.com/coreos/go-systemd/fixtures/enable-disable.service
generated
vendored
5
vendor/github.com/coreos/go-systemd/fixtures/enable-disable.service
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
[Unit]
|
||||
Description=enable disable test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sleep 400
|
5
vendor/github.com/coreos/go-systemd/fixtures/mask-unmask.service
generated
vendored
5
vendor/github.com/coreos/go-systemd/fixtures/mask-unmask.service
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
[Unit]
|
||||
Description=mask unmask test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sleep 400
|
6
vendor/github.com/coreos/go-systemd/fixtures/reload.service
generated
vendored
6
vendor/github.com/coreos/go-systemd/fixtures/reload.service
generated
vendored
|
@ -1,6 +0,0 @@
|
|||
[Unit]
|
||||
Description=reload test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/bash -c "trap '' HUP; /bin/sleep 400"
|
||||
ExecReload=-/bin/systemctl kill -s HUP reload.service
|
6
vendor/github.com/coreos/go-systemd/fixtures/start-failed.service
generated
vendored
6
vendor/github.com/coreos/go-systemd/fixtures/start-failed.service
generated
vendored
|
@ -1,6 +0,0 @@
|
|||
[Unit]
|
||||
Description=starting a failed test
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/bin/false
|
||||
ExecStart=/bin/sleep 400
|
5
vendor/github.com/coreos/go-systemd/fixtures/start-stop.service
generated
vendored
5
vendor/github.com/coreos/go-systemd/fixtures/start-stop.service
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
[Unit]
|
||||
Description=start stop test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sleep 400
|
5
vendor/github.com/coreos/go-systemd/fixtures/subscribe-events-set.service
generated
vendored
5
vendor/github.com/coreos/go-systemd/fixtures/subscribe-events-set.service
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
[Unit]
|
||||
Description=start stop test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sleep 400
|
5
vendor/github.com/coreos/go-systemd/fixtures/subscribe-events.service
generated
vendored
5
vendor/github.com/coreos/go-systemd/fixtures/subscribe-events.service
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
[Unit]
|
||||
Description=start stop test
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sleep 400
|
179
vendor/github.com/coreos/go-systemd/journal/journal.go
generated
vendored
179
vendor/github.com/coreos/go-systemd/journal/journal.go
generated
vendored
|
@ -1,179 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package journal provides write bindings to the local systemd journal.
|
||||
// It is implemented in pure Go and connects to the journal directly over its
|
||||
// unix socket.
|
||||
//
|
||||
// To read from the journal, see the "sdjournal" package, which wraps the
|
||||
// sd-journal a C API.
|
||||
//
|
||||
// http://www.freedesktop.org/software/systemd/man/systemd-journald.service.html
|
||||
package journal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Priority of a journal message
|
||||
type Priority int
|
||||
|
||||
const (
|
||||
PriEmerg Priority = iota
|
||||
PriAlert
|
||||
PriCrit
|
||||
PriErr
|
||||
PriWarning
|
||||
PriNotice
|
||||
PriInfo
|
||||
PriDebug
|
||||
)
|
||||
|
||||
var conn net.Conn
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
conn, err = net.Dial("unixgram", "/run/systemd/journal/socket")
|
||||
if err != nil {
|
||||
conn = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Enabled returns true if the local systemd journal is available for logging
|
||||
func Enabled() bool {
|
||||
return conn != nil
|
||||
}
|
||||
|
||||
// Send a message to the local systemd journal. vars is a map of journald
|
||||
// fields to values. Fields must be composed of uppercase letters, numbers,
|
||||
// and underscores, but must not start with an underscore. Within these
|
||||
// restrictions, any arbitrary field name may be used. Some names have special
|
||||
// significance: see the journalctl documentation
|
||||
// (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
|
||||
// for more details. vars may be nil.
|
||||
func Send(message string, priority Priority, vars map[string]string) error {
|
||||
if conn == nil {
|
||||
return journalError("could not connect to journald socket")
|
||||
}
|
||||
|
||||
data := new(bytes.Buffer)
|
||||
appendVariable(data, "PRIORITY", strconv.Itoa(int(priority)))
|
||||
appendVariable(data, "MESSAGE", message)
|
||||
for k, v := range vars {
|
||||
appendVariable(data, k, v)
|
||||
}
|
||||
|
||||
_, err := io.Copy(conn, data)
|
||||
if err != nil && isSocketSpaceError(err) {
|
||||
file, err := tempFd()
|
||||
if err != nil {
|
||||
return journalError(err.Error())
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, data)
|
||||
if err != nil {
|
||||
return journalError(err.Error())
|
||||
}
|
||||
|
||||
rights := syscall.UnixRights(int(file.Fd()))
|
||||
|
||||
/* this connection should always be a UnixConn, but better safe than sorry */
|
||||
unixConn, ok := conn.(*net.UnixConn)
|
||||
if !ok {
|
||||
return journalError("can't send file through non-Unix connection")
|
||||
}
|
||||
unixConn.WriteMsgUnix([]byte{}, rights, nil)
|
||||
} else if err != nil {
|
||||
return journalError(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Print prints a message to the local systemd journal using Send().
|
||||
func Print(priority Priority, format string, a ...interface{}) error {
|
||||
return Send(fmt.Sprintf(format, a...), priority, nil)
|
||||
}
|
||||
|
||||
func appendVariable(w io.Writer, name, value string) {
|
||||
if !validVarName(name) {
|
||||
journalError("variable name contains invalid character, ignoring")
|
||||
}
|
||||
if strings.ContainsRune(value, '\n') {
|
||||
/* When the value contains a newline, we write:
|
||||
* - the variable name, followed by a newline
|
||||
* - the size (in 64bit little endian format)
|
||||
* - the data, followed by a newline
|
||||
*/
|
||||
fmt.Fprintln(w, name)
|
||||
binary.Write(w, binary.LittleEndian, uint64(len(value)))
|
||||
fmt.Fprintln(w, value)
|
||||
} else {
|
||||
/* just write the variable and value all on one line */
|
||||
fmt.Fprintf(w, "%s=%s\n", name, value)
|
||||
}
|
||||
}
|
||||
|
||||
func validVarName(name string) bool {
|
||||
/* The variable name must be in uppercase and consist only of characters,
|
||||
* numbers and underscores, and may not begin with an underscore. (from the docs)
|
||||
*/
|
||||
|
||||
valid := name[0] != '_'
|
||||
for _, c := range name {
|
||||
valid = valid && ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_'
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
func isSocketSpaceError(err error) bool {
|
||||
opErr, ok := err.(*net.OpError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
sysErr, ok := opErr.Err.(syscall.Errno)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return sysErr == syscall.EMSGSIZE || sysErr == syscall.ENOBUFS
|
||||
}
|
||||
|
||||
func tempFd() (*os.File, error) {
|
||||
file, err := ioutil.TempFile("/dev/shm/", "journal.XXXXX")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
syscall.Unlink(file.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func journalError(s string) error {
|
||||
s = "journal error: " + s
|
||||
fmt.Fprintln(os.Stderr, s)
|
||||
return errors.New(s)
|
||||
}
|
108
vendor/github.com/coreos/go-systemd/login1/dbus.go
generated
vendored
108
vendor/github.com/coreos/go-systemd/login1/dbus.go
generated
vendored
|
@ -1,108 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Integration with the systemd logind API. See http://www.freedesktop.org/wiki/Software/systemd/logind/
|
||||
package login1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
)
|
||||
|
||||
const (
|
||||
dbusInterface = "org.freedesktop.login1.Manager"
|
||||
dbusPath = "/org/freedesktop/login1"
|
||||
)
|
||||
|
||||
// Conn is a connection to systemds dbus endpoint.
|
||||
type Conn struct {
|
||||
conn *dbus.Conn
|
||||
object dbus.BusObject
|
||||
}
|
||||
|
||||
// New() establishes a connection to the system bus and authenticates.
|
||||
func New() (*Conn, error) {
|
||||
c := new(Conn)
|
||||
|
||||
if err := c.initConnection(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Conn) initConnection() error {
|
||||
var err error
|
||||
c.conn, err = dbus.SystemBusPrivate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Only use EXTERNAL method, and hardcode the uid (not username)
|
||||
// to avoid a username lookup (which requires a dynamically linked
|
||||
// libc)
|
||||
methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}
|
||||
|
||||
err = c.conn.Auth(methods)
|
||||
if err != nil {
|
||||
c.conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.conn.Hello()
|
||||
if err != nil {
|
||||
c.conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
c.object = c.conn.Object("org.freedesktop.login1", dbus.ObjectPath(dbusPath))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reboot asks logind for a reboot optionally asking for auth.
|
||||
func (c *Conn) Reboot(askForAuth bool) {
|
||||
c.object.Call(dbusInterface+".Reboot", 0, askForAuth)
|
||||
}
|
||||
|
||||
// Inhibit takes inhibition lock in logind.
|
||||
func (c *Conn) Inhibit(what, who, why, mode string) (*os.File, error) {
|
||||
var fd dbus.UnixFD
|
||||
|
||||
err := c.object.Call(dbusInterface+".Inhibit", 0, what, who, why, mode).Store(&fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return os.NewFile(uintptr(fd), "inhibit"), nil
|
||||
}
|
||||
|
||||
// Subscribe to signals on the logind dbus
|
||||
func (c *Conn) Subscribe(members ...string) chan *dbus.Signal {
|
||||
for _, member := range members {
|
||||
c.conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
||||
fmt.Sprintf("type='signal',interface='org.freedesktop.login1.Manager',member='%s'", member))
|
||||
}
|
||||
ch := make(chan *dbus.Signal, 10)
|
||||
c.conn.Signal(ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
// PowerOff asks logind for a power off optionally asking for auth.
|
||||
func (c *Conn) PowerOff(askForAuth bool) {
|
||||
c.object.Call(dbusInterface+".PowerOff", 0, askForAuth)
|
||||
}
|
28
vendor/github.com/coreos/go-systemd/login1/dbus_test.go
generated
vendored
28
vendor/github.com/coreos/go-systemd/login1/dbus_test.go
generated
vendored
|
@ -1,28 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package login1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestNew ensures that New() works without errors.
|
||||
func TestNew(t *testing.T) {
|
||||
_, err := New()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
81
vendor/github.com/coreos/go-systemd/machine1/dbus.go
generated
vendored
81
vendor/github.com/coreos/go-systemd/machine1/dbus.go
generated
vendored
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 CoreOS Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Integration with the systemd machined API. See http://www.freedesktop.org/wiki/Software/systemd/machined/
|
||||
package machine1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
)
|
||||
|
||||
const (
|
||||
dbusInterface = "org.freedesktop.machine1.Manager"
|
||||
dbusPath = "/org/freedesktop/machine1"
|
||||
)
|
||||
|
||||
// Conn is a connection to systemds dbus endpoint.
|
||||
type Conn struct {
|
||||
conn *dbus.Conn
|
||||
object dbus.BusObject
|
||||
}
|
||||
|
||||
// New() establishes a connection to the system bus and authenticates.
|
||||
func New() (*Conn, error) {
|
||||
c := new(Conn)
|
||||
|
||||
if err := c.initConnection(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Conn) initConnection() error {
|
||||
var err error
|
||||
c.conn, err = dbus.SystemBusPrivate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Only use EXTERNAL method, and hardcode the uid (not username)
|
||||
// to avoid a username lookup (which requires a dynamically linked
|
||||
// libc)
|
||||
methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}
|
||||
|
||||
err = c.conn.Auth(methods)
|
||||
if err != nil {
|
||||
c.conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.conn.Hello()
|
||||
if err != nil {
|
||||
c.conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
c.object = c.conn.Object("org.freedesktop.machine1", dbus.ObjectPath(dbusPath))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterMachine registers the container with the systemd-machined
|
||||
func (c *Conn) RegisterMachine(name string, id []byte, service string, class string, pid int, root_directory string) error {
|
||||
return c.object.Call(dbusInterface+".RegisterMachine", 0, name, id, service, class, uint32(pid), root_directory).Err
|
||||
}
|
30
vendor/github.com/coreos/go-systemd/machine1/dbus_test.go
generated
vendored
30
vendor/github.com/coreos/go-systemd/machine1/dbus_test.go
generated
vendored
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 CoreOS Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package machine1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestNew ensures that New() works without errors.
|
||||
func TestNew(t *testing.T) {
|
||||
_, err := New()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
66
vendor/github.com/coreos/go-systemd/sdjournal/functions.go
generated
vendored
66
vendor/github.com/coreos/go-systemd/sdjournal/functions.go
generated
vendored
|
@ -1,66 +0,0 @@
|
|||
// 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
36
vendor/github.com/coreos/go-systemd/sdjournal/functions_test.go
generated
vendored
|
@ -1,36 +0,0 @@
|
|||
// 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")
|
||||
}
|
||||
}
|
1024
vendor/github.com/coreos/go-systemd/sdjournal/journal.go
generated
vendored
1024
vendor/github.com/coreos/go-systemd/sdjournal/journal.go
generated
vendored
File diff suppressed because it is too large
Load diff
399
vendor/github.com/coreos/go-systemd/sdjournal/journal_test.go
generated
vendored
399
vendor/github.com/coreos/go-systemd/sdjournal/journal_test.go
generated
vendored
|
@ -1,399 +0,0 @@
|
|||
// 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 (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-systemd/journal"
|
||||
)
|
||||
|
||||
func TestJournalFollow(t *testing.T) {
|
||||
r, err := NewJournalReader(JournalReaderConfig{
|
||||
Since: time.Duration(-15) * time.Second,
|
||||
Matches: []Match{
|
||||
{
|
||||
Field: SD_JOURNAL_FIELD_SYSTEMD_UNIT,
|
||||
Value: "NetworkManager.service",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error opening journal: %s", err)
|
||||
}
|
||||
|
||||
if r == nil {
|
||||
t.Fatal("Got a nil reader")
|
||||
}
|
||||
|
||||
defer r.Close()
|
||||
|
||||
// start writing some test entries
|
||||
done := make(chan struct{}, 1)
|
||||
defer close(done)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
default:
|
||||
if err := journal.Print(journal.PriInfo, "test message %s", time.Now()); err != nil {
|
||||
t.Fatalf("Error writing to journal: %s", err)
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// and follow the reader synchronously
|
||||
timeout := time.Duration(5) * time.Second
|
||||
if err = r.Follow(time.After(timeout), os.Stdout); err != ErrExpired {
|
||||
t.Fatalf("Error during follow: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJournalGetUsage(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()
|
||||
|
||||
_, err = j.GetUsage()
|
||||
|
||||
if err != nil {
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
func TestJournalGetUniqueValues(t *testing.T) {
|
||||
j, err := NewJournal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer j.Close()
|
||||
|
||||
uniqueString := generateRandomField(20)
|
||||
testEntries := []string{"A", "B", "C", "D"}
|
||||
for _, v := range testEntries {
|
||||
err := journal.Send("TEST: "+uniqueString, journal.PriInfo, map[string]string{uniqueString: v})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add proper `waitOnMatch` function which should wait for journal entry with filter to commit.
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
|
||||
values, err := j.GetUniqueValues(uniqueString)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(values) != len(testEntries) {
|
||||
t.Fatalf("Expect %d entries. Got %d", len(testEntries), len(values))
|
||||
}
|
||||
|
||||
if !contains(values, "A") || !contains(values, "B") || !contains(values, "C") || !contains(values, "D") {
|
||||
t.Fatalf("Expect 4 values for %s field: A,B,C,D. Got %s", uniqueString, values)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(s []string, v string) bool {
|
||||
for _, entry := range s {
|
||||
if entry == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func generateRandomField(n int) string {
|
||||
letters := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
s := make([]rune, n)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
for i := range s {
|
||||
s[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(s)
|
||||
}
|
260
vendor/github.com/coreos/go-systemd/sdjournal/read.go
generated
vendored
260
vendor/github.com/coreos/go-systemd/sdjournal/read.go
generated
vendored
|
@ -1,260 +0,0 @@
|
|||
// 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrExpired = errors.New("Timeout expired")
|
||||
)
|
||||
|
||||
// JournalReaderConfig represents options to drive the behavior of a JournalReader.
|
||||
type JournalReaderConfig struct {
|
||||
// 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.
|
||||
Matches []Match
|
||||
|
||||
// If not empty, the journal instance will point to a journal residing
|
||||
// in this directory. The supplied path may be relative or absolute.
|
||||
Path string
|
||||
}
|
||||
|
||||
// JournalReader is an io.ReadCloser which provides a simple interface for iterating through the
|
||||
// systemd journal. A JournalReader is not safe for concurrent use by multiple goroutines.
|
||||
type JournalReader struct {
|
||||
journal *Journal
|
||||
msgReader *strings.Reader
|
||||
}
|
||||
|
||||
// NewJournalReader creates a new JournalReader with configuration options that are similar to the
|
||||
// systemd journalctl tool's iteration and filtering features.
|
||||
func NewJournalReader(config JournalReaderConfig) (*JournalReader, error) {
|
||||
r := &JournalReader{}
|
||||
|
||||
// Open the journal
|
||||
var err error
|
||||
if config.Path != "" {
|
||||
r.journal, err = NewJournalFromDir(config.Path)
|
||||
} else {
|
||||
r.journal, err = NewJournal()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add any supplied matches
|
||||
for _, m := range config.Matches {
|
||||
r.journal.AddMatch(m.String())
|
||||
}
|
||||
|
||||
// Set the start position based on options
|
||||
if config.Since != 0 {
|
||||
// Start based on a relative time
|
||||
start := time.Now().Add(config.Since)
|
||||
if err := r.journal.SeekRealtimeUsec(uint64(start.UnixNano() / 1000)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if config.NumFromTail != 0 {
|
||||
// Start based on a number of lines before the tail
|
||||
if err := r.journal.SeekTail(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if r.msgReader == nil {
|
||||
var c uint64
|
||||
|
||||
// Advance the journal cursor. It has to be called at least one time
|
||||
// before reading
|
||||
c, err = r.journal.Next()
|
||||
|
||||
// An unexpected error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// EOF detection
|
||||
if c == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// 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
|
||||
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 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) {
|
||||
|
||||
// Process journal entries and events. Entries are flushed until the tail or
|
||||
// timeout is reached, and then we wait for new events or the timeout.
|
||||
var msg = make([]byte, 64*1<<(10))
|
||||
process:
|
||||
for {
|
||||
c, err := r.Read(msg)
|
||||
if err != nil && err != io.EOF {
|
||||
break process
|
||||
}
|
||||
|
||||
select {
|
||||
case <-until:
|
||||
return ErrExpired
|
||||
default:
|
||||
if c > 0 {
|
||||
if _, err = writer.Write(msg[:c]); err != nil {
|
||||
break process
|
||||
}
|
||||
continue process
|
||||
}
|
||||
}
|
||||
|
||||
// We're at the tail, so wait for new events or time out.
|
||||
// Holds journal events to process. Tightly bounded for now unless there's a
|
||||
// reason to unblock the journal watch routine more quickly.
|
||||
events := make(chan int, 1)
|
||||
pollDone := make(chan bool, 1)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-pollDone:
|
||||
return
|
||||
default:
|
||||
events <- r.journal.Wait(time.Duration(1) * time.Second)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-until:
|
||||
pollDone <- true
|
||||
return ErrExpired
|
||||
case e := <-events:
|
||||
pollDone <- true
|
||||
switch e {
|
||||
case SD_JOURNAL_NOP, SD_JOURNAL_APPEND, SD_JOURNAL_INVALIDATE:
|
||||
// TODO: need to account for any of these?
|
||||
default:
|
||||
log.Printf("Received unknown event: %d\n", e)
|
||||
}
|
||||
continue process
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// buildMessage returns a string representing the current journal entry in a simple format which
|
||||
// includes the entry timestamp and MESSAGE field.
|
||||
func (r *JournalReader) buildMessage() (string, error) {
|
||||
var msg string
|
||||
var usec uint64
|
||||
var err error
|
||||
|
||||
if msg, err = r.journal.GetData("MESSAGE"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if usec, err = r.journal.GetRealtimeUsec(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
timestamp := time.Unix(0, int64(usec)*int64(time.Microsecond))
|
||||
|
||||
return fmt.Sprintf("%s %s\n", timestamp, msg), nil
|
||||
}
|
87
vendor/github.com/coreos/go-systemd/test
generated
vendored
87
vendor/github.com/coreos/go-systemd/test
generated
vendored
|
@ -1,87 +0,0 @@
|
|||
#!/bin/bash -e
|
||||
#
|
||||
# Run all tests
|
||||
# ./test
|
||||
# ./test -v
|
||||
#
|
||||
# Run tests for one package
|
||||
# PKG=./foo ./test
|
||||
# PKG=bar ./test
|
||||
#
|
||||
|
||||
# Invoke ./cover for HTML output
|
||||
COVER=${COVER:-"-cover"}
|
||||
|
||||
PROJ="go-systemd"
|
||||
ORG_PATH="github.com/coreos"
|
||||
REPO_PATH="${ORG_PATH}/${PROJ}"
|
||||
|
||||
# As a convenience, set up a self-contained GOPATH if none set
|
||||
if [ -z "$GOPATH" ]; then
|
||||
if [ ! -h gopath/src/${REPO_PATH} ]; then
|
||||
mkdir -p gopath/src/${ORG_PATH}
|
||||
ln -s ../../../.. gopath/src/${REPO_PATH} || exit 255
|
||||
fi
|
||||
export GOPATH=${PWD}/gopath
|
||||
go get -u github.com/godbus/dbus
|
||||
go get -u github.com/coreos/pkg/dlopen
|
||||
fi
|
||||
|
||||
TESTABLE="activation daemon journal login1 machine1 unit"
|
||||
FORMATTABLE="$TESTABLE sdjournal dbus"
|
||||
if [ -e "/run/systemd/system/" ]; then
|
||||
TESTABLE="${TESTABLE} sdjournal"
|
||||
if [ "$EUID" == "0" ]; then
|
||||
# testing actual systemd behaviour requires root
|
||||
TESTABLE="${TESTABLE} dbus"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# user has not provided PKG override
|
||||
if [ -z "$PKG" ]; then
|
||||
TEST=$TESTABLE
|
||||
FMT=$FORMATTABLE
|
||||
|
||||
# user has provided PKG override
|
||||
else
|
||||
# strip out slashes and dots from PKG=./foo/
|
||||
TEST=${PKG//\//}
|
||||
TEST=${TEST//./}
|
||||
|
||||
# only run gofmt on packages provided by user
|
||||
FMT="$TEST"
|
||||
fi
|
||||
|
||||
# split TEST into an array and prepend REPO_PATH to each local package
|
||||
split=(${TEST// / })
|
||||
TEST=${split[@]/#/${REPO_PATH}/}
|
||||
|
||||
echo "Running tests..."
|
||||
go test -v ${COVER} $@ ${TEST}
|
||||
|
||||
echo "Checking gofmt..."
|
||||
fmtRes=$(gofmt -l $FMT)
|
||||
if [ -n "${fmtRes}" ]; then
|
||||
echo -e "gofmt checking failed:\n${fmtRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo "Checking govet..."
|
||||
vetRes=$(go vet $TEST)
|
||||
if [ -n "${vetRes}" ]; then
|
||||
echo -e "govet checking failed:\n${vetRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo "Checking for license header..."
|
||||
licRes=$(for file in $(find . -type f -iname '*.go' ! -path './gopath/*'); do
|
||||
head -n3 "${file}" | grep -Eq "(Copyright|generated|GENERATED)" || echo -e " ${file}"
|
||||
done;)
|
||||
if [ -n "${licRes}" ]; then
|
||||
echo -e "license header checking failed:\n${licRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
|
||||
echo "Success"
|
276
vendor/github.com/coreos/go-systemd/unit/deserialize.go
generated
vendored
276
vendor/github.com/coreos/go-systemd/unit/deserialize.go
generated
vendored
|
@ -1,276 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
// SYSTEMD_LINE_MAX mimics the maximum line length that systemd can use.
|
||||
// On typical systemd platforms (i.e. modern Linux), this will most
|
||||
// commonly be 2048, so let's use that as a sanity check.
|
||||
// Technically, we should probably pull this at runtime:
|
||||
// SYSTEMD_LINE_MAX = int(C.sysconf(C.__SC_LINE_MAX))
|
||||
// but this would introduce an (unfortunate) dependency on cgo
|
||||
SYSTEMD_LINE_MAX = 2048
|
||||
|
||||
// characters that systemd considers indicate a newline
|
||||
SYSTEMD_NEWLINE = "\r\n"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrLineTooLong = fmt.Errorf("line too long (max %d bytes)", SYSTEMD_LINE_MAX)
|
||||
)
|
||||
|
||||
// Deserialize parses a systemd unit file into a list of UnitOption objects.
|
||||
func Deserialize(f io.Reader) (opts []*UnitOption, err error) {
|
||||
lexer, optchan, errchan := newLexer(f)
|
||||
go lexer.lex()
|
||||
|
||||
for opt := range optchan {
|
||||
opts = append(opts, &(*opt))
|
||||
}
|
||||
|
||||
err = <-errchan
|
||||
return opts, err
|
||||
}
|
||||
|
||||
func newLexer(f io.Reader) (*lexer, <-chan *UnitOption, <-chan error) {
|
||||
optchan := make(chan *UnitOption)
|
||||
errchan := make(chan error, 1)
|
||||
buf := bufio.NewReader(f)
|
||||
|
||||
return &lexer{buf, optchan, errchan, ""}, optchan, errchan
|
||||
}
|
||||
|
||||
type lexer struct {
|
||||
buf *bufio.Reader
|
||||
optchan chan *UnitOption
|
||||
errchan chan error
|
||||
section string
|
||||
}
|
||||
|
||||
func (l *lexer) lex() {
|
||||
var err error
|
||||
defer func() {
|
||||
close(l.optchan)
|
||||
close(l.errchan)
|
||||
}()
|
||||
next := l.lexNextSection
|
||||
for next != nil {
|
||||
if l.buf.Buffered() >= SYSTEMD_LINE_MAX {
|
||||
// systemd truncates lines longer than LINE_MAX
|
||||
// https://bugs.freedesktop.org/show_bug.cgi?id=85308
|
||||
// Rather than allowing this to pass silently, let's
|
||||
// explicitly gate people from encountering this
|
||||
line, err := l.buf.Peek(SYSTEMD_LINE_MAX)
|
||||
if err != nil {
|
||||
l.errchan <- err
|
||||
return
|
||||
}
|
||||
if bytes.IndexAny(line, SYSTEMD_NEWLINE) == -1 {
|
||||
l.errchan <- ErrLineTooLong
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
next, err = next()
|
||||
if err != nil {
|
||||
l.errchan <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type lexStep func() (lexStep, error)
|
||||
|
||||
func (l *lexer) lexSectionName() (lexStep, error) {
|
||||
sec, err := l.buf.ReadBytes(']')
|
||||
if err != nil {
|
||||
return nil, errors.New("unable to find end of section")
|
||||
}
|
||||
|
||||
return l.lexSectionSuffixFunc(string(sec[:len(sec)-1])), nil
|
||||
}
|
||||
|
||||
func (l *lexer) lexSectionSuffixFunc(section string) lexStep {
|
||||
return func() (lexStep, error) {
|
||||
garbage, _, err := l.toEOL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
garbage = bytes.TrimSpace(garbage)
|
||||
if len(garbage) > 0 {
|
||||
return nil, fmt.Errorf("found garbage after section name %s: %v", l.section, garbage)
|
||||
}
|
||||
|
||||
return l.lexNextSectionOrOptionFunc(section), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lexer) ignoreLineFunc(next lexStep) lexStep {
|
||||
return func() (lexStep, error) {
|
||||
for {
|
||||
line, _, err := l.toEOL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
line = bytes.TrimSuffix(line, []byte{' '})
|
||||
|
||||
// lack of continuation means this line has been exhausted
|
||||
if !bytes.HasSuffix(line, []byte{'\\'}) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// reached end of buffer, safe to exit
|
||||
return next, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lexer) lexNextSection() (lexStep, error) {
|
||||
r, _, err := l.buf.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r == '[' {
|
||||
return l.lexSectionName, nil
|
||||
} else if isComment(r) {
|
||||
return l.ignoreLineFunc(l.lexNextSection), nil
|
||||
}
|
||||
|
||||
return l.lexNextSection, nil
|
||||
}
|
||||
|
||||
func (l *lexer) lexNextSectionOrOptionFunc(section string) lexStep {
|
||||
return func() (lexStep, error) {
|
||||
r, _, err := l.buf.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if unicode.IsSpace(r) {
|
||||
return l.lexNextSectionOrOptionFunc(section), nil
|
||||
} else if r == '[' {
|
||||
return l.lexSectionName, nil
|
||||
} else if isComment(r) {
|
||||
return l.ignoreLineFunc(l.lexNextSectionOrOptionFunc(section)), nil
|
||||
}
|
||||
|
||||
l.buf.UnreadRune()
|
||||
return l.lexOptionNameFunc(section), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lexer) lexOptionNameFunc(section string) lexStep {
|
||||
return func() (lexStep, error) {
|
||||
var partial bytes.Buffer
|
||||
for {
|
||||
r, _, err := l.buf.ReadRune()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r == '\n' || r == '\r' {
|
||||
return nil, errors.New("unexpected newline encountered while parsing option name")
|
||||
}
|
||||
|
||||
if r == '=' {
|
||||
break
|
||||
}
|
||||
|
||||
partial.WriteRune(r)
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(partial.String())
|
||||
return l.lexOptionValueFunc(section, name, bytes.Buffer{}), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lexer) lexOptionValueFunc(section, name string, partial bytes.Buffer) lexStep {
|
||||
return func() (lexStep, error) {
|
||||
for {
|
||||
line, eof, err := l.toEOL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(bytes.TrimSpace(line)) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
partial.Write(line)
|
||||
|
||||
// lack of continuation means this value has been exhausted
|
||||
idx := bytes.LastIndex(line, []byte{'\\'})
|
||||
if idx == -1 || idx != (len(line)-1) {
|
||||
break
|
||||
}
|
||||
|
||||
if !eof {
|
||||
partial.WriteRune('\n')
|
||||
}
|
||||
|
||||
return l.lexOptionValueFunc(section, name, partial), nil
|
||||
}
|
||||
|
||||
val := partial.String()
|
||||
if strings.HasSuffix(val, "\n") {
|
||||
// A newline was added to the end, so the file didn't end with a backslash.
|
||||
// => Keep the newline
|
||||
val = strings.TrimSpace(val) + "\n"
|
||||
} else {
|
||||
val = strings.TrimSpace(val)
|
||||
}
|
||||
l.optchan <- &UnitOption{Section: section, Name: name, Value: val}
|
||||
|
||||
return l.lexNextSectionOrOptionFunc(section), nil
|
||||
}
|
||||
}
|
||||
|
||||
// toEOL reads until the end-of-line or end-of-file.
|
||||
// Returns (data, EOFfound, error)
|
||||
func (l *lexer) toEOL() ([]byte, bool, error) {
|
||||
line, err := l.buf.ReadBytes('\n')
|
||||
// ignore EOF here since it's roughly equivalent to EOL
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
line = bytes.TrimSuffix(line, []byte{'\r'})
|
||||
line = bytes.TrimSuffix(line, []byte{'\n'})
|
||||
|
||||
return line, err == io.EOF, nil
|
||||
}
|
||||
|
||||
func isComment(r rune) bool {
|
||||
return r == '#' || r == ';'
|
||||
}
|
381
vendor/github.com/coreos/go-systemd/unit/deserialize_test.go
generated
vendored
381
vendor/github.com/coreos/go-systemd/unit/deserialize_test.go
generated
vendored
|
@ -1,381 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDeserialize(t *testing.T) {
|
||||
tests := []struct {
|
||||
input []byte
|
||||
output []*UnitOption
|
||||
}{
|
||||
// multiple options underneath a section
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description=Foo
|
||||
Description=Bar
|
||||
Requires=baz.service
|
||||
After=baz.service
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Unit", "Description", "Bar"},
|
||||
&UnitOption{"Unit", "Requires", "baz.service"},
|
||||
&UnitOption{"Unit", "After", "baz.service"},
|
||||
},
|
||||
},
|
||||
|
||||
// multiple sections
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description=Foo
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/sleep infinity
|
||||
|
||||
[X-Third-Party]
|
||||
Pants=on
|
||||
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Service", "ExecStart", "/usr/bin/sleep infinity"},
|
||||
&UnitOption{"X-Third-Party", "Pants", "on"},
|
||||
},
|
||||
},
|
||||
|
||||
// multiple sections with no options
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
[Service]
|
||||
[X-Third-Party]
|
||||
`),
|
||||
[]*UnitOption{},
|
||||
},
|
||||
|
||||
// multiple values not special-cased
|
||||
{
|
||||
[]byte(`[Service]
|
||||
Environment= "FOO=BAR" "BAZ=QUX"
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Service", "Environment", "\"FOO=BAR\" \"BAZ=QUX\""},
|
||||
},
|
||||
},
|
||||
|
||||
// line continuations unmodified
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description= Unnecessarily wrapped \
|
||||
words here
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", `Unnecessarily wrapped \
|
||||
words here`},
|
||||
},
|
||||
},
|
||||
|
||||
// comments ignored
|
||||
{
|
||||
[]byte(`; comment alpha
|
||||
# comment bravo
|
||||
[Unit]
|
||||
; comment charlie
|
||||
# comment delta
|
||||
#Description=Foo
|
||||
Description=Bar
|
||||
; comment echo
|
||||
# comment foxtrot
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// apparent comment lines inside of line continuations not ignored
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description=Bar\
|
||||
# comment alpha
|
||||
|
||||
Description=Bar\
|
||||
# comment bravo \
|
||||
Baz
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Bar\\\n# comment alpha"},
|
||||
&UnitOption{"Unit", "Description", "Bar\\\n# comment bravo \\\nBaz"},
|
||||
},
|
||||
},
|
||||
|
||||
// options outside of sections are ignored
|
||||
{
|
||||
[]byte(`Description=Foo
|
||||
[Unit]
|
||||
Description=Bar
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// garbage outside of sections are ignored
|
||||
{
|
||||
[]byte(`<<<<<<<<
|
||||
[Unit]
|
||||
Description=Bar
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// garbage used as unit option
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
<<<<<<<<=Bar
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "<<<<<<<<", "Bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// option name with spaces are valid
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Some Thing = Bar
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Some Thing", "Bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// lack of trailing newline doesn't cause problem for non-continued file
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description=Bar`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// unit file with continuation but no following line is ok, too
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description=Bar \`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Bar \\"},
|
||||
},
|
||||
},
|
||||
|
||||
// Assert utf8 characters are preserved
|
||||
{
|
||||
[]byte(`[©]
|
||||
µ☃=ÇôrèÕ$`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"©", "µ☃", "ÇôrèÕ$"},
|
||||
},
|
||||
},
|
||||
|
||||
// whitespace removed around option name
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description =words here
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "words here"},
|
||||
},
|
||||
},
|
||||
|
||||
// whitespace around option value stripped
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description= words here `),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "words here"},
|
||||
},
|
||||
},
|
||||
|
||||
// whitespace around option value stripped, regardless of continuation
|
||||
{
|
||||
[]byte(`[Unit]
|
||||
Description= words here \
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "words here \\\n"},
|
||||
},
|
||||
},
|
||||
|
||||
// backslash not considered continuation if followed by text
|
||||
{
|
||||
[]byte(`[Service]
|
||||
ExecStart=/bin/bash -c "while true; do echo \"ping\"; sleep 1; done"
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Service", "ExecStart", `/bin/bash -c "while true; do echo \"ping\"; sleep 1; done"`},
|
||||
},
|
||||
},
|
||||
|
||||
// backslash not considered continuation if followed by whitespace, but still trimmed
|
||||
{
|
||||
[]byte(`[Service]
|
||||
ExecStart=/bin/bash echo poof \ `),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Service", "ExecStart", `/bin/bash echo poof \`},
|
||||
},
|
||||
},
|
||||
// a long unit file line that's just equal to the maximum permitted length
|
||||
{
|
||||
[]byte(`[Service]
|
||||
ExecStart=/bin/bash -c "echo ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Service", "ExecStart", `/bin/bash -c "echo ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."`},
|
||||
},
|
||||
},
|
||||
// the same, but with a trailing newline
|
||||
{
|
||||
[]byte(`[Service]
|
||||
ExecStart=/bin/bash -c "echo ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."
|
||||
Option=value
|
||||
`),
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Service", "ExecStart", `/bin/bash -c "echo ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."`},
|
||||
&UnitOption{"Service", "Option", "value"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert := func(expect, output []*UnitOption) error {
|
||||
if len(expect) != len(output) {
|
||||
return fmt.Errorf("expected %d items, got %d", len(expect), len(output))
|
||||
}
|
||||
|
||||
for i, _ := range expect {
|
||||
if !reflect.DeepEqual(expect[i], output[i]) {
|
||||
return fmt.Errorf("item %d: expected %v, got %v", i, expect[i], output[i])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
output, err := Deserialize(bytes.NewReader(tt.input))
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error parsing unit: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = assert(tt.output, output)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: %v", i, err)
|
||||
t.Log("Expected options:")
|
||||
logUnitOptionSlice(t, tt.output)
|
||||
t.Log("Actual options:")
|
||||
logUnitOptionSlice(t, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeserializeFail(t *testing.T) {
|
||||
tests := [][]byte{
|
||||
// malformed section header
|
||||
[]byte(`[Unit
|
||||
Description=Foo
|
||||
`),
|
||||
|
||||
// garbage following section header
|
||||
[]byte(`[Unit] pants
|
||||
Description=Foo
|
||||
`),
|
||||
|
||||
// option without value
|
||||
[]byte(`[Unit]
|
||||
Description
|
||||
`),
|
||||
|
||||
// garbage inside of section
|
||||
[]byte(`[Unit]
|
||||
<<<<<<
|
||||
Description=Foo
|
||||
`),
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
output, err := Deserialize(bytes.NewReader(tt))
|
||||
if err == nil {
|
||||
t.Errorf("case %d: unexpected nil error", i)
|
||||
t.Log("Output:")
|
||||
logUnitOptionSlice(t, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func logUnitOptionSlice(t *testing.T, opts []*UnitOption) {
|
||||
for idx, opt := range opts {
|
||||
t.Logf("%d: %v", idx, opt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeserializeLineTooLong(t *testing.T) {
|
||||
tests := [][]byte{
|
||||
// section header that's far too long
|
||||
[]byte(`[Seeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeervice]
|
||||
`),
|
||||
// sane-looking unit file with a line just greater than the maximum allowed (currently, 2048)
|
||||
[]byte(`[Service]
|
||||
ExecStart=/bin/bash -c "echo ..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."
|
||||
`),
|
||||
// sane-looking unit file with option value way too long
|
||||
[]byte(`
|
||||
# test unit file
|
||||
|
||||
[Service]
|
||||
ExecStartPre=-/usr/bin/docker rm %p
|
||||
ExecStartPre=-/usr/bin/docker pull busybox
|
||||
ExecStart=/usr/bin/docker run --rm --name %p --net=host \
|
||||
-e "test=1123t" \
|
||||
-e "test=1123t" \
|
||||
-e "fiz=1123t" \
|
||||
-e "buz=1123t" \
|
||||
-e "FOO=BARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBABARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARRBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBAR"BARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBABARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARRBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBARBAR" \
|
||||
busybox sleep 10
|
||||
ExecStop=-/usr/bin/docker kill %p
|
||||
SyslogIdentifier=busybox
|
||||
Restart=always
|
||||
RestartSec=10s
|
||||
`),
|
||||
// single arbitrary line that's way too long
|
||||
[]byte(`arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 character arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 character arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 character arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 character arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters arbitrary and extraordinarily long line that is far greater than 2048 characters`),
|
||||
// sane-looking unit file with option name way too long
|
||||
[]byte(`[Service]
|
||||
ExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStartExecStart=/bin/true
|
||||
`),
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
output, err := Deserialize(bytes.NewReader(tt))
|
||||
if err != ErrLineTooLong {
|
||||
t.Errorf("case %d: unexpected err: %v", i, err)
|
||||
t.Log("Output:")
|
||||
logUnitOptionSlice(t, output)
|
||||
}
|
||||
}
|
||||
}
|
88
vendor/github.com/coreos/go-systemd/unit/end_to_end_test.go
generated
vendored
88
vendor/github.com/coreos/go-systemd/unit/end_to_end_test.go
generated
vendored
|
@ -1,88 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDeserializeAndReserialize(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
wout string
|
||||
}{
|
||||
{
|
||||
`[Service]
|
||||
ExecStart=/bin/bash -c "while true; do echo \"ping\"; sleep 1; done"
|
||||
`,
|
||||
`[Service]
|
||||
ExecStart=/bin/bash -c "while true; do echo \"ping\"; sleep 1; done"
|
||||
`},
|
||||
{
|
||||
`[Unit]
|
||||
Description= Unnecessarily wrapped \
|
||||
words here`,
|
||||
`[Unit]
|
||||
Description=Unnecessarily wrapped \
|
||||
words here
|
||||
`,
|
||||
},
|
||||
{
|
||||
`[Unit]
|
||||
Description=Demo \
|
||||
|
||||
Requires=docker.service
|
||||
`,
|
||||
`[Unit]
|
||||
Description=Demo \
|
||||
|
||||
Requires=docker.service
|
||||
`,
|
||||
},
|
||||
{
|
||||
`; comment alpha
|
||||
# comment bravo
|
||||
[Unit]
|
||||
; comment charlie
|
||||
# comment delta
|
||||
#Description=Foo
|
||||
Description=Bar
|
||||
; comment echo
|
||||
# comment foxtrot
|
||||
`,
|
||||
`[Unit]
|
||||
Description=Bar
|
||||
`},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
ds, err := Deserialize(bytes.NewBufferString(tt.in))
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error parsing unit: %v", i, err)
|
||||
continue
|
||||
}
|
||||
out, err := ioutil.ReadAll(Serialize(ds))
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error serializing unit: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if g := string(out); g != tt.wout {
|
||||
t.Errorf("case %d: incorrect output", i)
|
||||
t.Logf("Expected:\n%#v", tt.wout)
|
||||
t.Logf("Actual:\n%#v", g)
|
||||
}
|
||||
}
|
||||
}
|
116
vendor/github.com/coreos/go-systemd/unit/escape.go
generated
vendored
116
vendor/github.com/coreos/go-systemd/unit/escape.go
generated
vendored
|
@ -1,116 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Implements systemd-escape [--unescape] [--path]
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
allowed = `:_.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`
|
||||
)
|
||||
|
||||
// If isPath is true:
|
||||
// We remove redundant '/'s, the leading '/', and trailing '/'.
|
||||
// If the result is empty, a '/' is inserted.
|
||||
//
|
||||
// We always:
|
||||
// Replace the following characters with `\x%x`:
|
||||
// Leading `.`
|
||||
// `-`, `\`, and anything not in this set: `:-_.\[0-9a-zA-Z]`
|
||||
// Replace '/' with '-'.
|
||||
func escape(unescaped string, isPath bool) string {
|
||||
e := []byte{}
|
||||
inSlashes := false
|
||||
start := true
|
||||
for i := 0; i < len(unescaped); i++ {
|
||||
c := unescaped[i]
|
||||
if isPath {
|
||||
if c == '/' {
|
||||
inSlashes = true
|
||||
continue
|
||||
} else if inSlashes {
|
||||
inSlashes = false
|
||||
if !start {
|
||||
e = append(e, '-')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c == '/' {
|
||||
e = append(e, '-')
|
||||
} else if start && c == '.' || strings.IndexByte(allowed, c) == -1 {
|
||||
e = append(e, []byte(fmt.Sprintf(`\x%x`, c))...)
|
||||
} else {
|
||||
e = append(e, c)
|
||||
}
|
||||
start = false
|
||||
}
|
||||
if isPath && len(e) == 0 {
|
||||
e = append(e, '-')
|
||||
}
|
||||
return string(e)
|
||||
}
|
||||
|
||||
// If isPath is true:
|
||||
// We always return a string beginning with '/'.
|
||||
//
|
||||
// We always:
|
||||
// Replace '-' with '/'.
|
||||
// Replace `\x%x` with the value represented in hex.
|
||||
func unescape(escaped string, isPath bool) string {
|
||||
u := []byte{}
|
||||
for i := 0; i < len(escaped); i++ {
|
||||
c := escaped[i]
|
||||
if c == '-' {
|
||||
c = '/'
|
||||
} else if c == '\\' && len(escaped)-i >= 4 && escaped[i+1] == 'x' {
|
||||
n, err := strconv.ParseInt(escaped[i+2:i+4], 16, 8)
|
||||
if err == nil {
|
||||
c = byte(n)
|
||||
i += 3
|
||||
}
|
||||
}
|
||||
u = append(u, c)
|
||||
}
|
||||
if isPath && (len(u) == 0 || u[0] != '/') {
|
||||
u = append([]byte("/"), u...)
|
||||
}
|
||||
return string(u)
|
||||
}
|
||||
|
||||
// UnitNameEscape escapes a string as `systemd-escape` would
|
||||
func UnitNameEscape(unescaped string) string {
|
||||
return escape(unescaped, false)
|
||||
}
|
||||
|
||||
// UnitNameUnescape unescapes a string as `systemd-escape --unescape` would
|
||||
func UnitNameUnescape(escaped string) string {
|
||||
return unescape(escaped, false)
|
||||
}
|
||||
|
||||
// UnitNamePathEscape escapes a string as `systemd-escape --path` would
|
||||
func UnitNamePathEscape(unescaped string) string {
|
||||
return escape(unescaped, true)
|
||||
}
|
||||
|
||||
// UnitNamePathUnescape unescapes a string as `systemd-escape --path --unescape` would
|
||||
func UnitNamePathUnescape(escaped string) string {
|
||||
return unescape(escaped, true)
|
||||
}
|
211
vendor/github.com/coreos/go-systemd/unit/escape_test.go
generated
vendored
211
vendor/github.com/coreos/go-systemd/unit/escape_test.go
generated
vendored
|
@ -1,211 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitNameEscape(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
out string
|
||||
isPath bool
|
||||
}{
|
||||
// turn empty string path into escaped /
|
||||
{
|
||||
in: "",
|
||||
out: "-",
|
||||
isPath: true,
|
||||
},
|
||||
// turn redundant ////s into single escaped /
|
||||
{
|
||||
in: "/////////",
|
||||
out: "-",
|
||||
isPath: true,
|
||||
},
|
||||
// remove all redundant ////s
|
||||
{
|
||||
in: "///foo////bar/////tail//////",
|
||||
out: "foo-bar-tail",
|
||||
isPath: true,
|
||||
},
|
||||
// leave empty string empty
|
||||
{
|
||||
in: "",
|
||||
out: "",
|
||||
isPath: false,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: ".",
|
||||
out: `\x2e`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: "/.",
|
||||
out: `\x2e`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: "/////////.",
|
||||
out: `\x2e`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: "/////////.///////////////",
|
||||
out: `\x2e`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: ".....",
|
||||
out: `\x2e....`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: "/.foo/.bar",
|
||||
out: `\x2efoo-.bar`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: ".foo/.bar",
|
||||
out: `\x2efoo-.bar`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape leading dot
|
||||
{
|
||||
in: ".foo/.bar",
|
||||
out: `\x2efoo-.bar`,
|
||||
isPath: false,
|
||||
},
|
||||
// escape disallowed
|
||||
{
|
||||
in: `///..\-!#??///`,
|
||||
out: `---..\x5c\x2d\x21\x23\x3f\x3f---`,
|
||||
isPath: false,
|
||||
},
|
||||
// escape disallowed
|
||||
{
|
||||
in: `///..\-!#??///`,
|
||||
out: `\x2e.\x5c\x2d\x21\x23\x3f\x3f`,
|
||||
isPath: true,
|
||||
},
|
||||
// escape real-world example
|
||||
{
|
||||
in: `user-cloudinit@/var/lib/coreos/vagrant/vagrantfile-user-data.service`,
|
||||
out: `user\x2dcloudinit\x40-var-lib-coreos-vagrant-vagrantfile\x2duser\x2ddata.service`,
|
||||
isPath: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var s string
|
||||
if tt.isPath {
|
||||
s = UnitNamePathEscape(tt.in)
|
||||
} else {
|
||||
s = UnitNameEscape(tt.in)
|
||||
}
|
||||
if s != tt.out {
|
||||
t.Errorf("case %d: failed escaping %v isPath: %v - expected %v, got %v", i, tt.in, tt.isPath, tt.out, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnitNameUnescape(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
out string
|
||||
isPath bool
|
||||
}{
|
||||
// turn empty string path into /
|
||||
{
|
||||
in: "",
|
||||
out: "/",
|
||||
isPath: true,
|
||||
},
|
||||
// leave empty string empty
|
||||
{
|
||||
in: "",
|
||||
out: "",
|
||||
isPath: false,
|
||||
},
|
||||
// turn ////s into
|
||||
{
|
||||
in: "---------",
|
||||
out: "/////////",
|
||||
isPath: true,
|
||||
},
|
||||
// unescape hex
|
||||
{
|
||||
in: `---..\x5c\x2d\x21\x23\x3f\x3f---`,
|
||||
out: `///..\-!#??///`,
|
||||
isPath: false,
|
||||
},
|
||||
// unescape hex
|
||||
{
|
||||
in: `\x2e.\x5c\x2d\x21\x23\x3f\x3f`,
|
||||
out: `/..\-!#??`,
|
||||
isPath: true,
|
||||
},
|
||||
// unescape hex, retain invalids
|
||||
{
|
||||
in: `\x2e.\x5c\x2d\xaZ\x.o\x21\x23\x3f\x3f`,
|
||||
out: `/..\-\xaZ\x.o!#??`,
|
||||
isPath: true,
|
||||
},
|
||||
// unescape hex, retain invalids, partial tail
|
||||
{
|
||||
in: `\x2e.\x5c\x\x2d\xaZ\x.o\x21\x23\x3f\x3f\x3`,
|
||||
out: `/..\\x-\xaZ\x.o!#??\x3`,
|
||||
isPath: true,
|
||||
},
|
||||
// unescape hex, retain invalids, partial tail
|
||||
{
|
||||
in: `\x2e.\x5c\x\x2d\xaZ\x.o\x21\x23\x3f\x3f\x`,
|
||||
out: `/..\\x-\xaZ\x.o!#??\x`,
|
||||
isPath: true,
|
||||
},
|
||||
// unescape hex, retain invalids, partial tail
|
||||
{
|
||||
in: `\x2e.\x5c\x\x2d\xaZ\x.o\x21\x23\x3f\x3f\`,
|
||||
out: `/..\\x-\xaZ\x.o!#??\`,
|
||||
isPath: true,
|
||||
},
|
||||
// unescape real-world example
|
||||
{
|
||||
in: `user\x2dcloudinit\x40-var-lib-coreos-vagrant-vagrantfile\x2duser\x2ddata.service`,
|
||||
out: `user-cloudinit@/var/lib/coreos/vagrant/vagrantfile-user-data.service`,
|
||||
isPath: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var s string
|
||||
if tt.isPath {
|
||||
s = UnitNamePathUnescape(tt.in)
|
||||
} else {
|
||||
s = UnitNameUnescape(tt.in)
|
||||
}
|
||||
if s != tt.out {
|
||||
t.Errorf("case %d: failed unescaping %v isPath: %v - expected %v, got %v", i, tt.in, tt.isPath, tt.out, s)
|
||||
}
|
||||
}
|
||||
}
|
54
vendor/github.com/coreos/go-systemd/unit/option.go
generated
vendored
54
vendor/github.com/coreos/go-systemd/unit/option.go
generated
vendored
|
@ -1,54 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type UnitOption struct {
|
||||
Section string
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
func NewUnitOption(section, name, value string) *UnitOption {
|
||||
return &UnitOption{Section: section, Name: name, Value: value}
|
||||
}
|
||||
|
||||
func (uo *UnitOption) String() string {
|
||||
return fmt.Sprintf("{Section: %q, Name: %q, Value: %q}", uo.Section, uo.Name, uo.Value)
|
||||
}
|
||||
|
||||
func (uo *UnitOption) Match(other *UnitOption) bool {
|
||||
return uo.Section == other.Section &&
|
||||
uo.Name == other.Name &&
|
||||
uo.Value == other.Value
|
||||
}
|
||||
|
||||
func AllMatch(u1 []*UnitOption, u2 []*UnitOption) bool {
|
||||
length := len(u1)
|
||||
if length != len(u2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
if !u1[i].Match(u2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
214
vendor/github.com/coreos/go-systemd/unit/option_test.go
generated
vendored
214
vendor/github.com/coreos/go-systemd/unit/option_test.go
generated
vendored
|
@ -1,214 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllMatch(t *testing.T) {
|
||||
tests := []struct {
|
||||
u1 []*UnitOption
|
||||
u2 []*UnitOption
|
||||
match bool
|
||||
}{
|
||||
// empty lists match
|
||||
{
|
||||
u1: []*UnitOption{},
|
||||
u2: []*UnitOption{},
|
||||
match: true,
|
||||
},
|
||||
|
||||
// simple match of a single option
|
||||
{
|
||||
u1: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
},
|
||||
u2: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
},
|
||||
match: true,
|
||||
},
|
||||
|
||||
// single option mismatched
|
||||
{
|
||||
u1: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
},
|
||||
u2: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "BAR"},
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
|
||||
// multiple options match
|
||||
{
|
||||
u1: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Unit", Name: "BindsTo", Value: "bar.service"},
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
},
|
||||
u2: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Unit", Name: "BindsTo", Value: "bar.service"},
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
},
|
||||
match: true,
|
||||
},
|
||||
|
||||
// mismatch length
|
||||
{
|
||||
u1: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Unit", Name: "BindsTo", Value: "bar.service"},
|
||||
},
|
||||
u2: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Unit", Name: "BindsTo", Value: "bar.service"},
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
|
||||
// multiple options misordered
|
||||
{
|
||||
u1: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
},
|
||||
u2: []*UnitOption{
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
|
||||
// interleaved sections mismatch
|
||||
{
|
||||
u1: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Unit", Name: "BindsTo", Value: "bar.service"},
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
{Section: "Service", Name: "ExecStop", Value: "/bin/true"},
|
||||
},
|
||||
u2: []*UnitOption{
|
||||
{Section: "Unit", Name: "Description", Value: "FOO"},
|
||||
{Section: "Service", Name: "ExecStart", Value: "/bin/true"},
|
||||
{Section: "Unit", Name: "BindsTo", Value: "bar.service"},
|
||||
{Section: "Service", Name: "ExecStop", Value: "/bin/true"},
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
match := AllMatch(tt.u1, tt.u2)
|
||||
if match != tt.match {
|
||||
t.Errorf("case %d: failed comparing u1 to u2 - expected match=%t, got %t", i, tt.match, match)
|
||||
}
|
||||
|
||||
match = AllMatch(tt.u2, tt.u1)
|
||||
if match != tt.match {
|
||||
t.Errorf("case %d: failed comparing u2 to u1 - expected match=%t, got %t", i, tt.match, match)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatch(t *testing.T) {
|
||||
tests := []struct {
|
||||
o1 *UnitOption
|
||||
o2 *UnitOption
|
||||
match bool
|
||||
}{
|
||||
// empty options match
|
||||
{
|
||||
o1: &UnitOption{},
|
||||
o2: &UnitOption{},
|
||||
match: true,
|
||||
},
|
||||
|
||||
// all fields match
|
||||
{
|
||||
o1: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "Description",
|
||||
Value: "FOO",
|
||||
},
|
||||
o2: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "Description",
|
||||
Value: "FOO",
|
||||
},
|
||||
match: true,
|
||||
},
|
||||
|
||||
// Section mismatch
|
||||
{
|
||||
o1: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "Description",
|
||||
Value: "FOO",
|
||||
},
|
||||
o2: &UnitOption{
|
||||
Section: "X-Other",
|
||||
Name: "Description",
|
||||
Value: "FOO",
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
|
||||
// Name mismatch
|
||||
{
|
||||
o1: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "Description",
|
||||
Value: "FOO",
|
||||
},
|
||||
o2: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "BindsTo",
|
||||
Value: "FOO",
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
|
||||
// Value mismatch
|
||||
{
|
||||
o1: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "Description",
|
||||
Value: "FOO",
|
||||
},
|
||||
o2: &UnitOption{
|
||||
Section: "Unit",
|
||||
Name: "Description",
|
||||
Value: "BAR",
|
||||
},
|
||||
match: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
match := tt.o1.Match(tt.o2)
|
||||
if match != tt.match {
|
||||
t.Errorf("case %d: failed comparing o1 to o2 - expected match=%t, got %t", i, tt.match, match)
|
||||
}
|
||||
|
||||
match = tt.o2.Match(tt.o1)
|
||||
if match != tt.match {
|
||||
t.Errorf("case %d: failed comparing o2 to o1 - expected match=%t, got %t", i, tt.match, match)
|
||||
}
|
||||
}
|
||||
}
|
75
vendor/github.com/coreos/go-systemd/unit/serialize.go
generated
vendored
75
vendor/github.com/coreos/go-systemd/unit/serialize.go
generated
vendored
|
@ -1,75 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Serialize encodes all of the given UnitOption objects into a
|
||||
// unit file. When serialized the options are sorted in their
|
||||
// supplied order but grouped by section.
|
||||
func Serialize(opts []*UnitOption) io.Reader {
|
||||
var buf bytes.Buffer
|
||||
|
||||
if len(opts) == 0 {
|
||||
return &buf
|
||||
}
|
||||
|
||||
// Index of sections -> ordered options
|
||||
idx := map[string][]*UnitOption{}
|
||||
// Separately preserve order in which sections were seen
|
||||
sections := []string{}
|
||||
for _, opt := range opts {
|
||||
sec := opt.Section
|
||||
if _, ok := idx[sec]; !ok {
|
||||
sections = append(sections, sec)
|
||||
}
|
||||
idx[sec] = append(idx[sec], opt)
|
||||
}
|
||||
|
||||
for i, sect := range sections {
|
||||
writeSectionHeader(&buf, sect)
|
||||
writeNewline(&buf)
|
||||
|
||||
opts := idx[sect]
|
||||
for _, opt := range opts {
|
||||
writeOption(&buf, opt)
|
||||
writeNewline(&buf)
|
||||
}
|
||||
if i < len(sections)-1 {
|
||||
writeNewline(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
return &buf
|
||||
}
|
||||
|
||||
func writeNewline(buf *bytes.Buffer) {
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
|
||||
func writeSectionHeader(buf *bytes.Buffer, section string) {
|
||||
buf.WriteRune('[')
|
||||
buf.WriteString(section)
|
||||
buf.WriteRune(']')
|
||||
}
|
||||
|
||||
func writeOption(buf *bytes.Buffer, opt *UnitOption) {
|
||||
buf.WriteString(opt.Name)
|
||||
buf.WriteRune('=')
|
||||
buf.WriteString(opt.Value)
|
||||
}
|
170
vendor/github.com/coreos/go-systemd/unit/serialize_test.go
generated
vendored
170
vendor/github.com/coreos/go-systemd/unit/serialize_test.go
generated
vendored
|
@ -1,170 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSerialize(t *testing.T) {
|
||||
tests := []struct {
|
||||
input []*UnitOption
|
||||
output string
|
||||
}{
|
||||
// no options results in empty file
|
||||
{
|
||||
[]*UnitOption{},
|
||||
``,
|
||||
},
|
||||
|
||||
// options with same section share the header
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Unit", "BindsTo", "bar.service"},
|
||||
},
|
||||
`[Unit]
|
||||
Description=Foo
|
||||
BindsTo=bar.service
|
||||
`,
|
||||
},
|
||||
|
||||
// options with same name are not combined
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Unit", "Description", "Bar"},
|
||||
},
|
||||
`[Unit]
|
||||
Description=Foo
|
||||
Description=Bar
|
||||
`,
|
||||
},
|
||||
|
||||
// multiple options printed under different section headers
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Service", "ExecStart", "/usr/bin/sleep infinity"},
|
||||
},
|
||||
`[Unit]
|
||||
Description=Foo
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/sleep infinity
|
||||
`,
|
||||
},
|
||||
|
||||
// options are grouped into sections
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Service", "ExecStart", "/usr/bin/sleep infinity"},
|
||||
&UnitOption{"Unit", "BindsTo", "bar.service"},
|
||||
},
|
||||
`[Unit]
|
||||
Description=Foo
|
||||
BindsTo=bar.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/sleep infinity
|
||||
`,
|
||||
},
|
||||
|
||||
// options are ordered within groups, and sections are ordered in the order in which they were first seen
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Foo"},
|
||||
&UnitOption{"Service", "ExecStart", "/usr/bin/sleep infinity"},
|
||||
&UnitOption{"Unit", "BindsTo", "bar.service"},
|
||||
&UnitOption{"X-Foo", "Bar", "baz"},
|
||||
&UnitOption{"Service", "ExecStop", "/usr/bin/sleep 1"},
|
||||
&UnitOption{"Unit", "Documentation", "https://foo.com"},
|
||||
},
|
||||
`[Unit]
|
||||
Description=Foo
|
||||
BindsTo=bar.service
|
||||
Documentation=https://foo.com
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/sleep infinity
|
||||
ExecStop=/usr/bin/sleep 1
|
||||
|
||||
[X-Foo]
|
||||
Bar=baz
|
||||
`,
|
||||
},
|
||||
|
||||
// utf8 characters are not a problem
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"©", "µ☃", "ÇôrèÕ$"},
|
||||
},
|
||||
`[©]
|
||||
µ☃=ÇôrèÕ$
|
||||
`,
|
||||
},
|
||||
|
||||
// no verification is done on section names
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Un\nit", "Description", "Foo"},
|
||||
},
|
||||
`[Un
|
||||
it]
|
||||
Description=Foo
|
||||
`,
|
||||
},
|
||||
|
||||
// no verification is done on option names
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Desc\nription", "Foo"},
|
||||
},
|
||||
`[Unit]
|
||||
Desc
|
||||
ription=Foo
|
||||
`,
|
||||
},
|
||||
|
||||
// no verification is done on option values
|
||||
{
|
||||
[]*UnitOption{
|
||||
&UnitOption{"Unit", "Description", "Fo\no"},
|
||||
},
|
||||
`[Unit]
|
||||
Description=Fo
|
||||
o
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
outReader := Serialize(tt.input)
|
||||
outBytes, err := ioutil.ReadAll(outReader)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: encountered error while reading output: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
output := string(outBytes)
|
||||
if tt.output != output {
|
||||
t.Errorf("case %d: incorrect output", i)
|
||||
t.Logf("Expected:\n%s", tt.output)
|
||||
t.Logf("Actual:\n%s", output)
|
||||
}
|
||||
}
|
||||
}
|
74
vendor/github.com/coreos/go-systemd/util/util_test.go
generated
vendored
74
vendor/github.com/coreos/go-systemd/util/util_test.go
generated
vendored
|
@ -1,74 +0,0 @@
|
|||
// 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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testIsRunningSystemd(t *testing.T) {
|
||||
if !IsRunningSystemd() {
|
||||
t.Skip("Not running on a systemd host")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunningFromSystemService(t *testing.T) {
|
||||
testIsRunningSystemd(t)
|
||||
t.Parallel()
|
||||
|
||||
// tests shouldn't be running as a service
|
||||
s, err := RunningFromSystemService()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if s {
|
||||
t.Errorf("tests aren't expected to run as a service")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentUnitName(t *testing.T) {
|
||||
testIsRunningSystemd(t)
|
||||
|
||||
s, err := CurrentUnitName()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
if s == "" {
|
||||
t.Error("CurrentUnitName returned a empty string")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMachineID(t *testing.T) {
|
||||
testIsRunningSystemd(t)
|
||||
|
||||
id, err := GetMachineID()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
if id == "" {
|
||||
t.Error("GetMachineID returned a empty string")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRunningSlice(t *testing.T) {
|
||||
testIsRunningSystemd(t)
|
||||
|
||||
s, err := getRunningSlice()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
if s == "" {
|
||||
t.Error("getRunningSlice returned a empty string")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue