Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
Remove image lookups from acorn ps (#1888)
Browse files Browse the repository at this point in the history
Signed-off-by: Grant Linville <[email protected]>
  • Loading branch information
g-linville authored Jul 8, 2023
1 parent 9e0c9f7 commit 95c1a6e
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 180 deletions.
34 changes: 3 additions & 31 deletions pkg/cli/apps.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
package cli

import (
"context"
"strings"

apiv1 "github.com/acorn-io/runtime/pkg/apis/api.acorn.io/v1"
cli "github.com/acorn-io/runtime/pkg/cli/builder"
"github.com/acorn-io/runtime/pkg/cli/builder/table"
"github.com/acorn-io/runtime/pkg/client"
"github.com/acorn-io/runtime/pkg/tables"
"github.com/spf13/cobra"
"k8s.io/utils/strings/slices"
Expand Down Expand Up @@ -45,7 +40,7 @@ func (a *App) Run(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
writeApp(cmd.Context(), app, out, c)
out.Write(app)
return out.Err()
}

Expand All @@ -60,35 +55,12 @@ func (a *App) Run(cmd *cobra.Command, args []string) error {
}
if len(args) > 0 {
if slices.Contains(args, app.Name) {
writeApp(cmd.Context(), &app, out, c)
out.Write(&app)
}
} else {
writeApp(cmd.Context(), &app, out, c)
out.Write(&app)
}
}

return out.Err()
}

func writeApp(ctx context.Context, app *apiv1.App, out table.Writer, c client.Client) {
image, err := c.ImageGet(ctx, strings.TrimPrefix(app.Status.AppImage.Digest, "sha256:"))
if err != nil {
// Give up and write the app with its digest as its name
app.Status.AppImage.Name = strings.TrimPrefix(app.Status.AppImage.Digest, "sha256:")
out.Write(app)
return
}

var tagIsValid bool
for _, tag := range image.Tags {
if tag == app.Status.AppImage.Name || (strings.Contains(tag, "docker.io") && strings.HasSuffix(tag, app.Status.AppImage.Name)) {
tagIsValid = true
break
}
}
if !tagIsValid {
app.Status.AppImage.Name = strings.TrimPrefix(app.Status.AppImage.Digest, "sha256:")
}

out.Write(app)
}
147 changes: 2 additions & 145 deletions pkg/cli/apps_test.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
package cli

import (
"context"
"fmt"
"io"
"os"
"strings"
"testing"
"time"

v1 "github.com/acorn-io/runtime/pkg/apis/api.acorn.io/v1"
internalv1 "github.com/acorn-io/runtime/pkg/apis/internal.acorn.io/v1"
"github.com/acorn-io/runtime/pkg/cli/builder/table"
"github.com/acorn-io/runtime/pkg/cli/testdata"
"github.com/acorn-io/runtime/pkg/mocks"
"github.com/acorn-io/runtime/pkg/tables"
"github.com/golang/mock/gomock"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestApp(t *testing.T) {
Expand Down Expand Up @@ -58,7 +48,7 @@ func TestApp(t *testing.T) {
client: &testdata.MockClient{},
},
wantErr: false,
wantOut: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nfound 292y ago \n",
wantOut: "NAME IMAGE DIGEST HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nfound 292y ago \n",
},
{
name: "acorn app found", fields: fields{
Expand All @@ -77,7 +67,7 @@ func TestApp(t *testing.T) {
client: &testdata.MockClient{},
},
wantErr: false,
wantOut: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nfound 292y ago \n",
wantOut: "NAME IMAGE DIGEST HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nfound 292y ago \n",
},
{
name: "acorn app dne", fields: fields{
Expand Down Expand Up @@ -118,136 +108,3 @@ func TestApp(t *testing.T) {
})
}
}

func TestWriteApp(t *testing.T) {
ctrl := gomock.NewController(t)
c := mocks.NewMockClient(ctrl)
registerMockCalls(t, c)

cases := []struct {
name string
appImageName string
appImageDigest string
expected string
}{
{
name: "basic",
appImageName: "myimage:latest",
appImageDigest: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
expected: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nmyapp myimage:latest 60m ago \n",
},
{
name: "docker.io => index.docker.io",
appImageName: "docker.io/myimage:latest",
appImageDigest: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
expected: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nmyapp docker.io/myimage:latest 60m ago \n",
},
{
name: "implicit docker.io",
appImageName: "myotherimage:latest",
appImageDigest: "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
expected: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nmyapp myotherimage:latest 60m ago \n",
},
{
name: "tag moved",
appImageName: "myimage:latest",
appImageDigest: "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
expected: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nmyapp dddddddddddd 60m ago \n",
},
{
name: "not found",
appImageName: "dne:v1",
appImageDigest: "sha256:1111111111111111111111111111111111111111111111111111111111111111",
expected: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nmyapp 111111111111 60m ago \n",
},
{
name: "no implicit assumption for other registries",
appImageName: "acornimage:latest",
appImageDigest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
expected: "NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE\nmyapp eeeeeeeeeeee 60m ago \n",
},
}

for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
r, w, _ := os.Pipe()
os.Stdout = w
out := table.NewWriter(tables.App, false, "")

app := &v1.App{
ObjectMeta: metav1.ObjectMeta{
Name: "myapp",
CreationTimestamp: metav1.Time{
Time: time.Now().Add(-1 * time.Hour),
},
},
Status: internalv1.AppInstanceStatus{
AppImage: internalv1.AppImage{
Name: tt.appImageName,
Digest: tt.appImageDigest,
},
},
}
writeApp(context.Background(), app, out, c)
out.Flush()
w.Close()
output, _ := io.ReadAll(r)
assert.Equal(t, tt.expected, string(output))
})
}
}

func registerMockCalls(t *testing.T, c *mocks.MockClient) {
t.Helper()

c.EXPECT().ImageGet(gomock.Any(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
Return(&v1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
Digest: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
Tags: []string{"myimage:latest"},
}, nil).AnyTimes()
c.EXPECT().ImageGet(gomock.Any(), "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").
Return(&v1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
},
Digest: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
Tags: []string{"index.docker.io/myimage:latest", "myimage:v1"},
}, nil).AnyTimes()
c.EXPECT().ImageGet(gomock.Any(), "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc").
Return(&v1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
},
Digest: "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
Tags: []string{"docker.io/myotherimage:latest"},
}, nil).AnyTimes()
c.EXPECT().ImageGet(gomock.Any(), "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd").
Return(&v1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
},
Digest: "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
Tags: nil,
}, nil).AnyTimes()
c.EXPECT().ImageGet(gomock.Any(), "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee").
Return(&v1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
},
Digest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
Tags: []string{"acorn.io/acornimage:latest"},
}, nil).AnyTimes()
c.EXPECT().ImageGet(gomock.Any(), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").
Return(&v1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
},
Digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
Tags: []string{"acornimage:latest"},
}, nil).AnyTimes()
c.EXPECT().ImageGet(gomock.Any(), "1111111111111111111111111111111111111111111111111111111111111111").
Return(nil, fmt.Errorf("dne")).AnyTimes()
}
10 changes: 10 additions & 0 deletions pkg/cli/builder/table/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var (
"defaultMemory": DefaultMemory,
"ownerName": OwnerReferenceName,
"imageName": ImageName,
"imageDigest": ImageDigest,
}
)

Expand Down Expand Up @@ -306,3 +307,12 @@ func ImageName(obj metav1.Object) string {
}
return app.Status.AppImage.Name
}

func ImageDigest(obj metav1.Object) string {
app, ok := obj.(*apiv1.App)
if !ok {
return ""
}

return strings.TrimPrefix(app.Status.AppImage.Digest, "sha256:")
}
4 changes: 2 additions & 2 deletions pkg/cli/testdata/all/all_test.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

APPS:
NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE
found 292y ago
NAME IMAGE DIGEST HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE
found 292y ago

CONTAINERS:
NAME APP IMAGE STATE RESTARTCOUNT CREATED MESSAGE
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/testdata/all/all_test_i.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

APPS:
NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE
found 292y ago
NAME IMAGE DIGEST HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE
found 292y ago

CONTAINERS:
NAME APP IMAGE STATE RESTARTCOUNT CREATED MESSAGE
Expand Down
1 change: 1 addition & 0 deletions pkg/tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var (
App = [][]string{
{"Name", "{{ . | name }}"},
{"Image", "{{ . | imageName | trunc }}"},
{"Digest", "{{ . | imageDigest | trunc }}"},
{"Healthy", "Status.Columns.Healthy"},
{"Up-To-Date", "Status.Columns.UpToDate"},
{"Created", "{{ago .CreationTimestamp}}"},
Expand Down

0 comments on commit 95c1a6e

Please sign in to comment.