Fix the dependency issue (#231)

This commit is contained in:
Robbie Zhang
2018-06-21 12:09:42 -07:00
committed by GitHub
parent 027b76651d
commit 6ec1098bb8
16629 changed files with 74837 additions and 4975021 deletions

View File

@@ -1,9 +0,0 @@
---
language: go
sudo: false
notifications:
email: false
go:
- 1.7
install: make deps
script: make validate && make test

View File

@@ -1,141 +0,0 @@
# Changelog
Items starting with DEPRECATE are important deprecation notices. For more information on the list of deprecated APIs please have a look at https://docs.docker.com/misc/deprecated/ where target removal dates can also be found.
## 0.3.2 (2016-03-30)
## Client
- Revert setting the ServerName in the TLS configuration at client init. See https://github.com/docker/swarm/issues/2027.
## 0.3.1 (2016-03-23)
### Client
- Ensure that API paths are properly escaped.
## 0.3.0 (2016-03-22)
### Client
- Add context to every function.
- Fix issue loading a default TLS CA.
- Allow to configure the client with a given http.Client.
- Add support for Windows named pipes.
- Set default host for Solaris.
- Add quiet flag for image load.
- Add ability to hijack connections through a proxy.
- Correctly set content type for image load.
- Add support for getting token for login.
### Types
- Add struct for update restart policy.
- Add human friendly State for container.
- Use OS specific host when DOCKER_HOST is not set.
- Rename Status in info to SystemStatus.
- Add internal flag to network inspect.
- Add disk quota field to container.
- Add EnableIPv6 fields.
- Add Mounts to container.
- Add cgroup driver to info.
- Add userns to host config.
- Remove email from AuthConfig.
- Make AuthConfig fields optional.
- Add IO resource settings for Windows.
- Add storage driver to host config.
- Update NetworkName to return proper user defined network names.
- Support joining cgroups by container id.
- Add KernelMemory to info.
- Add UsernsMode to container config.
- Add CPU resource control for Windows.
- Add AutoRemove to host config.
- Add Status field to Volume.
- Add Label to Image, Network and Volume.
- Add RootFS to container.
## 0.2.3 (2016-02-02)
### Types
- Add missing status field.
## 0.2.2 (2016-01-13)
### Client
- Fix issue configuring response hijacking with TLS enabled.
## 0.2.1 (2016-01-12)
### Client
- Fix issue detecting missing images on container creation.
### Types
- Remove invalid json tag in endpoint configuration.
- Add missing fields in info structure.
## 0.2.0 (2016-01-11)
### Client
- Allow to force network disconnection. (docker 1.10)
### Types
- Add global and local alias configuration to network endpoint.
- Add network ID to network endpoint.
- Add IPAM options.
- Add Seccomp options.
- Fix issue referencing OOMKillDisable.
## 0.1.3 (2016-01-07)
### Client
- Fix issue sending all network configurations for a per network request.
## 0.1.2 (2016-01-07)
### Client
- Add interface to represent the API client.
- Restrict the fields send to the update endpoint to only those that are used.
- Send network settings as part of the container create request. (docker 1.10)
- Send network settings as part of the network connect request. (docker 1.10)
### Types
- Add PidsLimit as part of the host configuration.
- Add PidsStats to show PID stats.
- Add graph storage options to host configuration.
- Add NetworkConfig and EndpointIPAMConfig structs. (docker 1.10)
## 0.1.1 (2016-01-06)
### Client
- Delegate shmSize units conversion to the consumer.
### Types
- Add warnings to the volume list response.
- Fix image build options:
* use 0 as default value for shmSize.
## 0.1.0 (2016-01-04)
### Client
- Initial API client implementation.
### Types
- Initial API types implementation.

View File

@@ -1,55 +0,0 @@
# Contributing to Docker
### Sign your work
The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch or otherwise have the right to pass
it on as an open-source patch. The rules are pretty simple: if you can certify
the below (from [developercertificate.org](http://developercertificate.org/)):
```
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.
```
Then you just add a line to every git commit message:
Signed-off-by: Joe Smith <joe.smith@email.com>
Use your real name (sorry, no pseudonyms or anonymous contributions.)
If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.

View File

@@ -1,160 +0,0 @@
# engine-api maintainers file
#
# This file describes who runs the docker/engine-api project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"aaronlehmann",
"calavera",
"coolljt0725",
"cpuguy83",
"crosbymichael",
"dnephin",
"dongluochen",
"duglin",
"estesp",
"icecrime",
"jhowardmsft",
"lk4d4",
"mavenugo",
"mhbauer",
"runcom",
"stevvooe",
"thajeztah",
"tianon",
"tibor",
"tonistiigi",
"unclejack",
"vdemeester",
"vieux"
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aaronlehmann]
Name = "Aaron Lehmann"
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.calavera]
Name = "David Calavera"
Email = "david.calavera@gmail.com"
GitHub = "calavera"
[people.coolljt0725]
Name = "Lei Jitang"
Email = "leijitang@huawei.com"
GitHub = "coolljt0725"
[people.cpuguy83]
Name = "Brian Goff"
Email = "cpuguy83@gmail.com"
Github = "cpuguy83"
[people.crosbymichael]
Name = "Michael Crosby"
Email = "crosbymichael@gmail.com"
GitHub = "crosbymichael"
[people.dnephin]
Name = "Daniel Nephin"
Email = "dnephin@gmail.com"
GitHub = "dnephin"
[people.dongluochen]
Name = "Dongluo Chen"
Email = "dongluo.chen@docker.com"
GitHub = "dongluochen"
[people.duglin]
Name = "Doug Davis"
Email = "dug@us.ibm.com"
GitHub = "duglin"
[people.estesp]
Name = "Phil Estes"
Email = "estesp@linux.vnet.ibm.com"
GitHub = "estesp"
[people.icecrime]
Name = "Arnaud Porterie"
Email = "arnaud@docker.com"
GitHub = "icecrime"
[people.jhowardmsft]
Name = "John Howard"
Email = "jhoward@microsoft.com"
GitHub = "jhowardmsft"
[people.lk4d4]
Name = "Alexander Morozov"
Email = "lk4d4@docker.com"
GitHub = "lk4d4"
[people.mavenugo]
Name = "Madhu Venugopal"
Email = "madhu@docker.com"
GitHub = "mavenugo"
[people.mhbauer]
Name = "Morgan Bauer"
Email = "mbauer@us.ibm.com"
GitHub = "mhbauer"
[people.runcom]
Name = "Antonio Murdaca"
Email = "runcom@redhat.com"
GitHub = "runcom"
[people.stevvooe]
Name = "Stephen Day"
Email = "stephen.day@docker.com"
GitHub = "stevvooe"
[people.thajeztah]
Name = "Sebastiaan van Stijn"
Email = "github@gone.nl"
GitHub = "thaJeztah"
[people.tianon]
Name = "Tianon Gravi"
Email = "admwiggin@gmail.com"
GitHub = "tianon"
[people.tibor]
Name = "Tibor Vass"
Email = "tibor@docker.com"
GitHub = "tiborvass"
[people.tonistiigi]
Name = "Tõnis Tiigi"
Email = "tonis@docker.com"
GitHub = "tonistiigi"
[people.unclejack]
Name = "Cristian Staretu"
Email = "cristian.staretu@gmail.com"
GitHub = "unclejack"
[people.vdemeester]
Name = "Vincent Demeester"
Email = "vincent@sbr.pm"
GitHub = "vdemeester"
[people.vieux]
Name = "Victor Vieux"
Email = "vieux@docker.com"
GitHub = "vieux"

View File

@@ -1,21 +0,0 @@
.PHONY: all deps test validate lint
all: deps test validate
deps:
go get -t ./...
go get -u github.com/golang/lint/golint
test:
go test -tags experimental -race -cover ./...
validate: lint
go vet ./...
test -z "$(gofmt -s -l . | tee /dev/stderr)"
lint:
out="$$(golint ./...)"; \
if [ -n "$$(golint ./...)" ]; then \
echo "$$out"; \
exit 1; \
fi

View File

@@ -1,55 +0,0 @@
# Go client for the Hyper.sh API
The `hyper` command uses this package to communicate with the Hyper.sh server. It can also be used by your own Go applications to do anything the command-line interface does  running containers, pulling images, managing volumes, etc.
For example, to list running containers (the equivalent of `hyper ps`):
```go
package main
import (
"context"
"crypto/tls"
"fmt"
"net/http"
"github.com/hyperhq/hyper-api/client"
"github.com/hyperhq/hyper-api/types"
)
func main() {
var (
host = "tcp://us-west-1.hyper.sh:443"
customHeaders = map[string]string{}
verStr = "v1.23"
accessKey = "xx"
secretKey = "xxx"
)
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
client, err := client.NewClient(host, verStr, httpClient, customHeaders, accessKey, secretKey)
if err != nil {
panic(err)
}
containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
panic(err)
}
for _, container := range containers {
fmt.Printf("%s\t%s\n", container.ID[:10], container.Image)
}
}
```
Full documentation is available on [document](https://docs.hyper.sh).
## License
engine-api is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text.

View File

@@ -1,37 +0,0 @@
version: "{build}"
# Source Config
clone_folder: c:\gopath\src\github.com\docker\engine-api
# Build host
environment:
GOPATH: c:\gopath
GOVERSION: 1.6
init:
- git config --global core.autocrlf input
# Build
install:
# Install Go 1.6.
- rmdir c:\go /s /q
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
- msiexec /i go%GOVERSION%.windows-amd64.msi /q
- set Path=c:\go\bin;c:\gopath\bin;%Path%
- go version
- go env
build: false
deploy: false
before_test:
- go get -t ./...
- go get github.com/golang/lint/golint
test_script:
- go vet ./...
- golint ./...
- gofmt -s -l .
- go test -race -cover -v -tags=test ./...

View File

@@ -1,73 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
)
func TestCheckpointCreateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.CheckpointCreate(context.Background(), "nothing", types.CheckpointCreateOptions{
CheckpointID: "noting",
Exit: true,
})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestCheckpointCreate(t *testing.T) {
expectedContainerID := "container_id"
expectedCheckpointID := "checkpoint_id"
expectedURL := "/containers/container_id/checkpoints"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
createOptions := &types.CheckpointCreateOptions{}
if err := json.NewDecoder(req.Body).Decode(createOptions); err != nil {
return nil, err
}
if createOptions.CheckpointID != expectedCheckpointID {
return nil, fmt.Errorf("expected CheckpointID to be 'checkpoint_id', got %v", createOptions.CheckpointID)
}
if !createOptions.Exit {
return nil, fmt.Errorf("expected Exit to be true")
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.CheckpointCreate(context.Background(), expectedContainerID, types.CheckpointCreateOptions{
CheckpointID: expectedCheckpointID,
Exit: true,
})
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,47 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestCheckpointDeleteError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.CheckpointDelete(context.Background(), "container_id", "checkpoint_id")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestCheckpointDelete(t *testing.T) {
expectedURL := "/containers/container_id/checkpoints/checkpoint_id"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "DELETE" {
return nil, fmt.Errorf("expected DELETE method, got %s", req.Method)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.CheckpointDelete(context.Background(), "container_id", "checkpoint_id")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,57 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestCheckpointListError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.CheckpointList(context.Background(), "container_id")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestCheckpointList(t *testing.T) {
expectedURL := "/containers/container_id/checkpoints"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
content, err := json.Marshal([]types.Checkpoint{
{
Name: "checkpoint",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
checkpoints, err := client.CheckpointList(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
if len(checkpoints) != 1 {
t.Fatalf("expected 1 checkpoint, got %v", checkpoints)
}
}

View File

@@ -1,76 +0,0 @@
package client
import (
"bytes"
"crypto/tls"
"encoding/json"
"io/ioutil"
"net/http"
"github.com/hyperhq/hyper-api/client/transport"
"github.com/hyperhq/hyper-api/types"
)
type mockClient struct {
do func(*http.Request) (*http.Response, error)
}
// TLSConfig returns the TLS configuration.
func (m *mockClient) TLSConfig() *tls.Config {
return &tls.Config{}
}
// Scheme returns protocol scheme to use.
func (m *mockClient) Scheme() string {
return "http"
}
// Secure returns true if there is a TLS configuration.
func (m *mockClient) Secure() bool {
return false
}
// NewMockClient returns a mocked client that runs the function supplied as `client.Do` call
func newMockClient(tlsConfig *tls.Config, doer func(*http.Request) (*http.Response, error)) transport.Client {
if tlsConfig != nil {
panic("this actually gets set!")
}
return &mockClient{
do: doer,
}
}
// Do executes the supplied function for the mock.
func (m mockClient) Do(req *http.Request) (*http.Response, error) {
return m.do(req)
}
func errorMock(statusCode int, message string) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
header := http.Header{}
header.Set("Content-Type", "application/json")
body, err := json.Marshal(&types.ErrorResponse{
Message: message,
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: statusCode,
Body: ioutil.NopCloser(bytes.NewReader(body)),
Header: header,
}, nil
}
}
func plainTextErrorMock(statusCode int, message string) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: statusCode,
Body: ioutil.NopCloser(bytes.NewReader([]byte(message))),
}, nil
}
}

View File

@@ -1,245 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestNewEnvClient(t *testing.T) {
cases := []struct {
envs map[string]string
expectedError string
expectedVersion string
}{
{
envs: map[string]string{},
expectedVersion: DefaultVersion,
},
{
envs: map[string]string{
"DOCKER_CERT_PATH": "invalid/path",
},
expectedError: "Could not load X509 key pair: open invalid/path/cert.pem: no such file or directory. Make sure the key is not encrypted",
},
{
envs: map[string]string{
"DOCKER_CERT_PATH": "testdata/",
},
expectedVersion: DefaultVersion,
},
{
envs: map[string]string{
"DOCKER_HOST": "host",
},
expectedError: "unable to parse docker host `host`",
},
{
envs: map[string]string{
"DOCKER_HOST": "invalid://url",
},
expectedVersion: DefaultVersion,
},
{
envs: map[string]string{
"DOCKER_API_VERSION": "anything",
},
expectedVersion: "anything",
},
{
envs: map[string]string{
"DOCKER_API_VERSION": "1.22",
},
expectedVersion: "1.22",
},
}
for _, c := range cases {
recoverEnvs := setupEnvs(t, c.envs)
apiclient, err := NewEnvClient()
if c.expectedError != "" {
if err == nil || err.Error() != c.expectedError {
t.Errorf("expected an error %s, got %s, for %v", c.expectedError, err.Error(), c)
}
} else {
if err != nil {
t.Error(err)
}
version := apiclient.ClientVersion()
if version != c.expectedVersion {
t.Errorf("expected %s, got %s, for %v", c.expectedVersion, version, c)
}
}
recoverEnvs(t)
}
}
func setupEnvs(t *testing.T, envs map[string]string) func(*testing.T) {
oldEnvs := map[string]string{}
for key, value := range envs {
oldEnv := os.Getenv(key)
oldEnvs[key] = oldEnv
err := os.Setenv(key, value)
if err != nil {
t.Error(err)
}
}
return func(t *testing.T) {
for key, value := range oldEnvs {
err := os.Setenv(key, value)
if err != nil {
t.Error(err)
}
}
}
}
func TestGetAPIPath(t *testing.T) {
cases := []struct {
v string
p string
q url.Values
e string
}{
{"", "/containers/json", nil, "/containers/json"},
{"", "/containers/json", url.Values{}, "/containers/json"},
{"", "/containers/json", url.Values{"s": []string{"c"}}, "/containers/json?s=c"},
{"1.22", "/containers/json", nil, "/v1.22/containers/json"},
{"1.22", "/containers/json", url.Values{}, "/v1.22/containers/json"},
{"1.22", "/containers/json", url.Values{"s": []string{"c"}}, "/v1.22/containers/json?s=c"},
{"v1.22", "/containers/json", nil, "/v1.22/containers/json"},
{"v1.22", "/containers/json", url.Values{}, "/v1.22/containers/json"},
{"v1.22", "/containers/json", url.Values{"s": []string{"c"}}, "/v1.22/containers/json?s=c"},
{"v1.22", "/networks/kiwl$%^", nil, "/v1.22/networks/kiwl$%25%5E"},
}
for _, cs := range cases {
c, err := NewClient("unix:///var/run/docker.sock", cs.v, nil, nil)
if err != nil {
t.Fatal(err)
}
g := c.getAPIPath(cs.p, cs.q)
if g != cs.e {
t.Fatalf("Expected %s, got %s", cs.e, g)
}
}
}
func TestParseHost(t *testing.T) {
cases := []struct {
host string
proto string
addr string
base string
err bool
}{
{"", "", "", "", true},
{"foobar", "", "", "", true},
{"foo://bar", "foo", "bar", "", false},
{"tcp://localhost:2476", "tcp", "localhost:2476", "", false},
{"tcp://localhost:2476/path", "tcp", "localhost:2476", "/path", false},
}
for _, cs := range cases {
p, a, b, e := ParseHost(cs.host)
if cs.err && e == nil {
t.Fatalf("expected error, got nil")
}
if !cs.err && e != nil {
t.Fatal(e)
}
if cs.proto != p {
t.Fatalf("expected proto %s, got %s", cs.proto, p)
}
if cs.addr != a {
t.Fatalf("expected addr %s, got %s", cs.addr, a)
}
if cs.base != b {
t.Fatalf("expected base %s, got %s", cs.base, b)
}
}
}
func TestUpdateClientVersion(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
splitQuery := strings.Split(req.URL.Path, "/")
queryVersion := splitQuery[1]
b, err := json.Marshal(types.Version{
APIVersion: queryVersion,
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
cases := []struct {
v string
}{
{"1.20"},
{"v1.21"},
{"1.22"},
{"v1.22"},
}
for _, cs := range cases {
client.UpdateClientVersion(cs.v)
r, err := client.ServerVersion(context.Background())
if err != nil {
t.Fatal(err)
}
if strings.TrimPrefix(r.APIVersion, "v") != strings.TrimPrefix(cs.v, "v") {
t.Fatalf("Expected %s, got %s", cs.v, r.APIVersion)
}
}
}
func TestNewEnvClientSetsDefaultVersion(t *testing.T) {
// Unset environment variables
envVarKeys := []string{
"DOCKER_HOST",
"DOCKER_API_VERSION",
"DOCKER_TLS_VERIFY",
"DOCKER_CERT_PATH",
}
envVarValues := make(map[string]string)
for _, key := range envVarKeys {
envVarValues[key] = os.Getenv(key)
os.Setenv(key, "")
}
client, err := NewEnvClient()
if err != nil {
t.Fatal(err)
}
if client.version != DefaultVersion {
t.Fatalf("Expected %s, got %s", DefaultVersion, client.version)
}
expected := "1.22"
os.Setenv("DOCKER_API_VERSION", expected)
client, err = NewEnvClient()
if err != nil {
t.Fatal(err)
}
if client.version != expected {
t.Fatalf("Expected %s, got %s", expected, client.version)
}
// Restore environment variables
for _, key := range envVarKeys {
os.Setenv(key, envVarValues[key])
}
}

View File

@@ -1,96 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerCommitError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerCommit(context.Background(), "nothing", types.ContainerCommitOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerCommit(t *testing.T) {
expectedURL := "/commit"
expectedContainerID := "container_id"
specifiedReference := "repository_name:tag"
expectedRepositoryName := "repository_name"
expectedTag := "tag"
expectedComment := "comment"
expectedAuthor := "author"
expectedChanges := []string{"change1", "change2"}
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
containerID := query.Get("container")
if containerID != expectedContainerID {
return nil, fmt.Errorf("container id not set in URL query properly. Expected '%s', got %s", expectedContainerID, containerID)
}
repo := query.Get("repo")
if repo != expectedRepositoryName {
return nil, fmt.Errorf("container repo not set in URL query properly. Expected '%s', got %s", expectedRepositoryName, repo)
}
tag := query.Get("tag")
if tag != expectedTag {
return nil, fmt.Errorf("container tag not set in URL query properly. Expected '%s', got %s'", expectedTag, tag)
}
comment := query.Get("comment")
if comment != expectedComment {
return nil, fmt.Errorf("container comment not set in URL query properly. Expected '%s', got %s'", expectedComment, comment)
}
author := query.Get("author")
if author != expectedAuthor {
return nil, fmt.Errorf("container author not set in URL query properly. Expected '%s', got %s'", expectedAuthor, author)
}
pause := query.Get("pause")
if pause != "0" {
return nil, fmt.Errorf("container pause not set in URL query properly. Expected 'true', got %v'", pause)
}
changes := query["changes"]
if len(changes) != len(expectedChanges) {
return nil, fmt.Errorf("expected container changes size to be '%d', got %d", len(expectedChanges), len(changes))
}
b, err := json.Marshal(types.ContainerCommitResponse{
ID: "new_container_id",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
r, err := client.ContainerCommit(context.Background(), expectedContainerID, types.ContainerCommitOptions{
Reference: specifiedReference,
Comment: expectedComment,
Author: expectedAuthor,
Changes: expectedChanges,
Pause: false,
})
if err != nil {
t.Fatal(err)
}
if r.ID != "new_container_id" {
t.Fatalf("expected `container_id`, got %s", r.ID)
}
}

View File

@@ -1,244 +0,0 @@
package client
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerStatPathError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerStatPath(context.Background(), "container_id", "path")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestContainerStatPathNoHeaderError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
_, err := client.ContainerStatPath(context.Background(), "container_id", "path/to/file")
if err == nil {
t.Fatalf("expected an error, got nothing")
}
}
func TestContainerStatPath(t *testing.T) {
expectedURL := "/containers/container_id/archive"
expectedPath := "path/to/file"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "HEAD" {
return nil, fmt.Errorf("expected HEAD method, got %s", req.Method)
}
query := req.URL.Query()
path := query.Get("path")
if path != expectedPath {
return nil, fmt.Errorf("path not set in URL query properly")
}
content, err := json.Marshal(types.ContainerPathStat{
Name: "name",
Mode: 0700,
})
if err != nil {
return nil, err
}
base64PathStat := base64.StdEncoding.EncodeToString(content)
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
Header: http.Header{
"X-Docker-Container-Path-Stat": []string{base64PathStat},
},
}, nil
}),
}
stat, err := client.ContainerStatPath(context.Background(), "container_id", expectedPath)
if err != nil {
t.Fatal(err)
}
if stat.Name != "name" {
t.Fatalf("expected container path stat name to be 'name', was '%s'", stat.Name)
}
if stat.Mode != 0700 {
t.Fatalf("expected container path stat mode to be 0700, was '%v'", stat.Mode)
}
}
func TestCopyToContainerError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestCopyToContainerNotStatusOKError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNoContent, "No content")),
}
err := client.CopyToContainer(context.Background(), "container_id", "path/to/file", bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
if err == nil || err.Error() != "unexpected status code from daemon: 204" {
t.Fatalf("expected an unexpected status code error, got %v", err)
}
}
func TestCopyToContainer(t *testing.T) {
expectedURL := "/containers/container_id/archive"
expectedPath := "path/to/file"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "PUT" {
return nil, fmt.Errorf("expected PUT method, got %s", req.Method)
}
query := req.URL.Query()
path := query.Get("path")
if path != expectedPath {
return nil, fmt.Errorf("path not set in URL query properly, expected '%s', got %s", expectedPath, path)
}
noOverwriteDirNonDir := query.Get("noOverwriteDirNonDir")
if noOverwriteDirNonDir != "true" {
return nil, fmt.Errorf("noOverwriteDirNonDir not set in URL query properly, expected true, got %s", noOverwriteDirNonDir)
}
content, err := ioutil.ReadAll(req.Body)
if err != nil {
return nil, err
}
if err := req.Body.Close(); err != nil {
return nil, err
}
if string(content) != "content" {
return nil, fmt.Errorf("expected content to be 'content', got %s", string(content))
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.CopyToContainer(context.Background(), "container_id", expectedPath, bytes.NewReader([]byte("content")), types.CopyToContainerOptions{
AllowOverwriteDirWithFile: false,
})
if err != nil {
t.Fatal(err)
}
}
func TestCopyFromContainerError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestCopyFromContainerNotStatusOKError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNoContent, "No content")),
}
_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
if err == nil || err.Error() != "unexpected status code from daemon: 204" {
t.Fatalf("expected an unexpected status code error, got %v", err)
}
}
func TestCopyFromContainerNoHeaderError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
_, _, err := client.CopyFromContainer(context.Background(), "container_id", "path/to/file")
if err == nil {
t.Fatalf("expected an error, got nothing")
}
}
func TestCopyFromContainer(t *testing.T) {
expectedURL := "/containers/container_id/archive"
expectedPath := "path/to/file"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "GET" {
return nil, fmt.Errorf("expected PUT method, got %s", req.Method)
}
query := req.URL.Query()
path := query.Get("path")
if path != expectedPath {
return nil, fmt.Errorf("path not set in URL query properly, expected '%s', got %s", expectedPath, path)
}
headercontent, err := json.Marshal(types.ContainerPathStat{
Name: "name",
Mode: 0700,
})
if err != nil {
return nil, err
}
base64PathStat := base64.StdEncoding.EncodeToString(headercontent)
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("content"))),
Header: http.Header{
"X-Docker-Container-Path-Stat": []string{base64PathStat},
},
}, nil
}),
}
r, stat, err := client.CopyFromContainer(context.Background(), "container_id", expectedPath)
if err != nil {
t.Fatal(err)
}
if stat.Name != "name" {
t.Fatalf("expected container path stat name to be 'name', was '%s'", stat.Name)
}
if stat.Mode != 0700 {
t.Fatalf("expected container path stat mode to be 0700, was '%v'", stat.Mode)
}
content, err := ioutil.ReadAll(r)
if err != nil {
t.Fatal(err)
}
if err := r.Close(); err != nil {
t.Fatal(err)
}
if string(content) != "content" {
t.Fatalf("expected content to be 'content', got %s", string(content))
}
}

View File

@@ -1,77 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/container"
)
func TestContainerCreateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerCreate(context.Background(), nil, nil, nil, "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
// 404 doesn't automagitally means an unknown image
client = &Client{
transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")),
}
_, err = client.ContainerCreate(context.Background(), nil, nil, nil, "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerCreateImageNotFound(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNotFound, "No such image")),
}
_, err := client.ContainerCreate(context.Background(), &container.Config{Image: "unknown_image"}, nil, nil, "unknown")
if err == nil || !IsErrImageNotFound(err) {
t.Fatalf("expected an imageNotFound error, got %v", err)
}
}
func TestContainerCreateWithName(t *testing.T) {
expectedURL := "/containers/create"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
name := req.URL.Query().Get("name")
if name != "container_name" {
return nil, fmt.Errorf("container name not set in URL query properly. Expected `container_name`, got %s", name)
}
b, err := json.Marshal(types.ContainerCreateResponse{
ID: "container_id",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
r, err := client.ContainerCreate(context.Background(), nil, nil, nil, "container_name")
if err != nil {
t.Fatal(err)
}
if r.ID != "container_id" {
t.Fatalf("expected `container_id`, got %s", r.ID)
}
}

View File

@@ -1,61 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerDiffError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerDiff(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerDiff(t *testing.T) {
expectedURL := "/containers/container_id/changes"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
b, err := json.Marshal([]types.ContainerChange{
{
Kind: 0,
Path: "/path/1",
},
{
Kind: 1,
Path: "/path/2",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
changes, err := client.ContainerDiff(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
if len(changes) != 2 {
t.Fatalf("expected an array of 2 changes, got %v", changes)
}
}

View File

@@ -1,157 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerExecCreateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerExecCreate(t *testing.T) {
expectedURL := "/containers/container_id/exec"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
// FIXME validate the content is the given ExecConfig ?
if err := req.ParseForm(); err != nil {
return nil, err
}
execConfig := &types.ExecConfig{}
if err := json.NewDecoder(req.Body).Decode(execConfig); err != nil {
return nil, err
}
if execConfig.User != "user" {
return nil, fmt.Errorf("expected an execConfig with User == 'user', got %v", execConfig)
}
b, err := json.Marshal(types.ContainerExecCreateResponse{
ID: "exec_id",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
r, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{
User: "user",
})
if err != nil {
t.Fatal(err)
}
if r.ID != "exec_id" {
t.Fatalf("expected `exec_id`, got %s", r.ID)
}
}
func TestContainerExecStartError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerExecStart(context.Background(), "nothing", types.ExecStartCheck{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerExecStart(t *testing.T) {
expectedURL := "/exec/exec_id/start"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if err := req.ParseForm(); err != nil {
return nil, err
}
execStartCheck := &types.ExecStartCheck{}
if err := json.NewDecoder(req.Body).Decode(execStartCheck); err != nil {
return nil, err
}
if execStartCheck.Tty || !execStartCheck.Detach {
return nil, fmt.Errorf("expected execStartCheck{Detach:true,Tty:false}, got %v", execStartCheck)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerExecStart(context.Background(), "exec_id", types.ExecStartCheck{
Detach: true,
Tty: false,
})
if err != nil {
t.Fatal(err)
}
}
func TestContainerExecInspectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerExecInspect(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerExecInspect(t *testing.T) {
expectedURL := "/exec/exec_id/json"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
b, err := json.Marshal(types.ContainerExecInspect{
ExecID: "exec_id",
ContainerID: "container_id",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
inspect, err := client.ContainerExecInspect(context.Background(), "exec_id")
if err != nil {
t.Fatal(err)
}
if inspect.ExecID != "exec_id" {
t.Fatalf("expected ExecID to be `exec_id`, got %s", inspect.ExecID)
}
if inspect.ContainerID != "container_id" {
t.Fatalf("expected ContainerID `container_id`, got %s", inspect.ContainerID)
}
}

View File

@@ -1,50 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestContainerExportError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerExport(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerExport(t *testing.T) {
expectedURL := "/containers/container_id/export"
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("response"))),
}, nil
}),
}
body, err := client.ContainerExport(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
defer body.Close()
content, err := ioutil.ReadAll(body)
if err != nil {
t.Fatal(err)
}
if string(content) != "response" {
t.Fatalf("expected response to contain 'response', got %s", string(content))
}
}

View File

@@ -1,125 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerInspectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerInspect(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerInspectContainerNotFound(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")),
}
_, err := client.ContainerInspect(context.Background(), "unknown")
if err == nil || !IsErrContainerNotFound(err) {
t.Fatalf("expected a containerNotFound error, got %v", err)
}
}
func TestContainerInspect(t *testing.T) {
expectedURL := "/containers/container_id/json"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
content, err := json.Marshal(types.ContainerJSON{
ContainerJSONBase: &types.ContainerJSONBase{
ID: "container_id",
Image: "image",
Name: "name",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
r, err := client.ContainerInspect(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
if r.ID != "container_id" {
t.Fatalf("expected `container_id`, got %s", r.ID)
}
if r.Image != "image" {
t.Fatalf("expected `image`, got %s", r.ID)
}
if r.Name != "name" {
t.Fatalf("expected `name`, got %s", r.ID)
}
}
func TestContainerInspectNode(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
content, err := json.Marshal(types.ContainerJSON{
ContainerJSONBase: &types.ContainerJSONBase{
ID: "container_id",
Image: "image",
Name: "name",
Node: &types.ContainerNode{
ID: "container_node_id",
Addr: "container_node",
Labels: map[string]string{"foo": "bar"},
},
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
r, err := client.ContainerInspect(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
if r.ID != "container_id" {
t.Fatalf("expected `container_id`, got %s", r.ID)
}
if r.Image != "image" {
t.Fatalf("expected `image`, got %s", r.ID)
}
if r.Name != "name" {
t.Fatalf("expected `name`, got %s", r.ID)
}
if r.Node.ID != "container_node_id" {
t.Fatalf("expected `container_node_id`, got %s", r.Node.ID)
}
if r.Node.Addr != "container_node" {
t.Fatalf("expected `container_node`, got %s", r.Node.Addr)
}
foo, ok := r.Node.Labels["foo"]
if foo != "bar" || !ok {
t.Fatalf("expected `bar` for label `foo`")
}
}

View File

@@ -1,46 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestContainerKillError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerKill(context.Background(), "nothing", "SIGKILL")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerKill(t *testing.T) {
expectedURL := "/containers/container_id/kill"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
signal := req.URL.Query().Get("signal")
if signal != "SIGKILL" {
return nil, fmt.Errorf("signal not set in URL query properly. Expected 'SIGKILL', got %s", signal)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerKill(context.Background(), "container_id", "SIGKILL")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,96 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/filters"
)
func TestContainerListError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerList(context.Background(), types.ContainerListOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerList(t *testing.T) {
expectedURL := "/containers/json"
expectedFilters := `{"before":{"container":true},"label":{"label1":true,"label2":true}}`
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
all := query.Get("all")
if all != "1" {
return nil, fmt.Errorf("all not set in URL query properly. Expected '1', got %s", all)
}
limit := query.Get("limit")
if limit != "0" {
return nil, fmt.Errorf("limit should have not be present in query. Expected '0', got %s", limit)
}
since := query.Get("since")
if since != "container" {
return nil, fmt.Errorf("since not set in URL query properly. Expected 'container', got %s", since)
}
before := query.Get("before")
if before != "" {
return nil, fmt.Errorf("before should have not be present in query, go %s", before)
}
size := query.Get("size")
if size != "1" {
return nil, fmt.Errorf("size not set in URL query properly. Expected '1', got %s", size)
}
filters := query.Get("filters")
if filters != expectedFilters {
return nil, fmt.Errorf("expected filters incoherent '%v' with actual filters %v", expectedFilters, filters)
}
b, err := json.Marshal([]types.Container{
{
ID: "container_id1",
},
{
ID: "container_id2",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
filters := filters.NewArgs()
filters.Add("label", "label1")
filters.Add("label", "label2")
filters.Add("before", "container")
containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{
Size: true,
All: true,
Since: "container",
Filter: filters,
})
if err != nil {
t.Fatal(err)
}
if len(containers) != 2 {
t.Fatalf("expected 2 containers, got %v", containers)
}
}

View File

@@ -1,133 +0,0 @@
package client
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"testing"
"time"
"github.com/hyperhq/hyper-api/types"
"context"
)
func TestContainerLogsError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerLogs(context.Background(), "container_id", types.ContainerLogsOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
_, err = client.ContainerLogs(context.Background(), "container_id", types.ContainerLogsOptions{
Since: "2006-01-02TZ",
})
if err == nil || !strings.Contains(err.Error(), `parsing time "2006-01-02TZ"`) {
t.Fatalf("expected a 'parsing time' error, got %v", err)
}
}
func TestContainerLogs(t *testing.T) {
expectedURL := "/containers/container_id/logs"
cases := []struct {
options types.ContainerLogsOptions
expectedQueryParams map[string]string
}{
{
expectedQueryParams: map[string]string{
"tail": "",
},
},
{
options: types.ContainerLogsOptions{
Tail: "any",
},
expectedQueryParams: map[string]string{
"tail": "any",
},
},
{
options: types.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
Timestamps: true,
Details: true,
Follow: true,
},
expectedQueryParams: map[string]string{
"tail": "",
"stdout": "1",
"stderr": "1",
"timestamps": "1",
"details": "1",
"follow": "1",
},
},
{
options: types.ContainerLogsOptions{
// An complete invalid date, timestamp or go duration will be
// passed as is
Since: "invalid but valid",
},
expectedQueryParams: map[string]string{
"tail": "",
"since": "invalid but valid",
},
},
}
for _, logCase := range cases {
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
// Check query parameters
query := r.URL.Query()
for key, expected := range logCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("response"))),
}, nil
}),
}
body, err := client.ContainerLogs(context.Background(), "container_id", logCase.options)
if err != nil {
t.Fatal(err)
}
defer body.Close()
content, err := ioutil.ReadAll(body)
if err != nil {
t.Fatal(err)
}
if string(content) != "response" {
t.Fatalf("expected response to contain 'response', got %s", string(content))
}
}
}
func ExampleClient_ContainerLogs_withTimeout() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
client, _ := NewEnvClient()
reader, err := client.ContainerLogs(ctx, "container_id", types.ContainerLogsOptions{})
if err != nil {
log.Fatal(err)
}
_, err = io.Copy(os.Stdout, reader)
if err != nil && err != io.EOF {
log.Fatal(err)
}
}

View File

@@ -1,41 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestContainerPauseError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerPause(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerPause(t *testing.T) {
expectedURL := "/containers/container_id/pause"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerPause(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,59 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerRemoveError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerRemove(t *testing.T) {
expectedURL := "/containers/container_id"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
volume := query.Get("v")
if volume != "1" {
return nil, fmt.Errorf("v (volume) not set in URL query properly. Expected '1', got %s", volume)
}
force := query.Get("force")
if force != "1" {
return nil, fmt.Errorf("force not set in URL query properly. Expected '1', got %s", force)
}
link := query.Get("link")
if link != "" {
return nil, fmt.Errorf("link should have not be present in query, go %s", link)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{
RemoveVolumes: true,
Force: true,
})
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,46 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestContainerRenameError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerRename(context.Background(), "nothing", "newNothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerRename(t *testing.T) {
expectedURL := "/containers/container_id/rename"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
name := req.URL.Query().Get("name")
if name != "newName" {
return nil, fmt.Errorf("name not set in URL query properly. Expected 'newName', got %s", name)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerRename(context.Background(), "container_id", "newName")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,82 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerResizeError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerResize(context.Background(), "container_id", types.ResizeOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerExecResizeError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerExecResize(context.Background(), "exec_id", types.ResizeOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerResize(t *testing.T) {
client := &Client{
transport: newMockClient(nil, resizeTransport("/containers/container_id/resize")),
}
err := client.ContainerResize(context.Background(), "container_id", types.ResizeOptions{
Height: 500,
Width: 600,
})
if err != nil {
t.Fatal(err)
}
}
func TestContainerExecResize(t *testing.T) {
client := &Client{
transport: newMockClient(nil, resizeTransport("/exec/exec_id/resize")),
}
err := client.ContainerExecResize(context.Background(), "exec_id", types.ResizeOptions{
Height: 500,
Width: 600,
})
if err != nil {
t.Fatal(err)
}
}
func resizeTransport(expectedURL string) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
h := query.Get("h")
if h != "500" {
return nil, fmt.Errorf("h not set in URL query properly. Expected '500', got %s", h)
}
w := query.Get("w")
if w != "600" {
return nil, fmt.Errorf("w not set in URL query properly. Expected '600', got %s", w)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}
}

View File

@@ -1,48 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"time"
"context"
)
func TestContainerRestartError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
timeout := 0 * time.Second
err := client.ContainerRestart(context.Background(), "nothing", &timeout)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerRestart(t *testing.T) {
expectedURL := "/containers/container_id/restart"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
t := req.URL.Query().Get("t")
if t != "100" {
return nil, fmt.Errorf("t (timeout) not set in URL query properly. Expected '100', got %s", t)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
timeout := 100 * time.Second
err := client.ContainerRestart(context.Background(), "container_id", &timeout)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,58 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerStartError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerStart(context.Background(), "nothing", types.ContainerStartOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerStart(t *testing.T) {
expectedURL := "/containers/container_id/start"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
// we're not expecting any payload, but if one is supplied, check it is valid.
if req.Header.Get("Content-Type") == "application/json" {
var startConfig interface{}
if err := json.NewDecoder(req.Body).Decode(&startConfig); err != nil {
return nil, fmt.Errorf("Unable to parse json: %s", err)
}
}
checkpoint := req.URL.Query().Get("checkpoint")
if checkpoint != "checkpoint_id" {
return nil, fmt.Errorf("checkpoint not set in URL query properly. Expected 'checkpoint_id', got %s", checkpoint)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerStart(context.Background(), "container_id", types.ContainerStartOptions{CheckpointID: "checkpoint_id"})
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,70 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestContainerStatsError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerStats(context.Background(), "nothing", false)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerStats(t *testing.T) {
expectedURL := "/containers/container_id/stats"
cases := []struct {
stream bool
expectedStream string
}{
{
expectedStream: "0",
},
{
stream: true,
expectedStream: "1",
},
}
for _, c := range cases {
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
query := r.URL.Query()
stream := query.Get("stream")
if stream != c.expectedStream {
return nil, fmt.Errorf("stream not set in URL query properly. Expected '%s', got %s", c.expectedStream, stream)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("response"))),
}, nil
}),
}
body, err := client.ContainerStats(context.Background(), "container_id", c.stream)
if err != nil {
t.Fatal(err)
}
defer body.Close()
content, err := ioutil.ReadAll(body)
if err != nil {
t.Fatal(err)
}
if string(content) != "response" {
t.Fatalf("expected response to contain 'response', got %s", string(content))
}
}
}

View File

@@ -1,48 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"time"
"context"
)
func TestContainerStopError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
timeout := 0 * time.Second
err := client.ContainerStop(context.Background(), "nothing", &timeout)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerStop(t *testing.T) {
expectedURL := "/containers/container_id/stop"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
t := req.URL.Query().Get("t")
if t != "100" {
return nil, fmt.Errorf("t (timeout) not set in URL query properly. Expected '100', got %s", t)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
timeout := 100 * time.Second
err := client.ContainerStop(context.Background(), "container_id", &timeout)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,74 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestContainerTopError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerTop(context.Background(), "nothing", []string{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerTop(t *testing.T) {
expectedURL := "/containers/container_id/top"
expectedProcesses := [][]string{
{"p1", "p2"},
{"p3"},
}
expectedTitles := []string{"title1", "title2"}
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
args := query.Get("ps_args")
if args != "arg1 arg2" {
return nil, fmt.Errorf("args not set in URL query properly. Expected 'arg1 arg2', got %v", args)
}
b, err := json.Marshal(types.ContainerProcessList{
Processes: [][]string{
{"p1", "p2"},
{"p3"},
},
Titles: []string{"title1", "title2"},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
processList, err := client.ContainerTop(context.Background(), "container_id", []string{"arg1", "arg2"})
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(expectedProcesses, processList.Processes) {
t.Fatalf("Processes: expected %v, got %v", expectedProcesses, processList.Processes)
}
if !reflect.DeepEqual(expectedTitles, processList.Titles) {
t.Fatalf("Titles: expected %v, got %v", expectedTitles, processList.Titles)
}
}

View File

@@ -1,41 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestContainerUnpauseError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ContainerUnpause(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerUnpause(t *testing.T) {
expectedURL := "/containers/container_id/unpause"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ContainerUnpause(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,59 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/container"
)
func TestContainerUpdateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerUpdate(context.Background(), "nothing", container.UpdateConfig{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestContainerUpdate(t *testing.T) {
expectedURL := "/containers/container_id/update"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
b, err := json.Marshal(types.ContainerUpdateResponse{})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
_, err := client.ContainerUpdate(context.Background(), "container_id", container.UpdateConfig{
Resources: container.Resources{
CPUPeriod: 1,
},
RestartPolicy: container.RestartPolicy{
Name: "always",
},
})
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,70 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"testing"
"time"
"github.com/hyperhq/hyper-api/types"
"context"
)
func TestContainerWaitError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
code, err := client.ContainerWait(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
if code != -1 {
t.Fatalf("expected a status code equal to '-1', got %d", code)
}
}
func TestContainerWait(t *testing.T) {
expectedURL := "/containers/container_id/wait"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
b, err := json.Marshal(types.ContainerWaitResponse{
StatusCode: 15,
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
code, err := client.ContainerWait(context.Background(), "container_id")
if err != nil {
t.Fatal(err)
}
if code != 15 {
t.Fatalf("expected a status code equal to '15', got %d", code)
}
}
func ExampleClient_ContainerWait_withTimeout() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
client, _ := NewEnvClient()
_, err := client.ContainerWait(ctx, "container_id")
if err != nil {
log.Fatal(err)
}
}

View File

@@ -1,126 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/filters"
)
func TestEventsErrorInOptions(t *testing.T) {
errorCases := []struct {
options types.EventsOptions
expectedError string
}{
{
options: types.EventsOptions{
Since: "2006-01-02TZ",
},
expectedError: `parsing time "2006-01-02TZ"`,
},
{
options: types.EventsOptions{
Until: "2006-01-02TZ",
},
expectedError: `parsing time "2006-01-02TZ"`,
},
}
for _, e := range errorCases {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.Events(context.Background(), e.options)
if err == nil || !strings.Contains(err.Error(), e.expectedError) {
t.Fatalf("expected a error %q, got %v", e.expectedError, err)
}
}
}
func TestEventsErrorFromServer(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.Events(context.Background(), types.EventsOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestEvents(t *testing.T) {
expectedURL := "/events"
filters := filters.NewArgs()
filters.Add("label", "label1")
filters.Add("label", "label2")
expectedFiltersJSON := `{"label":{"label1":true,"label2":true}}`
eventsCases := []struct {
options types.EventsOptions
expectedQueryParams map[string]string
}{
{
options: types.EventsOptions{
Since: "invalid but valid",
},
expectedQueryParams: map[string]string{
"since": "invalid but valid",
},
},
{
options: types.EventsOptions{
Until: "invalid but valid",
},
expectedQueryParams: map[string]string{
"until": "invalid but valid",
},
},
{
options: types.EventsOptions{
Filters: filters,
},
expectedQueryParams: map[string]string{
"filters": expectedFiltersJSON,
},
},
}
for _, eventsCase := range eventsCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
for key, expected := range eventsCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("response"))),
}, nil
}),
}
body, err := client.Events(context.Background(), eventsCase.options)
if err != nil {
t.Fatal(err)
}
defer body.Close()
content, err := ioutil.ReadAll(body)
if err != nil {
t.Fatal(err)
}
if string(content) != "response" {
t.Fatalf("expected response to contain 'response', got %s", string(content))
}
}
}

View File

@@ -1,230 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"testing"
"context"
"github.com/docker/go-units"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/container"
)
func TestImageBuildError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageBuild(context.Background(), nil, types.ImageBuildOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImageBuild(t *testing.T) {
emptyRegistryConfig := "bnVsbA=="
buildCases := []struct {
buildOptions types.ImageBuildOptions
expectedQueryParams map[string]string
expectedTags []string
expectedRegistryConfig string
}{
{
buildOptions: types.ImageBuildOptions{
SuppressOutput: true,
NoCache: true,
Remove: true,
ForceRemove: true,
PullParent: true,
},
expectedQueryParams: map[string]string{
"q": "1",
"nocache": "1",
"rm": "1",
"forcerm": "1",
"pull": "1",
},
expectedTags: []string{},
expectedRegistryConfig: emptyRegistryConfig,
},
{
buildOptions: types.ImageBuildOptions{
SuppressOutput: false,
NoCache: false,
Remove: false,
ForceRemove: false,
PullParent: false,
},
expectedQueryParams: map[string]string{
"q": "",
"nocache": "",
"rm": "0",
"forcerm": "",
"pull": "",
},
expectedTags: []string{},
expectedRegistryConfig: emptyRegistryConfig,
},
{
buildOptions: types.ImageBuildOptions{
RemoteContext: "remoteContext",
Isolation: container.Isolation("isolation"),
CPUSetCPUs: "2",
CPUSetMems: "12",
CPUShares: 20,
CPUQuota: 10,
CPUPeriod: 30,
Memory: 256,
MemorySwap: 512,
ShmSize: 10,
CgroupParent: "cgroup_parent",
Dockerfile: "Dockerfile",
},
expectedQueryParams: map[string]string{
"remote": "remoteContext",
"isolation": "isolation",
"cpusetcpus": "2",
"cpusetmems": "12",
"cpushares": "20",
"cpuquota": "10",
"cpuperiod": "30",
"memory": "256",
"memswap": "512",
"shmsize": "10",
"cgroupparent": "cgroup_parent",
"dockerfile": "Dockerfile",
"rm": "0",
},
expectedTags: []string{},
expectedRegistryConfig: emptyRegistryConfig,
},
{
buildOptions: types.ImageBuildOptions{
BuildArgs: map[string]string{
"ARG1": "value1",
"ARG2": "value2",
},
},
expectedQueryParams: map[string]string{
"buildargs": `{"ARG1":"value1","ARG2":"value2"}`,
"rm": "0",
},
expectedTags: []string{},
expectedRegistryConfig: emptyRegistryConfig,
},
{
buildOptions: types.ImageBuildOptions{
Ulimits: []*units.Ulimit{
{
Name: "nproc",
Hard: 65557,
Soft: 65557,
},
{
Name: "nofile",
Hard: 20000,
Soft: 40000,
},
},
},
expectedQueryParams: map[string]string{
"ulimits": `[{"Name":"nproc","Hard":65557,"Soft":65557},{"Name":"nofile","Hard":20000,"Soft":40000}]`,
"rm": "0",
},
expectedTags: []string{},
expectedRegistryConfig: emptyRegistryConfig,
},
{
buildOptions: types.ImageBuildOptions{
AuthConfigs: map[string]types.AuthConfig{
"https://index.docker.io/v1/": {
Auth: "dG90bwo=",
},
},
},
expectedQueryParams: map[string]string{
"rm": "0",
},
expectedTags: []string{},
expectedRegistryConfig: "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289In19",
},
}
for _, buildCase := range buildCases {
expectedURL := "/build"
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
// Check request headers
registryConfig := r.Header.Get("X-Registry-Config")
if registryConfig != buildCase.expectedRegistryConfig {
return nil, fmt.Errorf("X-Registry-Config header not properly set in the request. Expected '%s', got %s", buildCase.expectedRegistryConfig, registryConfig)
}
contentType := r.Header.Get("Content-Type")
if contentType != "application/tar" {
return nil, fmt.Errorf("Content-type header not properly set in the request. Expected 'application/tar', got %s", contentType)
}
// Check query parameters
query := r.URL.Query()
for key, expected := range buildCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
// Check tags
if len(buildCase.expectedTags) > 0 {
tags := query["t"]
if !reflect.DeepEqual(tags, buildCase.expectedTags) {
return nil, fmt.Errorf("t (tags) not set in URL query properly. Expected '%s', got %s", buildCase.expectedTags, tags)
}
}
headers := http.Header{}
headers.Add("Server", "Docker/v1.23 (MyOS)")
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
Header: headers,
}, nil
}),
}
buildResponse, err := client.ImageBuild(context.Background(), nil, buildCase.buildOptions)
if err != nil {
t.Fatal(err)
}
if buildResponse.OSType != "MyOS" {
t.Fatalf("expected OSType to be 'MyOS', got %s", buildResponse.OSType)
}
response, err := ioutil.ReadAll(buildResponse.Body)
if err != nil {
t.Fatal(err)
}
buildResponse.Body.Close()
if string(response) != "body" {
t.Fatalf("expected Body to contain 'body' string, got %s", response)
}
}
}
func TestGetDockerOS(t *testing.T) {
cases := map[string]string{
"Docker/v1.22 (linux)": "linux",
"Docker/v1.22 (windows)": "windows",
"Foo/v1.22 (bar)": "",
}
for header, os := range cases {
g := getDockerOS(header)
if g != os {
t.Fatalf("Expected %s, got %s", os, g)
}
}
}

View File

@@ -1,76 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestImageCreateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageCreate(context.Background(), "reference", types.ImageCreateOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestImageCreate(t *testing.T) {
expectedURL := "/images/create"
expectedImage := "test:5000/my_image"
expectedTag := "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
expectedReference := fmt.Sprintf("%s@%s", expectedImage, expectedTag)
expectedRegistryAuth := "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289IiwiZW1haWwiOiJqb2huQGRvZS5jb20ifX0="
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
registryAuth := r.Header.Get("X-Registry-Auth")
if registryAuth != expectedRegistryAuth {
return nil, fmt.Errorf("X-Registry-Auth header not properly set in the request. Expected '%s', got %s", expectedRegistryAuth, registryAuth)
}
query := r.URL.Query()
fromImage := query.Get("fromImage")
if fromImage != expectedImage {
return nil, fmt.Errorf("fromImage not set in URL query properly. Expected '%s', got %s", expectedImage, fromImage)
}
tag := query.Get("tag")
if tag != expectedTag {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", expectedTag, tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
}, nil
}),
}
createResponse, err := client.ImageCreate(context.Background(), expectedReference, types.ImageCreateOptions{
RegistryAuth: expectedRegistryAuth,
})
if err != nil {
t.Fatal(err)
}
response, err := ioutil.ReadAll(createResponse)
if err != nil {
t.Fatal(err)
}
if err = createResponse.Close(); err != nil {
t.Fatal(err)
}
if string(response) != "body" {
t.Fatalf("expected Body to contain 'body' string, got %s", response)
}
}

View File

@@ -1,60 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestImageHistoryError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageHistory(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestImageHistory(t *testing.T) {
expectedURL := "/images/image_id/history"
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
b, err := json.Marshal([]types.ImageHistory{
{
ID: "image_id1",
Tags: []string{"tag1", "tag2"},
},
{
ID: "image_id2",
Tags: []string{"tag1", "tag2"},
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
imageHistories, err := client.ImageHistory(context.Background(), "image_id")
if err != nil {
t.Fatal(err)
}
if len(imageHistories) != 2 {
t.Fatalf("expected 2 containers, got %v", imageHistories)
}
}

View File

@@ -1,81 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestImageImportError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageImport(context.Background(), types.ImageImportSource{}, "image:tag", types.ImageImportOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestImageImport(t *testing.T) {
expectedURL := "/images/create"
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
query := r.URL.Query()
fromSrc := query.Get("fromSrc")
if fromSrc != "image_source" {
return nil, fmt.Errorf("fromSrc not set in URL query properly. Expected 'image_source', got %s", fromSrc)
}
repo := query.Get("repo")
if repo != "repository_name:imported" {
return nil, fmt.Errorf("repo not set in URL query properly. Expected 'repository_name', got %s", repo)
}
tag := query.Get("tag")
if tag != "imported" {
return nil, fmt.Errorf("tag not set in URL query properly. Expected 'imported', got %s", tag)
}
message := query.Get("message")
if message != "A message" {
return nil, fmt.Errorf("message not set in URL query properly. Expected 'A message', got %s", message)
}
changes := query["changes"]
expectedChanges := []string{"change1", "change2"}
if !reflect.DeepEqual(expectedChanges, changes) {
return nil, fmt.Errorf("changes not set in URL query properly. Expected %v, got %v", expectedChanges, changes)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("response"))),
}, nil
}),
}
importResponse, err := client.ImageImport(context.Background(), types.ImageImportSource{
Source: strings.NewReader("source"),
SourceName: "image_source",
}, "repository_name:imported", types.ImageImportOptions{
Tag: "imported",
Message: "A message",
Changes: []string{"change1", "change2"},
})
if err != nil {
t.Fatal(err)
}
response, err := ioutil.ReadAll(importResponse)
if err != nil {
t.Fatal(err)
}
importResponse.Close()
if string(response) != "response" {
t.Fatalf("expected response to contain 'response', got %s", string(response))
}
}

View File

@@ -1,71 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestImageInspectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, _, err := client.ImageInspectWithRaw(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImageInspectImageNotFound(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")),
}
_, _, err := client.ImageInspectWithRaw(context.Background(), "unknown")
if err == nil || !IsErrImageNotFound(err) {
t.Fatalf("expected an imageNotFound error, got %v", err)
}
}
func TestImageInspect(t *testing.T) {
expectedURL := "/images/image_id/json"
expectedTags := []string{"tag1", "tag2"}
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
content, err := json.Marshal(types.ImageInspect{
ID: "image_id",
RepoTags: expectedTags,
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
imageInspect, _, err := client.ImageInspectWithRaw(context.Background(), "image_id")
if err != nil {
t.Fatal(err)
}
if imageInspect.ID != "image_id" {
t.Fatalf("expected `image_id`, got %s", imageInspect.ID)
}
if !reflect.DeepEqual(imageInspect.RepoTags, expectedTags) {
t.Fatalf("expected `%v`, got %v", expectedTags, imageInspect.RepoTags)
}
}

View File

@@ -1,122 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/filters"
)
func TestImageListError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageList(context.Background(), types.ImageListOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImageList(t *testing.T) {
expectedURL := "/images/json"
noDanglingfilters := filters.NewArgs()
noDanglingfilters.Add("dangling", "false")
filters := filters.NewArgs()
filters.Add("label", "label1")
filters.Add("label", "label2")
filters.Add("dangling", "true")
listCases := []struct {
options types.ImageListOptions
expectedQueryParams map[string]string
}{
{
options: types.ImageListOptions{},
expectedQueryParams: map[string]string{
"all": "",
"filter": "",
"filters": "",
},
},
{
options: types.ImageListOptions{
All: true,
MatchName: "image_name",
},
expectedQueryParams: map[string]string{
"all": "1",
"filter": "image_name",
"filters": "",
},
},
{
options: types.ImageListOptions{
Filters: filters,
},
expectedQueryParams: map[string]string{
"all": "",
"filter": "",
"filters": `{"dangling":{"true":true},"label":{"label1":true,"label2":true}}`,
},
},
{
options: types.ImageListOptions{
Filters: noDanglingfilters,
},
expectedQueryParams: map[string]string{
"all": "",
"filter": "",
"filters": `{"dangling":{"false":true}}`,
},
},
}
for _, listCase := range listCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
for key, expected := range listCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
content, err := json.Marshal([]types.Image{
{
ID: "image_id2",
},
{
ID: "image_id2",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
images, err := client.ImageList(context.Background(), listCase.options)
if err != nil {
t.Fatal(err)
}
if len(images) != 2 {
t.Fatalf("expected 2 images, got %v", images)
}
}
}

View File

@@ -1,95 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestImageLoadError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageLoad(context.Background(), nil, true)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImageLoad(t *testing.T) {
expectedURL := "/images/load"
expectedInput := "inputBody"
expectedOutput := "outputBody"
loadCases := []struct {
quiet bool
responseContentType string
expectedResponseJSON bool
expectedQueryParams map[string]string
}{
{
quiet: false,
responseContentType: "text/plain",
expectedResponseJSON: false,
expectedQueryParams: map[string]string{
"quiet": "0",
},
},
{
quiet: true,
responseContentType: "application/json",
expectedResponseJSON: true,
expectedQueryParams: map[string]string{
"quiet": "1",
},
},
}
for _, loadCase := range loadCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
contentType := req.Header.Get("Content-Type")
if contentType != "application/x-tar" {
return nil, fmt.Errorf("content-type not set in URL headers properly. Expected 'application/x-tar', got %s", contentType)
}
query := req.URL.Query()
for key, expected := range loadCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
headers := http.Header{}
headers.Add("Content-Type", loadCase.responseContentType)
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(expectedOutput))),
Header: headers,
}, nil
}),
}
input := bytes.NewReader([]byte(expectedInput))
imageLoadResponse, err := client.ImageLoad(context.Background(), input, loadCase.quiet)
if err != nil {
t.Fatal(err)
}
if imageLoadResponse.JSON != loadCase.expectedResponseJSON {
t.Fatalf("expected a JSON response, was not.")
}
body, err := ioutil.ReadAll(imageLoadResponse.Body)
if err != nil {
t.Fatal(err)
}
if string(body) != expectedOutput {
t.Fatalf("expected %s, got %s", expectedOutput, string(body))
}
}
}

View File

@@ -1,199 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestImagePullReferenceParseError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
return nil, nil
}),
}
// An empty reference is an invalid reference
_, err := client.ImagePull(context.Background(), "", types.ImagePullOptions{})
if err == nil || err.Error() != "repository name must have at least one component" {
t.Fatalf("expected an error, got %v", err)
}
}
func TestImagePullAnyError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImagePullStatusUnauthorizedError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
_, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{})
if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
t.Fatalf("expected an Unauthorized Error, got %v", err)
}
}
func TestImagePullWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
privilegeFunc := func() (string, error) {
return "", fmt.Errorf("Error requesting privilege")
}
_, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{
PrivilegeFunc: privilegeFunc,
})
if err == nil || err.Error() != "Error requesting privilege" {
t.Fatalf("expected an error requesting privilege, got %v", err)
}
}
func TestImagePullWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
privilegeFunc := func() (string, error) {
return "a-auth-header", nil
}
_, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{
PrivilegeFunc: privilegeFunc,
})
if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
t.Fatalf("expected an Unauthorized Error, got %v", err)
}
}
func TestImagePullWithPrivilegedFuncNoError(t *testing.T) {
expectedURL := "/images/create"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
auth := req.Header.Get("X-Registry-Auth")
if auth == "NotValid" {
return &http.Response{
StatusCode: http.StatusUnauthorized,
Body: ioutil.NopCloser(bytes.NewReader([]byte("Invalid credentials"))),
}, nil
}
if auth != "IAmValid" {
return nil, fmt.Errorf("Invalid auth header : expected %s, got %s", "IAmValid", auth)
}
query := req.URL.Query()
fromImage := query.Get("fromImage")
if fromImage != "myimage" {
return nil, fmt.Errorf("fromimage not set in URL query properly. Expected '%s', got %s", "myimage", fromImage)
}
tag := query.Get("tag")
if tag != "latest" {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", "latest", tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("hello world"))),
}, nil
}),
}
privilegeFunc := func() (string, error) {
return "IAmValid", nil
}
resp, err := client.ImagePull(context.Background(), "myimage", types.ImagePullOptions{
RegistryAuth: "NotValid",
PrivilegeFunc: privilegeFunc,
})
if err != nil {
t.Fatal(err)
}
body, err := ioutil.ReadAll(resp)
if err != nil {
t.Fatal(err)
}
if string(body) != "hello world" {
t.Fatalf("expected 'hello world', got %s", string(body))
}
}
func TestImagePullWithoutErrors(t *testing.T) {
expectedURL := "/images/create"
expectedOutput := "hello world"
pullCases := []struct {
all bool
reference string
expectedImage string
expectedTag string
}{
{
all: false,
reference: "myimage",
expectedImage: "myimage",
expectedTag: "latest",
},
{
all: false,
reference: "myimage:tag",
expectedImage: "myimage",
expectedTag: "tag",
},
{
all: true,
reference: "myimage",
expectedImage: "myimage",
expectedTag: "",
},
{
all: true,
reference: "myimage:anything",
expectedImage: "myimage",
expectedTag: "",
},
}
for _, pullCase := range pullCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
fromImage := query.Get("fromImage")
if fromImage != pullCase.expectedImage {
return nil, fmt.Errorf("fromimage not set in URL query properly. Expected '%s', got %s", pullCase.expectedImage, fromImage)
}
tag := query.Get("tag")
if tag != pullCase.expectedTag {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", pullCase.expectedTag, tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(expectedOutput))),
}, nil
}),
}
resp, err := client.ImagePull(context.Background(), pullCase.reference, types.ImagePullOptions{
All: pullCase.all,
})
if err != nil {
t.Fatal(err)
}
body, err := ioutil.ReadAll(resp)
if err != nil {
t.Fatal(err)
}
if string(body) != expectedOutput {
t.Fatalf("expected '%s', got %s", expectedOutput, string(body))
}
}
}

View File

@@ -1,180 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestImagePushReferenceError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
return nil, nil
}),
}
// An empty reference is an invalid reference
_, err := client.ImagePush(context.Background(), "", types.ImagePushOptions{})
if err == nil || err.Error() != "repository name must have at least one component" {
t.Fatalf("expected an error, got %v", err)
}
// An canonical reference cannot be pushed
_, err = client.ImagePush(context.Background(), "repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", types.ImagePushOptions{})
if err == nil || err.Error() != "cannot push a digest reference" {
t.Fatalf("expected an error, got %v", err)
}
}
func TestImagePushAnyError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImagePushStatusUnauthorizedError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
_, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{})
if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
t.Fatalf("expected an Unauthorized Error, got %v", err)
}
}
func TestImagePushWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
privilegeFunc := func() (string, error) {
return "", fmt.Errorf("Error requesting privilege")
}
_, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{
PrivilegeFunc: privilegeFunc,
})
if err == nil || err.Error() != "Error requesting privilege" {
t.Fatalf("expected an error requesting privilege, got %v", err)
}
}
func TestImagePushWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
privilegeFunc := func() (string, error) {
return "a-auth-header", nil
}
_, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{
PrivilegeFunc: privilegeFunc,
})
if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
t.Fatalf("expected an Unauthorized Error, got %v", err)
}
}
func TestImagePushWithPrivilegedFuncNoError(t *testing.T) {
expectedURL := "/images/myimage/push"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
auth := req.Header.Get("X-Registry-Auth")
if auth == "NotValid" {
return &http.Response{
StatusCode: http.StatusUnauthorized,
Body: ioutil.NopCloser(bytes.NewReader([]byte("Invalid credentials"))),
}, nil
}
if auth != "IAmValid" {
return nil, fmt.Errorf("Invalid auth header : expected %s, got %s", "IAmValid", auth)
}
query := req.URL.Query()
tag := query.Get("tag")
if tag != "tag" {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", "tag", tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("hello world"))),
}, nil
}),
}
privilegeFunc := func() (string, error) {
return "IAmValid", nil
}
resp, err := client.ImagePush(context.Background(), "myimage:tag", types.ImagePushOptions{
RegistryAuth: "NotValid",
PrivilegeFunc: privilegeFunc,
})
if err != nil {
t.Fatal(err)
}
body, err := ioutil.ReadAll(resp)
if err != nil {
t.Fatal(err)
}
if string(body) != "hello world" {
t.Fatalf("expected 'hello world', got %s", string(body))
}
}
func TestImagePushWithoutErrors(t *testing.T) {
expectedOutput := "hello world"
expectedURLFormat := "/images/%s/push"
pullCases := []struct {
reference string
expectedImage string
expectedTag string
}{
{
reference: "myimage",
expectedImage: "myimage",
expectedTag: "",
},
{
reference: "myimage:tag",
expectedImage: "myimage",
expectedTag: "tag",
},
}
for _, pullCase := range pullCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
expectedURL := fmt.Sprintf(expectedURLFormat, pullCase.expectedImage)
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
tag := query.Get("tag")
if tag != pullCase.expectedTag {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", pullCase.expectedTag, tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(expectedOutput))),
}, nil
}),
}
resp, err := client.ImagePush(context.Background(), pullCase.reference, types.ImagePushOptions{})
if err != nil {
t.Fatal(err)
}
body, err := ioutil.ReadAll(resp)
if err != nil {
t.Fatal(err)
}
if string(body) != expectedOutput {
t.Fatalf("expected '%s', got %s", expectedOutput, string(body))
}
}
}

View File

@@ -1,95 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
)
func TestImageRemoveError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageRemove(context.Background(), "image_id", types.ImageRemoveOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImageRemove(t *testing.T) {
expectedURL := "/images/image_id"
removeCases := []struct {
force bool
pruneChildren bool
expectedQueryParams map[string]string
}{
{
force: false,
pruneChildren: false,
expectedQueryParams: map[string]string{
"force": "",
"noprune": "1",
},
}, {
force: true,
pruneChildren: true,
expectedQueryParams: map[string]string{
"force": "1",
"noprune": "",
},
},
}
for _, removeCase := range removeCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "DELETE" {
return nil, fmt.Errorf("expected DELETE method, got %s", req.Method)
}
query := req.URL.Query()
for key, expected := range removeCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
b, err := json.Marshal([]types.ImageDelete{
{
Untagged: "image_id1",
},
{
Deleted: "image_id",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
imageDeletes, err := client.ImageRemove(context.Background(), "image_id", types.ImageRemoveOptions{
Force: removeCase.force,
PruneChildren: removeCase.pruneChildren,
})
if err != nil {
t.Fatal(err)
}
if len(imageDeletes) != 2 {
t.Fatalf("expected 2 deleted images, got %v", imageDeletes)
}
}
}

View File

@@ -1,56 +0,0 @@
package client
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"testing"
)
func TestImageSaveError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageSave(context.Background(), []string{"nothing"})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server error, got %v", err)
}
}
func TestImageSave(t *testing.T) {
expectedURL := "/images/get"
client := &Client{
transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
}
query := r.URL.Query()
names := query["names"]
expectedNames := []string{"image_id1", "image_id2"}
if !reflect.DeepEqual(names, expectedNames) {
return nil, fmt.Errorf("names not set in URL query properly. Expected %v, got %v", names, expectedNames)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("response"))),
}, nil
}),
}
saveResponse, err := client.ImageSave(context.Background(), []string{"image_id1", "image_id2"})
if err != nil {
t.Fatal(err)
}
response, err := ioutil.ReadAll(saveResponse)
if err != nil {
t.Fatal(err)
}
saveResponse.Close()
if string(response) != "response" {
t.Fatalf("expected response to contain 'response', got %s", string(response))
}
}

View File

@@ -1,164 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/filters"
"github.com/hyperhq/hyper-api/types/registry"
)
func TestImageSearchAnyError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestImageSearchStatusUnauthorizedError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
_, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{})
if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
t.Fatalf("expected an Unauthorized Error, got %v", err)
}
}
func TestImageSearchWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
privilegeFunc := func() (string, error) {
return "", fmt.Errorf("Error requesting privilege")
}
_, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
PrivilegeFunc: privilegeFunc,
})
if err == nil || err.Error() != "Error requesting privilege" {
t.Fatalf("expected an error requesting privilege, got %v", err)
}
}
func TestImageSearchWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusUnauthorized, "Unauthorized error")),
}
privilegeFunc := func() (string, error) {
return "a-auth-header", nil
}
_, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
PrivilegeFunc: privilegeFunc,
})
if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
t.Fatalf("expected an Unauthorized Error, got %v", err)
}
}
func TestImageSearchWithPrivilegedFuncNoError(t *testing.T) {
expectedURL := "/images/search"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
auth := req.Header.Get("X-Registry-Auth")
if auth == "NotValid" {
return &http.Response{
StatusCode: http.StatusUnauthorized,
Body: ioutil.NopCloser(bytes.NewReader([]byte("Invalid credentials"))),
}, nil
}
if auth != "IAmValid" {
return nil, fmt.Errorf("Invalid auth header : expected %s, got %s", "IAmValid", auth)
}
query := req.URL.Query()
term := query.Get("term")
if term != "some-image" {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", "some-image", term)
}
content, err := json.Marshal([]registry.SearchResult{
{
Name: "anything",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
privilegeFunc := func() (string, error) {
return "IAmValid", nil
}
results, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
RegistryAuth: "NotValid",
PrivilegeFunc: privilegeFunc,
})
if err != nil {
t.Fatal(err)
}
if len(results) != 1 {
t.Fatalf("expected a result, got %v", results)
}
}
func TestImageSearchWithoutErrors(t *testing.T) {
expectedURL := "/images/search"
filterArgs := filters.NewArgs()
filterArgs.Add("is-automated", "true")
filterArgs.Add("stars", "3")
expectedFilters := `{"is-automated":{"true":true},"stars":{"3":true}}`
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
term := query.Get("term")
if term != "some-image" {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", "some-image", term)
}
filters := query.Get("filters")
if filters != expectedFilters {
return nil, fmt.Errorf("filters not set in URL query properly. Expected '%s', got %s", expectedFilters, filters)
}
content, err := json.Marshal([]registry.SearchResult{
{
Name: "anything",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
results, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
Filters: filterArgs,
})
if err != nil {
t.Fatal(err)
}
if len(results) != 1 {
t.Fatalf("expected a result, got %v", results)
}
}

View File

@@ -1,120 +0,0 @@
package client
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
)
func TestImageTagError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ImageTag(context.Background(), "image_id", "repo:tag")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
// Note: this is not testing all the InvalidReference as it's the reponsability
// of distribution/reference package.
func TestImageTagInvalidReference(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ImageTag(context.Background(), "image_id", "aa/asdf$$^/aa")
if err == nil || err.Error() != `Error parsing reference: "aa/asdf$$^/aa" is not a valid repository/tag` {
t.Fatalf("expected ErrReferenceInvalidFormat, got %v", err)
}
}
func TestImageTag(t *testing.T) {
expectedURL := "/images/image_id/tag"
tagCases := []struct {
reference string
expectedQueryParams map[string]string
}{
{
reference: "repository:tag1",
expectedQueryParams: map[string]string{
"repo": "repository",
"tag": "tag1",
},
}, {
reference: "another_repository:latest",
expectedQueryParams: map[string]string{
"repo": "another_repository",
"tag": "latest",
},
}, {
reference: "another_repository",
expectedQueryParams: map[string]string{
"repo": "another_repository",
"tag": "latest",
},
}, {
reference: "test/another_repository",
expectedQueryParams: map[string]string{
"repo": "test/another_repository",
"tag": "latest",
},
}, {
reference: "test/another_repository:tag1",
expectedQueryParams: map[string]string{
"repo": "test/another_repository",
"tag": "tag1",
},
}, {
reference: "test/test/another_repository:tag1",
expectedQueryParams: map[string]string{
"repo": "test/test/another_repository",
"tag": "tag1",
},
}, {
reference: "test:5000/test/another_repository:tag1",
expectedQueryParams: map[string]string{
"repo": "test:5000/test/another_repository",
"tag": "tag1",
},
}, {
reference: "test:5000/test/another_repository",
expectedQueryParams: map[string]string{
"repo": "test:5000/test/another_repository",
"tag": "latest",
},
},
}
for _, tagCase := range tagCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
query := req.URL.Query()
for key, expected := range tagCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
}
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.ImageTag(context.Background(), "image_id", tagCase.reference)
if err != nil {
t.Fatal(err)
}
}
}

View File

@@ -1,76 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
)
func TestInfoServerError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.Info(context.Background())
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestInfoInvalidResponseJSONError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("invalid json"))),
}, nil
}),
}
_, err := client.Info(context.Background())
if err == nil || !strings.Contains(err.Error(), "invalid character") {
t.Fatalf("expected a 'invalid character' error, got %v", err)
}
}
func TestInfo(t *testing.T) {
expectedURL := "/info"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
info := &types.Info{
ID: "daemonID",
Containers: 3,
}
b, err := json.Marshal(info)
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),
}
info, err := client.Info(context.Background())
if err != nil {
t.Fatal(err)
}
if info.ID != "daemonID" {
t.Fatalf("expected daemonID, got %s", info.ID)
}
if info.Containers != 3 {
t.Fatalf("expected 3 containers, got %d", info.Containers)
}
}

View File

@@ -1,107 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/network"
)
func TestNetworkConnectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.NetworkConnect(context.Background(), "network_id", "container_id", nil)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestNetworkConnectEmptyNilEndpointSettings(t *testing.T) {
expectedURL := "/networks/network_id/connect"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
var connect types.NetworkConnect
if err := json.NewDecoder(req.Body).Decode(&connect); err != nil {
return nil, err
}
if connect.Container != "container_id" {
return nil, fmt.Errorf("expected 'container_id', got %s", connect.Container)
}
if connect.EndpointConfig != nil {
return nil, fmt.Errorf("expected connect.EndpointConfig to be nil, got %v", connect.EndpointConfig)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.NetworkConnect(context.Background(), "network_id", "container_id", nil)
if err != nil {
t.Fatal(err)
}
}
func TestNetworkConnect(t *testing.T) {
expectedURL := "/networks/network_id/connect"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
var connect types.NetworkConnect
if err := json.NewDecoder(req.Body).Decode(&connect); err != nil {
return nil, err
}
if connect.Container != "container_id" {
return nil, fmt.Errorf("expected 'container_id', got %s", connect.Container)
}
if connect.EndpointConfig.NetworkID != "NetworkID" {
return nil, fmt.Errorf("expected 'NetworkID', got %s", connect.EndpointConfig.NetworkID)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.NetworkConnect(context.Background(), "network_id", "container_id", &network.EndpointSettings{
NetworkID: "NetworkID",
})
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,72 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestNetworkCreateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.NetworkCreate(context.Background(), "mynetwork", types.NetworkCreate{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestNetworkCreate(t *testing.T) {
expectedURL := "/networks/create"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
content, err := json.Marshal(types.NetworkCreateResponse{
ID: "network_id",
Warning: "warning",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
networkResponse, err := client.NetworkCreate(context.Background(), "mynetwork", types.NetworkCreate{
CheckDuplicate: true,
Driver: "mydriver",
EnableIPv6: true,
Internal: true,
Options: map[string]string{
"opt-key": "opt-value",
},
})
if err != nil {
t.Fatal(err)
}
if networkResponse.ID != "network_id" {
t.Fatalf("expected networkResponse.ID to be 'network_id', got %s", networkResponse.ID)
}
if networkResponse.Warning != "warning" {
t.Fatalf("expected networkResponse.Warning to be 'warning', got %s", networkResponse.Warning)
}
}

View File

@@ -1,64 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestNetworkDisconnectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.NetworkDisconnect(context.Background(), "network_id", "container_id", false)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestNetworkDisconnect(t *testing.T) {
expectedURL := "/networks/network_id/disconnect"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
var disconnect types.NetworkDisconnect
if err := json.NewDecoder(req.Body).Decode(&disconnect); err != nil {
return nil, err
}
if disconnect.Container != "container_id" {
return nil, fmt.Errorf("expected 'container_id', got %s", disconnect.Container)
}
if !disconnect.Force {
return nil, fmt.Errorf("expected Force to be true, got %v", disconnect.Force)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte(""))),
}, nil
}),
}
err := client.NetworkDisconnect(context.Background(), "network_id", "container_id", true)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,69 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestNetworkInspectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.NetworkInspect(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestNetworkInspectContainerNotFound(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")),
}
_, err := client.NetworkInspect(context.Background(), "unknown")
if err == nil || !IsErrNetworkNotFound(err) {
t.Fatalf("expected a containerNotFound error, got %v", err)
}
}
func TestNetworkInspect(t *testing.T) {
expectedURL := "/networks/network_id"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "GET" {
return nil, fmt.Errorf("expected GET method, got %s", req.Method)
}
content, err := json.Marshal(types.NetworkResource{
Name: "mynetwork",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
r, err := client.NetworkInspect(context.Background(), "network_id")
if err != nil {
t.Fatal(err)
}
if r.Name != "mynetwork" {
t.Fatalf("expected `mynetwork`, got %s", r.Name)
}
}

View File

@@ -1,108 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/filters"
)
func TestNetworkListError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.NetworkList(context.Background(), types.NetworkListOptions{
Filters: filters.NewArgs(),
})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestNetworkList(t *testing.T) {
expectedURL := "/networks"
noDanglingFilters := filters.NewArgs()
noDanglingFilters.Add("dangling", "false")
danglingFilters := filters.NewArgs()
danglingFilters.Add("dangling", "true")
labelFilters := filters.NewArgs()
labelFilters.Add("label", "label1")
labelFilters.Add("label", "label2")
listCases := []struct {
options types.NetworkListOptions
expectedFilters string
}{
{
options: types.NetworkListOptions{
Filters: filters.NewArgs(),
},
expectedFilters: "",
}, {
options: types.NetworkListOptions{
Filters: noDanglingFilters,
},
expectedFilters: `{"dangling":{"false":true}}`,
}, {
options: types.NetworkListOptions{
Filters: danglingFilters,
},
expectedFilters: `{"dangling":{"true":true}}`,
}, {
options: types.NetworkListOptions{
Filters: labelFilters,
},
expectedFilters: `{"label":{"label1":true,"label2":true}}`,
},
}
for _, listCase := range listCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "GET" {
return nil, fmt.Errorf("expected GET method, got %s", req.Method)
}
query := req.URL.Query()
actualFilters := query.Get("filters")
if actualFilters != listCase.expectedFilters {
return nil, fmt.Errorf("filters not set in URL query properly. Expected '%s', got %s", listCase.expectedFilters, actualFilters)
}
content, err := json.Marshal([]types.NetworkResource{
{
Name: "network",
Driver: "bridge",
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
networkResources, err := client.NetworkList(context.Background(), listCase.options)
if err != nil {
t.Fatal(err)
}
if len(networkResources) != 1 {
t.Fatalf("expected 1 network resource, got %v", networkResources)
}
}
}

View File

@@ -1,47 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestNetworkRemoveError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.NetworkRemove(context.Background(), "network_id")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestNetworkRemove(t *testing.T) {
expectedURL := "/networks/network_id"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "DELETE" {
return nil, fmt.Errorf("expected DELETE method, got %s", req.Method)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
}, nil
}),
}
err := client.NetworkRemove(context.Background(), "network_id")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,91 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
// TestSetHostHeader should set fake host for local communications, set real host
// for normal communications.
func TestSetHostHeader(t *testing.T) {
testURL := "/test"
testCases := []struct {
host string
expectedHost string
expectedURLHost string
}{
{
"unix:///var/run/docker.sock",
"docker",
"/var/run/docker.sock",
},
{
"npipe:////./pipe/docker_engine",
"docker",
"//./pipe/docker_engine",
},
{
"tcp://0.0.0.0:4243",
"",
"0.0.0.0:4243",
},
{
"tcp://localhost:4243",
"",
"localhost:4243",
},
}
for c, test := range testCases {
proto, addr, basePath, err := ParseHost(test.host)
if err != nil {
t.Fatal(err)
}
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, testURL) {
return nil, fmt.Errorf("Test Case #%d: Expected URL %q, got %q", c, testURL, req.URL)
}
if req.Host != test.expectedHost {
return nil, fmt.Errorf("Test Case #%d: Expected host %q, got %q", c, test.expectedHost, req.Host)
}
if req.URL.Host != test.expectedURLHost {
return nil, fmt.Errorf("Test Case #%d: Expected URL host %q, got %q", c, test.expectedURLHost, req.URL.Host)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(([]byte("")))),
}, nil
}),
proto: proto,
addr: addr,
basePath: basePath,
}
_, err = client.sendRequest(context.Background(), "GET", testURL, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
}
}
// TestPlainTextError tests the server returning an error in plain text for
// backwards compatibility with API versions <1.24. All other tests use
// errors returned as JSON
func TestPlainTextError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, plainTextErrorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.ContainerList(context.Background(), types.ContainerListOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}

View File

@@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgIRAILlP5WWLaHkQ/m2ASHP7SowDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHdmluY2VudDAeFw0xNjAzMjQxMDE5MDBaFw0xOTAzMDkxMDE5
MDBaMBIxEDAOBgNVBAoTB3ZpbmNlbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQD0yZPKAGncoaxaU/QW9tWEHbrvDoGVF/65L8Si/jBrlAgLjhmmV1di
vKG9QPzuU8snxHro3/uCwyA6kTqw0U8bGwHxJq2Bpa6JBYj8N2jMJ+M+sjXgSo2t
E0zIzjTW2Pir3C8qwfrVL6NFp9xClwMD23SFZ0UsEH36NkfyrKBVeM8IOjJd4Wjs
xIcuvF3BTVkji84IJBW2JIKf9ZrzJwUlSCPgptRp4Evdbyp5d+UPxtwxD7qjW4lM
yQQ8vfcC4lKkVx5s/RNJ4fzd5uEgLdEbZ20qt7Zt/bLcxFHpUhH2teA0QjmrOWFh
gbL83s95/+hbSVhsO4hoFW7vTeiCCY4xAgMBAAGjIzAhMA4GA1UdDwEB/wQEAwIC
rDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBY51RHajuDuhO2
tcm26jeNROzfffnjhvbOVPjSEdo9vI3JpMU/RuQw+nbNcLwJrdjL6UH7tD/36Y+q
NXH+xSIjWFH0zXGxrIUsVrvt6f8CbOvw7vD+gygOG+849PDQMbL6czP8rvXY7vZV
9pdpQfrENk4b5kePRW/6HaGSTvtgN7XOrYD9fp3pm/G534T2e3IxgYMRNwdB9Ul9
bLwMqQqf4eiqqMs6x4IVmZUkGVMKiFKcvkNg9a+Ozx5pMizHeAezWMcZ5V+QJZVT
8lElSCKZ2Yy2xkcl7aeQMLwcAeZwfTp+Yu9dVzlqXiiBTLd1+LtAQCuKHzmw4Q8k
EvD5m49l
-----END CERTIFICATE-----

View File

@@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC8DCCAdigAwIBAgIRAJAS1glgcke4q7eCaretwgUwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHdmluY2VudDAeFw0xNjAzMjQxMDE5MDBaFw0xOTAzMDkxMDE5
MDBaMB4xHDAaBgNVBAoME3ZpbmNlbnQuPGJvb3RzdHJhcD4wggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQClpvG442dGEvrRgmCrqY4kBml1LVlw2Y7ZDn6B
TKa52+MuGDmfXbO1UhclNqTXjLgAwKjPz/OvnPRxNEUoQEDbBd+Xev7rxTY5TvYI
27YH3fMH2LL2j62jum649abfhZ6ekD5eD8tCn3mnrEOgqRIlK7efPIVixq/ZqU1H
7ez0ggB7dmWHlhnUaxyQOCSnAX/7nKYQXqZgVvGhDeR2jp7GcnhbK/qPrZ/mOm83
2IjCeYN145opYlzTSp64GYIZz7uqMNcnDKK37ZbS8MYcTjrRaHEiqZVVdIC+ghbx
qYqzbZRVfgztI9jwmifn0mYrN4yt+nhNYwBcRJ4Pv3uLFbo7AgMBAAGjNTAzMA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA
MA0GCSqGSIb3DQEBCwUAA4IBAQDg1r7nksjYgDFYEcBbrRrRHddIoK+RVmSBTTrq
8giC77m0srKdh9XTVWK1PUbGfODV1oD8m9QhPE8zPDyYQ8jeXNRSU5wXdkrTRmmY
w/T3SREqmE7CObMtusokHidjYFuqqCR07sJzqBKRlzr3o0EGe3tuEhUlF5ARY028
eipaDcVlT5ChGcDa6LeJ4e05u4cVap0dd6Rp1w3Rx1AYAecdgtgBMnw1iWdl/nrC
sp26ZXNaAhFOUovlY9VY257AMd9hQV7WvAK4yNEHcckVu3uXTBmDgNSOPtl0QLsL
Kjlj75ksCx8nCln/hCut/0+kGTsGZqdV5c6ktgcGYRir/5Hs
-----END CERTIFICATE-----

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEApabxuONnRhL60YJgq6mOJAZpdS1ZcNmO2Q5+gUymudvjLhg5
n12ztVIXJTak14y4AMCoz8/zr5z0cTRFKEBA2wXfl3r+68U2OU72CNu2B93zB9iy
9o+to7puuPWm34WenpA+Xg/LQp95p6xDoKkSJSu3nzyFYsav2alNR+3s9IIAe3Zl
h5YZ1GsckDgkpwF/+5ymEF6mYFbxoQ3kdo6exnJ4Wyv6j62f5jpvN9iIwnmDdeOa
KWJc00qeuBmCGc+7qjDXJwyit+2W0vDGHE460WhxIqmVVXSAvoIW8amKs22UVX4M
7SPY8Jon59JmKzeMrfp4TWMAXESeD797ixW6OwIDAQABAoIBAHfyAAleL8NfrtnR
S+pApbmUIvxD0AWUooispBE/zWG6xC72P5MTqDJctIGvpYCmVf3Fgvamns7EGYN2
07Sngc6V3Ca1WqyhaffpIuGbJZ1gqr89u6gotRRexBmNVj13ZTlvPJmjWgxtqQsu
AvHsOkVL+HOGwRaaw24Z1umEcBVCepl7PGTqsLeJUtBUZBiqdJTu4JYLAB6BggBI
OxhHoTWvlNWwzezo2C/IXkXcXD/tp3i5vTn5rAXHSMQkdMAUh7/xJ73Fl36gxZhp
W7NoPKaS9qNh8jhs6p54S7tInb6+mrKtvRFKl5XAR3istXrXteT5UaukpuBbQ/5d
qf4BXuECgYEAzoOKxMee5tG/G9iC6ImNq5xGAZm0OnmteNgIEQj49If1Q68av525
FioqdC9zV+blfHQqXEIUeum4JAou4xqmB8Lw2H0lYwOJ1IkpUy3QJjU1IrI+U5Qy
ryZuA9cxSTLf1AJFbROsoZDpjaBh0uUQkD/4PHpwXMgHu/3CaJ4nTEkCgYEAzVjE
VWgczWJGyRxmHSeR51ft1jrlChZHEd3HwgLfo854JIj+MGUH4KPLSMIkYNuyiwNQ
W7zdXCB47U8afSL/lPTv1M5+ZsWY6sZAT6gtp/IeU0Va943h9cj10fAOBJaz1H6M
jnZS4jjWhVInE7wpCDVCwDRoHHJ84kb6JeflamMCgYBDQDcKie9HP3q6uLE4xMKr
5gIuNz2n5UQGnGNUGNXp2/SVDArr55MEksqsd19aesi01KeOz74XoNDke6R1NJJo
6KTB+08XhWl3GwuoGL02FBGvsNf3I8W1oBAnlAZqzfRx+CNfuA55ttU318jDgvD3
6L0QBNdef411PNf4dbhacQKBgAd/e0PHFm4lbYJAaDYeUMSKwGN3KQ/SOmwblgSu
iC36BwcGfYmU1tHMCUsx05Q50W4kA9Ylskt/4AqCPexdz8lHnE4/7/uesXO5I3YF
JQ2h2Jufx6+MXbjUyq0Mv+ZI/m3+5PD6vxIFk0ew9T5SO4lSMIrGHxsSzx6QCuhB
bG4TAoGBAJ5PWG7d2CyCjLtfF8J4NxykRvIQ8l/3kDvDdNrXiXbgonojo2lgRYaM
5LoK9ApN8KHdedpTRipBaDA22Sp5SjMcUE7A6q42PJCL9r+BRYF0foFQx/rqpCff
pVWKgwIPoKnfxDqN1RUgyFcx1jbA3XVJZCuT+wbMuDQ9nlvulD1W
-----END RSA PRIVATE KEY-----

View File

@@ -1,74 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
"github.com/hyperhq/hyper-api/types"
)
func TestVolumeCreateError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.VolumeCreate(context.Background(), types.VolumeCreateRequest{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestVolumeCreate(t *testing.T) {
expectedURL := "/volumes/create"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "POST" {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
content, err := json.Marshal(types.Volume{
Name: "volume",
Driver: "local",
Mountpoint: "mountpoint",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
volume, err := client.VolumeCreate(context.Background(), types.VolumeCreateRequest{
Name: "myvolume",
Driver: "mydriver",
DriverOpts: map[string]string{
"opt-key": "opt-value",
},
})
if err != nil {
t.Fatal(err)
}
if volume.Name != "volume" {
t.Fatalf("expected volume.Name to be 'volume', got %s", volume.Name)
}
if volume.Driver != "local" {
t.Fatalf("expected volume.Driver to be 'local', got %s", volume.Driver)
}
if volume.Mountpoint != "mountpoint" {
t.Fatalf("expected volume.Mountpoint to be 'mountpoint', got %s", volume.Mountpoint)
}
}

View File

@@ -1,76 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
)
func TestVolumeInspectError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.VolumeInspect(context.Background(), "nothing")
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestVolumeInspectNotFound(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusNotFound, "Server error")),
}
_, err := client.VolumeInspect(context.Background(), "unknown")
if err == nil || !IsErrVolumeNotFound(err) {
t.Fatalf("expected a volumeNotFound error, got %v", err)
}
}
func TestVolumeInspect(t *testing.T) {
expectedURL := "/volumes/volume_id"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "GET" {
return nil, fmt.Errorf("expected GET method, got %s", req.Method)
}
content, err := json.Marshal(types.Volume{
Name: "name",
Driver: "driver",
Mountpoint: "mountpoint",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
v, err := client.VolumeInspect(context.Background(), "volume_id")
if err != nil {
t.Fatal(err)
}
if v.Name != "name" {
t.Fatalf("expected `name`, got %s", v.Name)
}
if v.Driver != "driver" {
t.Fatalf("expected `driver`, got %s", v.Driver)
}
if v.Mountpoint != "mountpoint" {
t.Fatalf("expected `mountpoint`, got %s", v.Mountpoint)
}
}

View File

@@ -1,97 +0,0 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/filters"
)
func TestVolumeListError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
_, err := client.VolumeList(context.Background(), filters.NewArgs())
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestVolumeList(t *testing.T) {
expectedURL := "/volumes"
noDanglingFilters := filters.NewArgs()
noDanglingFilters.Add("dangling", "false")
danglingFilters := filters.NewArgs()
danglingFilters.Add("dangling", "true")
labelFilters := filters.NewArgs()
labelFilters.Add("label", "label1")
labelFilters.Add("label", "label2")
listCases := []struct {
filters filters.Args
expectedFilters string
}{
{
filters: filters.NewArgs(),
expectedFilters: "",
}, {
filters: noDanglingFilters,
expectedFilters: `{"dangling":{"false":true}}`,
}, {
filters: danglingFilters,
expectedFilters: `{"dangling":{"true":true}}`,
}, {
filters: labelFilters,
expectedFilters: `{"label":{"label1":true,"label2":true}}`,
},
}
for _, listCase := range listCases {
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
actualFilters := query.Get("filters")
if actualFilters != listCase.expectedFilters {
return nil, fmt.Errorf("filters not set in URL query properly. Expected '%s', got %s", listCase.expectedFilters, actualFilters)
}
content, err := json.Marshal(types.VolumesListResponse{
Volumes: []*types.Volume{
{
Name: "volume",
Driver: "local",
},
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
volumeResponse, err := client.VolumeList(context.Background(), listCase.filters)
if err != nil {
t.Fatal(err)
}
if len(volumeResponse.Volumes) != 1 {
t.Fatalf("expected 1 volume, got %v", volumeResponse.Volumes)
}
}
}

View File

@@ -1,47 +0,0 @@
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"context"
)
func TestVolumeRemoveError(t *testing.T) {
client := &Client{
transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.VolumeRemove(context.Background(), "volume_id", false)
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
}
func TestVolumeRemove(t *testing.T) {
expectedURL := "/volumes/volume_id"
client := &Client{
transport: newMockClient(nil, func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
if req.Method != "DELETE" {
return nil, fmt.Errorf("expected DELETE method, got %s", req.Method)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
}, nil
}),
}
err := client.VolumeRemove(context.Background(), "volume_id", false)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,21 +0,0 @@
/*
Package engineapi provides libraries to implement client and server components compatible with the Docker engine.
The client package in github.com/hyperhq/hyper-api/client implements all necessary requests to implement the official Docker engine cli.
Create a new client, then use it to send and receive messages to the Docker engine API:
defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"}
cli, err := client.NewClient("unix:///var/run/docker.sock", "v1.22", nil, defaultHeaders)
Other programs, like Docker Machine, can set the default Docker engine environment for you. There is a shortcut to use its variables to configure the client:
cli, err := client.NewEnvClient()
All request arguments are defined as typed structures in the types package. For instance, this is how to get all containers running in the host:
options := types.ContainerListOptions{All: true}
containers, err := cli.ContainerList(context.Background(), options)
*/
package engineapi

View File

@@ -1,40 +0,0 @@
package events
const (
// ContainerEventType is the event type that containers generate
ContainerEventType = "container"
// ImageEventType is the event type that images generate
ImageEventType = "image"
// VolumeEventType is the event type that volumes generate
VolumeEventType = "volume"
// NetworkEventType is the event type that networks generate
NetworkEventType = "network"
// DaemonEventType is the event type that daemon generate
DaemonEventType = "daemon"
)
// Actor describes something that generates events,
// like a container, or a network, or a volume.
// It has a defined name and a set or attributes.
// The container attributes are its labels, other actors
// can generate these attributes from other properties.
type Actor struct {
ID string
Attributes map[string]string
}
// Message represents the information an event contains
type Message struct {
// Deprecated information from JSONMessage.
// With data only in container events.
Status string `json:"status,omitempty"`
ID string `json:"id,omitempty"`
From string `json:"from,omitempty"`
Type string
Action string
Actor Actor
Time int64 `json:"time,omitempty"`
TimeNano int64 `json:"timeNano,omitempty"`
}

View File

@@ -1,417 +0,0 @@
package filters
import (
"fmt"
"testing"
)
func TestParseArgs(t *testing.T) {
// equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'`
flagArgs := []string{
"created=today",
"image.name=ubuntu*",
"image.name=*untu",
}
var (
args = NewArgs()
err error
)
for i := range flagArgs {
args, err = ParseFlag(flagArgs[i], args)
if err != nil {
t.Errorf("failed to parse %s: %s", flagArgs[i], err)
}
}
if len(args.Get("created")) != 1 {
t.Errorf("failed to set this arg")
}
if len(args.Get("image.name")) != 2 {
t.Errorf("the args should have collapsed")
}
}
func TestParseArgsEdgeCase(t *testing.T) {
var filters Args
args, err := ParseFlag("", filters)
if err != nil {
t.Fatal(err)
}
if args.Len() != 0 {
t.Fatalf("Expected an empty Args (map), got %v", args)
}
if args, err = ParseFlag("anything", args); err == nil || err != ErrBadFormat {
t.Fatalf("Expected ErrBadFormat, got %v", err)
}
}
func TestToParam(t *testing.T) {
fields := map[string]map[string]bool{
"created": {"today": true},
"image.name": {"ubuntu*": true, "*untu": true},
}
a := Args{fields: fields}
_, err := ToParam(a)
if err != nil {
t.Errorf("failed to marshal the filters: %s", err)
}
}
func TestToParamWithVersion(t *testing.T) {
fields := map[string]map[string]bool{
"created": {"today": true},
"image.name": {"ubuntu*": true, "*untu": true},
}
a := Args{fields: fields}
str1, err := ToParamWithVersion("1.21", a)
if err != nil {
t.Errorf("failed to marshal the filters with version < 1.22: %s", err)
}
str2, err := ToParamWithVersion("1.22", a)
if err != nil {
t.Errorf("failed to marshal the filters with version >= 1.22: %s", err)
}
if str1 != `{"created":["today"],"image.name":["*untu","ubuntu*"]}` &&
str1 != `{"created":["today"],"image.name":["ubuntu*","*untu"]}` {
t.Errorf("incorrectly marshaled the filters: %s", str1)
}
if str2 != `{"created":{"today":true},"image.name":{"*untu":true,"ubuntu*":true}}` &&
str2 != `{"created":{"today":true},"image.name":{"ubuntu*":true,"*untu":true}}` {
t.Errorf("incorrectly marshaled the filters: %s", str2)
}
}
func TestFromParam(t *testing.T) {
invalids := []string{
"anything",
"['a','list']",
"{'key': 'value'}",
`{"key": "value"}`,
}
valid := map[*Args][]string{
{fields: map[string]map[string]bool{"key": {"value": true}}}: {
`{"key": ["value"]}`,
`{"key": {"value": true}}`,
},
{fields: map[string]map[string]bool{"key": {"value1": true, "value2": true}}}: {
`{"key": ["value1", "value2"]}`,
`{"key": {"value1": true, "value2": true}}`,
},
{fields: map[string]map[string]bool{"key1": {"value1": true}, "key2": {"value2": true}}}: {
`{"key1": ["value1"], "key2": ["value2"]}`,
`{"key1": {"value1": true}, "key2": {"value2": true}}`,
},
}
for _, invalid := range invalids {
if _, err := FromParam(invalid); err == nil {
t.Fatalf("Expected an error with %v, got nothing", invalid)
}
}
for expectedArgs, matchers := range valid {
for _, json := range matchers {
args, err := FromParam(json)
if err != nil {
t.Fatal(err)
}
if args.Len() != expectedArgs.Len() {
t.Fatalf("Expected %v, go %v", expectedArgs, args)
}
for key, expectedValues := range expectedArgs.fields {
values := args.Get(key)
if len(values) != len(expectedValues) {
t.Fatalf("Expected %v, go %v", expectedArgs, args)
}
for _, v := range values {
if !expectedValues[v] {
t.Fatalf("Expected %v, go %v", expectedArgs, args)
}
}
}
}
}
}
func TestEmpty(t *testing.T) {
a := Args{}
v, err := ToParam(a)
if err != nil {
t.Errorf("failed to marshal the filters: %s", err)
}
v1, err := FromParam(v)
if err != nil {
t.Errorf("%s", err)
}
if a.Len() != v1.Len() {
t.Errorf("these should both be empty sets")
}
}
func TestArgsMatchKVListEmptySources(t *testing.T) {
args := NewArgs()
if !args.MatchKVList("created", map[string]string{}) {
t.Fatalf("Expected true for (%v,created), got true", args)
}
args = Args{map[string]map[string]bool{"created": {"today": true}}}
if args.MatchKVList("created", map[string]string{}) {
t.Fatalf("Expected false for (%v,created), got true", args)
}
}
func TestArgsMatchKVList(t *testing.T) {
// Not empty sources
sources := map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}
matches := map[*Args]string{
{}: "field",
{map[string]map[string]bool{
"created": {"today": true},
"labels": {"key1": true}},
}: "labels",
{map[string]map[string]bool{
"created": {"today": true},
"labels": {"key1=value1": true}},
}: "labels",
}
for args, field := range matches {
if args.MatchKVList(field, sources) != true {
t.Fatalf("Expected true for %v on %v, got false", sources, args)
}
}
differs := map[*Args]string{
{map[string]map[string]bool{
"created": {"today": true}},
}: "created",
{map[string]map[string]bool{
"created": {"today": true},
"labels": {"key4": true}},
}: "labels",
{map[string]map[string]bool{
"created": {"today": true},
"labels": {"key1=value3": true}},
}: "labels",
}
for args, field := range differs {
if args.MatchKVList(field, sources) != false {
t.Fatalf("Expected false for %v on %v, got true", sources, args)
}
}
}
func TestArgsMatch(t *testing.T) {
source := "today"
matches := map[*Args]string{
{}: "field",
{map[string]map[string]bool{
"created": {"today": true}},
}: "today",
{map[string]map[string]bool{
"created": {"to*": true}},
}: "created",
{map[string]map[string]bool{
"created": {"to(.*)": true}},
}: "created",
{map[string]map[string]bool{
"created": {"tod": true}},
}: "created",
{map[string]map[string]bool{
"created": {"anyting": true, "to*": true}},
}: "created",
}
for args, field := range matches {
if args.Match(field, source) != true {
t.Fatalf("Expected true for %v on %v, got false", source, args)
}
}
differs := map[*Args]string{
{map[string]map[string]bool{
"created": {"tomorrow": true}},
}: "created",
{map[string]map[string]bool{
"created": {"to(day": true}},
}: "created",
{map[string]map[string]bool{
"created": {"tom(.*)": true}},
}: "created",
{map[string]map[string]bool{
"created": {"tom": true}},
}: "created",
{map[string]map[string]bool{
"created": {"today1": true},
"labels": {"today": true}},
}: "created",
}
for args, field := range differs {
if args.Match(field, source) != false {
t.Fatalf("Expected false for %v on %v, got true", source, args)
}
}
}
func TestAdd(t *testing.T) {
f := NewArgs()
f.Add("status", "running")
v := f.fields["status"]
if len(v) != 1 || !v["running"] {
t.Fatalf("Expected to include a running status, got %v", v)
}
f.Add("status", "paused")
if len(v) != 2 || !v["paused"] {
t.Fatalf("Expected to include a paused status, got %v", v)
}
}
func TestDel(t *testing.T) {
f := NewArgs()
f.Add("status", "running")
f.Del("status", "running")
v := f.fields["status"]
if v["running"] {
t.Fatalf("Expected to not include a running status filter, got true")
}
}
func TestLen(t *testing.T) {
f := NewArgs()
if f.Len() != 0 {
t.Fatalf("Expected to not include any field")
}
f.Add("status", "running")
if f.Len() != 1 {
t.Fatalf("Expected to include one field")
}
}
func TestExactMatch(t *testing.T) {
f := NewArgs()
if !f.ExactMatch("status", "running") {
t.Fatalf("Expected to match `running` when there are no filters, got false")
}
f.Add("status", "running")
f.Add("status", "pause*")
if !f.ExactMatch("status", "running") {
t.Fatalf("Expected to match `running` with one of the filters, got false")
}
if f.ExactMatch("status", "paused") {
t.Fatalf("Expected to not match `paused` with one of the filters, got true")
}
}
func TestOnlyOneExactMatch(t *testing.T) {
f := NewArgs()
if !f.UniqueExactMatch("status", "running") {
t.Fatalf("Expected to match `running` when there are no filters, got false")
}
f.Add("status", "running")
if !f.UniqueExactMatch("status", "running") {
t.Fatalf("Expected to match `running` with one of the filters, got false")
}
if f.UniqueExactMatch("status", "paused") {
t.Fatalf("Expected to not match `paused` with one of the filters, got true")
}
f.Add("status", "pause")
if f.UniqueExactMatch("status", "running") {
t.Fatalf("Expected to not match only `running` with two filters, got true")
}
}
func TestInclude(t *testing.T) {
f := NewArgs()
if f.Include("status") {
t.Fatalf("Expected to not include a status key, got true")
}
f.Add("status", "running")
if !f.Include("status") {
t.Fatalf("Expected to include a status key, got false")
}
}
func TestValidate(t *testing.T) {
f := NewArgs()
f.Add("status", "running")
valid := map[string]bool{
"status": true,
"dangling": true,
}
if err := f.Validate(valid); err != nil {
t.Fatal(err)
}
f.Add("bogus", "running")
if err := f.Validate(valid); err == nil {
t.Fatalf("Expected to return an error, got nil")
}
}
func TestWalkValues(t *testing.T) {
f := NewArgs()
f.Add("status", "running")
f.Add("status", "paused")
f.WalkValues("status", func(value string) error {
if value != "running" && value != "paused" {
t.Fatalf("Unexpected value %s", value)
}
return nil
})
err := f.WalkValues("status", func(value string) error {
return fmt.Errorf("return")
})
if err == nil {
t.Fatalf("Expected to get an error, got nil")
}
err = f.WalkValues("foo", func(value string) error {
return fmt.Errorf("return")
})
if err != nil {
t.Fatalf("Expected to not iterate when the field doesn't exist, got %v", err)
}
}
func TestFuzzyMatch(t *testing.T) {
f := NewArgs()
f.Add("container", "foo")
cases := map[string]bool{
"foo": true,
"foobar": true,
"barfoo": false,
"bar": false,
}
for source, match := range cases {
got := f.FuzzyMatch("container", source)
if got != match {
t.Fatalf("Expected %v, got %v: %s", match, got, source)
}
}
}

View File

@@ -1,58 +0,0 @@
package mount
// Type represents the type of a mount.
type Type string
const (
// TypeBind BIND
TypeBind Type = "bind"
// TypeVolume VOLUME
TypeVolume Type = "volume"
)
// Mount represents a mount (volume).
type Mount struct {
Type Type `json:",omitempty"`
Source string `json:",omitempty"`
Target string `json:",omitempty"`
ReadOnly bool `json:",omitempty"`
BindOptions *BindOptions `json:",omitempty"`
VolumeOptions *VolumeOptions `json:",omitempty"`
}
// Propagation represents the propagation of a mount.
type Propagation string
const (
// PropagationRPrivate RPRIVATE
PropagationRPrivate Propagation = "rprivate"
// PropagationPrivate PRIVATE
PropagationPrivate Propagation = "private"
// PropagationRShared RSHARED
PropagationRShared Propagation = "rshared"
// PropagationShared SHARED
PropagationShared Propagation = "shared"
// PropagationRSlave RSLAVE
PropagationRSlave Propagation = "rslave"
// PropagationSlave SLAVE
PropagationSlave Propagation = "slave"
)
// BindOptions defines options specific to mounts of type "bind".
type BindOptions struct {
Propagation Propagation `json:",omitempty"`
}
// VolumeOptions represents the options for a mount of type volume.
type VolumeOptions struct {
NoCopy bool `json:",omitempty"`
Labels map[string]string `json:",omitempty"`
DriverConfig *Driver `json:",omitempty"`
}
// Driver represents a volume driver.
type Driver struct {
Name string `json:",omitempty"`
Options map[string]string `json:",omitempty"`
}

View File

@@ -1,72 +0,0 @@
package reference
import (
"testing"
)
func TestParse(t *testing.T) {
testCases := []struct {
ref string
expectedName string
expectedTag string
expectedError bool
}{
{
ref: "",
expectedName: "",
expectedTag: "",
expectedError: true,
},
{
ref: "repository",
expectedName: "repository",
expectedTag: "latest",
expectedError: false,
},
{
ref: "repository:tag",
expectedName: "repository",
expectedTag: "tag",
expectedError: false,
},
{
ref: "test.com/repository",
expectedName: "test.com/repository",
expectedTag: "latest",
expectedError: false,
},
{
ref: "test.com:5000/test/repository",
expectedName: "test.com:5000/test/repository",
expectedTag: "latest",
expectedError: false,
},
{
ref: "test.com:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
expectedName: "test.com:5000/repo",
expectedTag: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
expectedError: false,
},
{
ref: "test.com:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
expectedName: "test.com:5000/repo",
expectedTag: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
expectedError: false,
},
}
for _, c := range testCases {
name, tag, err := Parse(c.ref)
if err != nil && c.expectedError {
continue
} else if err != nil {
t.Fatalf("error with %s: %s", c.ref, err.Error())
}
if name != c.expectedName {
t.Fatalf("expected name %s, got %s", c.expectedName, name)
}
if tag != c.expectedTag {
t.Fatalf("expected tag %s, got %s", c.expectedTag, tag)
}
}
}

View File

@@ -1,86 +0,0 @@
package strslice
import (
"encoding/json"
"reflect"
"testing"
)
func TestStrSliceMarshalJSON(t *testing.T) {
for _, testcase := range []struct {
input StrSlice
expected string
}{
// MADNESS(stevvooe): No clue why nil would be "" but empty would be
// "null". Had to make a change here that may affect compatibility.
{input: nil, expected: "null"},
{StrSlice{}, "[]"},
{StrSlice{"/bin/sh", "-c", "echo"}, `["/bin/sh","-c","echo"]`},
} {
data, err := json.Marshal(testcase.input)
if err != nil {
t.Fatal(err)
}
if string(data) != testcase.expected {
t.Fatalf("%#v: expected %v, got %v", testcase.input, testcase.expected, string(data))
}
}
}
func TestStrSliceUnmarshalJSON(t *testing.T) {
parts := map[string][]string{
"": {"default", "values"},
"[]": {},
`["/bin/sh","-c","echo"]`: {"/bin/sh", "-c", "echo"},
}
for json, expectedParts := range parts {
strs := StrSlice{"default", "values"}
if err := strs.UnmarshalJSON([]byte(json)); err != nil {
t.Fatal(err)
}
actualParts := []string(strs)
if !reflect.DeepEqual(actualParts, expectedParts) {
t.Fatalf("%#v: expected %v, got %v", json, expectedParts, actualParts)
}
}
}
func TestStrSliceUnmarshalString(t *testing.T) {
var e StrSlice
echo, err := json.Marshal("echo")
if err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(echo, &e); err != nil {
t.Fatal(err)
}
if len(e) != 1 {
t.Fatalf("expected 1 element after unmarshal: %q", e)
}
if e[0] != "echo" {
t.Fatalf("expected `echo`, got: %q", e[0])
}
}
func TestStrSliceUnmarshalSlice(t *testing.T) {
var e StrSlice
echo, err := json.Marshal([]string{"echo"})
if err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(echo, &e); err != nil {
t.Fatal(err)
}
if len(e) != 1 {
t.Fatalf("expected 1 element after unmarshal: %q", e)
}
if e[0] != "echo" {
t.Fatalf("expected `echo`, got: %q", e[0])
}
}

View File

@@ -1,26 +0,0 @@
package time
import (
"testing"
"time"
)
func TestDurationToSecondsString(t *testing.T) {
cases := []struct {
in time.Duration
expected string
}{
{0 * time.Second, "0"},
{1 * time.Second, "1"},
{1 * time.Minute, "60"},
{24 * time.Hour, "86400"},
}
for _, c := range cases {
s := DurationToSecondsString(c.in)
if s != c.expected {
t.Errorf("wrong value for input `%v`: expected `%s`, got `%s`", c.in, c.expected, s)
t.Fail()
}
}
}

View File

@@ -1,93 +0,0 @@
package time
import (
"fmt"
"testing"
"time"
)
func TestGetTimestamp(t *testing.T) {
now := time.Now().In(time.UTC)
cases := []struct {
in, expected string
expectedErr bool
}{
// Partial RFC3339 strings get parsed with second precision
{"2006-01-02T15:04:05.999999999+07:00", "1136189045.999999999", false},
{"2006-01-02T15:04:05.999999999Z", "1136214245.999999999", false},
{"2006-01-02T15:04:05.999999999", "1136214245.999999999", false},
{"2006-01-02T15:04:05Z", "1136214245.000000000", false},
{"2006-01-02T15:04:05", "1136214245.000000000", false},
{"2006-01-02T15:04:0Z", "", true},
{"2006-01-02T15:04:0", "", true},
{"2006-01-02T15:04Z", "1136214240.000000000", false},
{"2006-01-02T15:04+00:00", "1136214240.000000000", false},
{"2006-01-02T15:04-00:00", "1136214240.000000000", false},
{"2006-01-02T15:04", "1136214240.000000000", false},
{"2006-01-02T15:0Z", "", true},
{"2006-01-02T15:0", "", true},
{"2006-01-02T15Z", "1136214000.000000000", false},
{"2006-01-02T15+00:00", "1136214000.000000000", false},
{"2006-01-02T15-00:00", "1136214000.000000000", false},
{"2006-01-02T15", "1136214000.000000000", false},
{"2006-01-02T1Z", "1136163600.000000000", false},
{"2006-01-02T1", "1136163600.000000000", false},
{"2006-01-02TZ", "", true},
{"2006-01-02T", "", true},
{"2006-01-02+00:00", "1136160000.000000000", false},
{"2006-01-02-00:00", "1136160000.000000000", false},
{"2006-01-02-00:01", "1136160060.000000000", false},
{"2006-01-02Z", "1136160000.000000000", false},
{"2006-01-02", "1136160000.000000000", false},
{"2015-05-13T20:39:09Z", "1431549549.000000000", false},
// unix timestamps returned as is
{"1136073600", "1136073600", false},
{"1136073600.000000001", "1136073600.000000001", false},
// Durations
{"1m", fmt.Sprintf("%d", now.Add(-1*time.Minute).Unix()), false},
{"1.5h", fmt.Sprintf("%d", now.Add(-90*time.Minute).Unix()), false},
{"1h30m", fmt.Sprintf("%d", now.Add(-90*time.Minute).Unix()), false},
// String fallback
{"invalid", "invalid", false},
}
for _, c := range cases {
o, err := GetTimestamp(c.in, now)
if o != c.expected ||
(err == nil && c.expectedErr) ||
(err != nil && !c.expectedErr) {
t.Errorf("wrong value for '%s'. expected:'%s' got:'%s' with error: `%s`", c.in, c.expected, o, err)
t.Fail()
}
}
}
func TestParseTimestamps(t *testing.T) {
cases := []struct {
in string
def, expectedS, expectedN int64
expectedErr bool
}{
// unix timestamps
{"1136073600", 0, 1136073600, 0, false},
{"1136073600.000000001", 0, 1136073600, 1, false},
{"1136073600.0000000010", 0, 1136073600, 1, false},
{"1136073600.00000001", 0, 1136073600, 10, false},
{"foo.bar", 0, 0, 0, true},
{"1136073600.bar", 0, 1136073600, 0, true},
{"", -1, -1, 0, false},
}
for _, c := range cases {
s, n, err := ParseTimestamps(c.in, c.def)
if s != c.expectedS ||
n != c.expectedN ||
(err == nil && c.expectedErr) ||
(err != nil && !c.expectedErr) {
t.Errorf("wrong values for input `%s` with default `%d` expected:'%d'seconds and `%d`nanosecond got:'%d'seconds and `%d`nanoseconds with error: `%s`", c.in, c.def, c.expectedS, c.expectedN, s, n, err)
t.Fail()
}
}
}

View File

@@ -1,14 +0,0 @@
## Legacy API type versions
This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`.
Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`.
### Package name conventions
The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention:
1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`.
2. We cannot use `_` because golint complains abount it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`.
For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`.

View File

@@ -1,26 +0,0 @@
package versions
import (
"testing"
)
func assertVersion(t *testing.T, a, b string, result int) {
if r := compare(a, b); r != result {
t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result)
}
}
func TestCompareVersion(t *testing.T) {
assertVersion(t, "1.12", "1.12", 0)
assertVersion(t, "1.0.0", "1", 0)
assertVersion(t, "1", "1.0.0", 0)
assertVersion(t, "1.05.00.0156", "1.0.221.9289", 1)
assertVersion(t, "1", "1.0.1", -1)
assertVersion(t, "1.0.1", "1", 1)
assertVersion(t, "1.0.1", "1.0.2", -1)
assertVersion(t, "1.0.2", "1.0.3", -1)
assertVersion(t, "1.0.3", "1.1", -1)
assertVersion(t, "1.1", "1.1.1", -1)
assertVersion(t, "1.1.1", "1.1.2", -1)
assertVersion(t, "1.1.2", "1.2", -1)
}

View File

@@ -1,35 +0,0 @@
// Package v1p19 provides specific API types for the API version 1, patch 19.
package v1p19
import (
"github.com/docker/go-connections/nat"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/container"
"github.com/hyperhq/hyper-api/types/versions/v1p20"
)
// ContainerJSON is a backcompatibility struct for APIs prior to 1.20.
// Note this is not used by the Windows daemon.
type ContainerJSON struct {
*types.ContainerJSONBase
Volumes map[string]string
VolumesRW map[string]bool
Config *ContainerConfig
NetworkSettings *v1p20.NetworkSettings
}
// ContainerConfig is a backcompatibility struct for APIs prior to 1.20.
type ContainerConfig struct {
*container.Config
MacAddress string
NetworkDisabled bool
ExposedPorts map[nat.Port]struct{}
// backward compatibility, they now live in HostConfig
VolumeDriver string
Memory int64
MemorySwap int64
CPUShares int64 `json:"CpuShares"`
CPUSet string `json:"Cpuset"`
}

View File

@@ -1,40 +0,0 @@
// Package v1p20 provides specific API types for the API version 1, patch 20.
package v1p20
import (
"github.com/docker/go-connections/nat"
"github.com/hyperhq/hyper-api/types"
"github.com/hyperhq/hyper-api/types/container"
)
// ContainerJSON is a backcompatibility struct for the API 1.20
type ContainerJSON struct {
*types.ContainerJSONBase
Mounts []types.MountPoint
Config *ContainerConfig
NetworkSettings *NetworkSettings
}
// ContainerConfig is a backcompatibility struct used in ContainerJSON for the API 1.20
type ContainerConfig struct {
*container.Config
MacAddress string
NetworkDisabled bool
ExposedPorts map[nat.Port]struct{}
// backward compatibility, they now live in HostConfig
VolumeDriver string
}
// StatsJSON is a backcompatibility struct used in Stats for APIs prior to 1.21
type StatsJSON struct {
types.Stats
Network types.NetworkStats `json:"network,omitempty"`
}
// NetworkSettings is a backward compatible struct for APIs prior to 1.21
type NetworkSettings struct {
types.NetworkSettingsBase
types.DefaultNetworkSettings
}