Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of remaining containerz tests. #3477

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ Now export the container to a tarball.

```shell
$ docker save -o /tmp/cntrsrv.tar cntrsrv:latest
$ docker tag cntrsrv:latest cntrsrv:upgrade
$ docker save -o /tmp/cntrsrv-upgrade.tar cntrsrv:upgrade
$ docker rmi cntrsrv:latest
```

Expand Down Expand Up @@ -98,6 +100,16 @@ Using the container started as part of CNTR-1.2, validate that the container can
be stopped, and is subsequently no longer listed in the `gnoi.Containerz.List`
API.

## CNTR-1.5: Create a volume on the DUT.

Validate the the DUT is capable of creating a volume, reading it back
and removing it.

## CNTR-1.6: Upgrade a container on the DUT.

Using the same container started as part of CNTR-1.1, validate that the container
can upgraded.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
can upgraded.
can be upgraded.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding something that defines what "upgraded" means?


## OpenConfig Path and RPC Coverage

The below yaml defines the RPCs intended to be covered by this test.
Expand All @@ -110,4 +122,8 @@ rpcs:
containerz.Containerz.StopContainer:
containerz.Containerz.Log:
containerz.Containerz.ListContainer:
containerz.Containerz.CreateVolume:
containerz.Containerz.RemoveVolume:
containerz.Containerz.ListVolume:
containerz.Containerz.UpgradeContainer:
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,42 @@ import (
"context"
"crypto/tls"
"flag"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/openconfig/containerz/client"
cpb "github.com/openconfig/featureprofiles/internal/cntrsrv/proto/cntr"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"testing"
"time"
)

var (
containerTar = flag.String("container_tar", "/tmp/cntrsrv.tar", "The container tarball to deploy.")
containerzAddr = flag.String("containerz_addr", "localhost:19999", "containerz server address")
containerTar = flag.String("container_tar", "/tmp/cntrsrv.tar", "The container tarball to deploy.")
containerUpgradeTar = flag.String("container_upgrade_tar", "/tmp/cntrsrv-upgrade.tar", "The container tarball to upgrade to.")
containerzAddr = flag.String("containerz_addr", "localhost:19999", "containerz server address")
)

// TestDeployAndStartContainer implements CNTR-1.1 validating that it is
// possible deploy and start a container via containerz.
func TestDeployAndStartContainer(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
const (
instanceName = "test-instance"
)

func containerzClient(ctx context.Context, t *testing.T) *client.Client {
client.Dial = func(ctx context.Context, target string, opts ...grpc.DialOption) (conn *grpc.ClientConn, err error) {
return grpc.DialContext(ctx, target, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
cli, err := client.NewClient(ctx, *containerzAddr)
if err != nil {
t.Fatalf("unable to dial containerz: %v", err)
}

return cli
}

func startContainer(ctx context.Context, t *testing.T) *client.Client {
cli := containerzClient(ctx, t)

progCh, err := cli.PushImage(ctx, "cntrsrv", "latest", *containerTar)
if err != nil {
t.Fatalf("unable to push image: %v", err)
Expand All @@ -45,18 +56,35 @@ func TestDeployAndStartContainer(t *testing.T) {
}
}

ret, err := cli.StartContainer(ctx, "cntrsrv", "latest", "./cntrsrv", "test-instance", client.WithPorts([]string{"60061:60061"}))
ret, err := cli.StartContainer(ctx, "cntrsrv", "latest", "./cntrsrv", instanceName, client.WithPorts([]string{"60061:60061"}))
if err != nil {
t.Fatalf("unable to start container: %v", err)
}

// wait for cntr container to come up.
time.Sleep(5 * time.Second)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume there's nothing fancier we can do to determine whether this container is alive? Is this the one that implements ping such that the service can be checked -- or should we consider this a wider integration test?

t.Logf("Started %s", ret)

return cli
}

func stopContainer(ctx context.Context, t *testing.T, cli *client.Client) {
if err := cli.StopContainer(ctx, instanceName, true); err != nil {
t.Logf("container already stopping: %v", err)
}
}

// TestDeployAndStartContainer implements CNTR-1.1 validating that it is
// possible deploy and start a container via containerz.
func TestDeployAndStartContainer(t *testing.T) {
ctx := context.Background()
cli := startContainer(ctx, t)
defer stopContainer(ctx, t, cli)

tlsc := credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true, // NOLINT
})
conntectionState := connectivity.Ready
conn, err := grpc.NewClient("localhost:60061", grpc.WithTransportCredentials(tlsc))
conn.WaitForStateChange(ctx, conntectionState)
if err != nil {
t.Fatalf("Failed to dial cntrsrv, %v", err)
}
Expand All @@ -65,5 +93,155 @@ func TestDeployAndStartContainer(t *testing.T) {
if _, err = cntrCli.Ping(ctx, &cpb.PingRequest{}); err != nil {
t.Errorf("unable to reach cntrsrv: %v", err)
}
}

// TestRetrieveLogs implements CNTR-1.2 validating that logs can be retrieved from a
// running container.
func TestRetrieveLogs(t *testing.T) {
ctx := context.Background()
cli := startContainer(ctx, t)
defer stopContainer(ctx, t, cli)

logCh, err := cli.Logs(ctx, instanceName, false)
if err != nil {
t.Errorf("unable to obtain logs for %s: %v", instanceName, err)
}

var logs []string
for msg := range logCh {
logs = append(logs, msg.Msg)
if msg.Error != nil {
t.Errorf("logs returned an error: %v", err)
}
}

if len(logs) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume that the container here is specified to create some logs so there's no chance that this is a flake?

t.Errorf("no logs were returned")
}
}

// TestListContainers implements CNTR-1.3 validating listing running containers.
func TestListContainers(t *testing.T) {
ctx := context.Background()
cli := startContainer(ctx, t)
defer stopContainer(ctx, t, cli)

listCh, err := cli.ListContainer(ctx, true, 0, nil)
if err != nil {
t.Errorf("unable to list containers: %v", err)
}

wantCntrs := []string{"cntrsrv:latest"}
var gotCntrs []string

for cnt := range listCh {
gotCntrs = append(gotCntrs, cnt.ImageName)
}

if diff := cmp.Diff(wantCntrs, gotCntrs, cmpopts.SortSlices(func(l, r string) bool { return l < r })); diff != "" {
t.Errorf("ListContainer() returned diff (-want, +got):\n%s", diff)
}
}

// TestStopContainer implements CNTR-1.4 validating that stopping a container works as expected.
func TestStopContainer(t *testing.T) {
ctx := context.Background()
cli := startContainer(ctx, t)
stopContainer(ctx, t, cli)

// wait for container to stop
time.Sleep(2 * time.Second)

listCh, err := cli.ListContainer(ctx, true, 0, nil)
if err != nil {
t.Errorf("unable to list containers: %v", err)
}

for cntr := range listCh {
t.Errorf("StopContainer did not stop the container: %v", cntr)
}
}

func TestVolumes(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here? I think it'd be worth just noting that the test here ensures that a volume can be created and removed from an API perspective -- it doesn't check that it's possible to actually use that volume.

ctx := context.Background()
cli := containerzClient(ctx, t)

wantVolume := "my-vol"
gotVolume, err := cli.CreateVolume(ctx, "my-vol", "local", nil, nil)
if err != nil {
t.Errorf("unable to create volume: %v", err)
}
defer cli.RemoveVolume(ctx, "my-vol", true)

if wantVolume != gotVolume {
t.Errorf("incorrect volume name: want %s, got %s", wantVolume, gotVolume)
}

t.Logf("created volume %s", gotVolume)

volCh, err := cli.ListVolume(ctx, nil)
if err != nil {
t.Errorf("unable to list volumes: %v", err)
}

wantVolumes := []*client.VolumeInfo{
{
Name: "my-vol",
Driver: "local",
Options: map[string]string{"device": "", "o": "", "type": "none"},
},
}
var gotVolumes []*client.VolumeInfo
for vol := range volCh {
gotVolumes = append(gotVolumes, vol)
}

if diff := cmp.Diff(wantVolumes, gotVolumes, cmpopts.IgnoreFields(client.VolumeInfo{}, "CreationTime")); diff != "" {
t.Errorf("Volumes returned diff (-want, +got):\n%s", diff)
}
}

func TestUpgrade(t *testing.T) {
ctx := context.Background()
cli := startContainer(ctx, t)
defer stopContainer(ctx, t, cli)

progCh, err := cli.PushImage(ctx, "cntrsrv", "upgrade", *containerUpgradeTar)
if err != nil {
t.Fatalf("unable to push image: %v", err)
}

for prog := range progCh {
switch {
case prog.Error != nil:
t.Fatalf("failed to push image: %v", err)
case prog.Finished:
t.Logf("Pushed %s/%s\n", prog.Image, prog.Tag)
default:
t.Logf(" %d bytes pushed", prog.BytesReceived)
}
}

_, err = cli.UpdateContainer(ctx, "cntrsrv", "upgrade", "./cntrsrv", instanceName, false, client.WithPorts([]string{"60061:60061"}))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_, err = cli.UpdateContainer(ctx, "cntrsrv", "upgrade", "./cntrsrv", instanceName, false, client.WithPorts([]string{"60061:60061"}))
if _, err = cli.UpdateContainer(ctx, "cntrsrv", "upgrade", "./cntrsrv", instanceName, false, client.WithPorts([]string{"60061:60061"})); err != nil { ... }

if err != nil {
t.Errorf("unable to upgrade container: %v", err)
}

time.Sleep(3 * time.Second)

listCh, err := cli.ListContainer(ctx, true, 0, nil)
if err != nil {
t.Errorf("unable to list containers: %v", err)
}

wantCntrs := []string{"cntrsrv:upgrade"}
var gotCntrs []string

for cnt := range listCh {
gotCntrs = append(gotCntrs, cnt.ImageName)
}

if diff := cmp.Diff(wantCntrs, gotCntrs, cmpopts.SortSlices(func(l, r string) bool { return l < r })); diff != "" {
t.Errorf("ListContainer() returned diff (-want, +got):\n%s", diff)
}
}
38 changes: 20 additions & 18 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ require (
github.com/cisco-open/go-p4 v0.1.2
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.11.0
github.com/golang/glog v1.2.1
github.com/golang/glog v1.2.2
github.com/google/go-cmp v0.6.0
github.com/google/go-github/v50 v50.1.0
github.com/google/gopacket v1.1.19
github.com/google/uuid v1.6.0
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/kr/pretty v0.3.1
github.com/open-traffic-generator/snappi/gosnappi v1.3.0
github.com/openconfig/containerz v0.0.0-20240620162940-e0bf23af17d6
github.com/open-traffic-generator/snappi/gosnappi v1.13.0
github.com/openconfig/containerz v0.0.0-20240926173756-5ea817752106
github.com/openconfig/entity-naming v0.0.0-20230912181021-7ac806551a31
github.com/openconfig/gnmi v0.11.0
github.com/openconfig/gnoi v0.4.1
github.com/openconfig/gnoi v0.5.0
github.com/openconfig/gnoigo v0.0.0-20240320202954-ebd033e3542c
github.com/openconfig/gnsi v1.6.0
github.com/openconfig/gocloser v0.0.0-20220310182203-c6c950ed3b0b
Expand All @@ -45,24 +45,24 @@ require (
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8
golang.org/x/text v0.18.0
google.golang.org/api v0.171.0
google.golang.org/grpc v1.66.2
google.golang.org/grpc v1.67.0
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/klog/v2 v2.120.1
)

require (
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
golang.org/x/oauth2 v0.21.0
golang.org/x/oauth2 v0.22.0
)

require (
bitbucket.org/creachadair/stringset v0.0.14 // indirect
cel.dev/expr v0.15.0 // indirect
cel.dev/expr v0.16.0 // indirect
cloud.google.com/go v0.112.1 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
cloud.google.com/go/iam v1.1.6 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
Expand All @@ -72,21 +72,21 @@ require (
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect
github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 // indirect
github.com/creack/pty v1.1.18 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/drivenets/cdnos-controller v1.7.4 // indirect
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 // indirect
github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
github.com/envoyproxy/go-control-plane v0.13.0 // indirect
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
Expand All @@ -100,6 +100,7 @@ require (
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand Down Expand Up @@ -146,10 +147,10 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.18.0 // indirect
Expand All @@ -160,8 +161,9 @@ require (
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.22.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
Expand Down
Loading
Loading