Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

Hide manifests behind button toggle #2841

Merged
Merged
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
4 changes: 2 additions & 2 deletions cmd/octant-sample-plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ func main() {
logger.Info("octant-sample-plugin is starting, with logger helper")
service.SetupPluginLogger(service.Info)
// OUTPUT: 2021-08-23T11:35:02.714-0500 INFO octant-sample-plugin plugin/logger.go:43 octant-sample-plugin is starting, with logger helper {"timestamp": "2021-08-23T11:35:02.714-0500"}
log.Println("octant-sample-plugin is starting, with with prefix logger")
// OUTPUT: 2021-08-23T11:35:02.714-0500 INFO octant-sample-plugin plugin/logger.go:43 [INFO] 2021/08/23 11:35:02 octant-sample-plugin is starting, with with prefix logger
log.Println("octant-sample-plugin is starting with prefix logger")
// OUTPUT: 2021-08-23T11:35:02.714-0500 INFO octant-sample-plugin plugin/logger.go:43 [INFO] 2021/08/23 11:35:02 octant-sample-plugin is starting with prefix logger
p.Serve()

}
Expand Down
43 changes: 30 additions & 13 deletions internal/printer/manifest.go → internal/manifest/manifest.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package printer
package manifest

import (
context "context"
"context"
"fmt"
"strings"
"sync"

"github.com/containers/image/v5/image"
imagev5 "github.com/containers/image/v5/image"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"

Expand All @@ -33,15 +33,32 @@ var (
)

func NewManifestConfiguration() *ManifestConfiguration {
mc := &ManifestConfiguration{}
mc := &ManifestConfiguration{
imageCache: make(map[ImageEntry]ImageManifest),
}
return mc
}

func (manifest *ManifestConfiguration) GetImageManifest(ctx context.Context, hostOS, imageName string) (string, string, error) {
func (manifest *ManifestConfiguration) SetManifest(imageEntry ImageEntry, imageManifest ImageManifest) {
manifest.imageCache[imageEntry] = imageManifest
}

func (manifest *ManifestConfiguration) HasEntry(hostOS, imageName string) bool {
imageName = parseName(imageName)
_, ok := manifest.imageCache[ImageEntry{ImageName: imageName, HostOS: hostOS}]
return ok
}

func parseName(imageName string) string {
parts := strings.SplitN(imageName, "://", 2) // if format not specified, assume docker
if len(parts) != 2 {
imageName = "docker://" + imageName
}
return imageName
}

func (manifest *ManifestConfiguration) GetImageManifest(ctx context.Context, hostOS, imageName string) (string, string, error) {
imageName = parseName(imageName)

imageEntry := ImageEntry{ImageName: imageName, HostOS: hostOS}
if _, ok := manifest.imageCache[imageEntry]; ok {
Expand All @@ -62,28 +79,28 @@ func (manifest *ManifestConfiguration) GetImageManifest(ctx context.Context, hos
if err != nil {
return "", "", fmt.Errorf("error creating image source for image %s: %w", imageName, err)
}
defer func() {
err = imageSrc.Close()
}()

rawManifest, _, err := imageSrc.GetManifest(ctx, nil)
if err != nil {
return "", "", fmt.Errorf("error getting manifest for for image %s: %w", imageName, err)
return "", "", fmt.Errorf("error getting manifest for image %s: %w", imageName, err)
}

image, err := image.FromUnparsedImage(ctx, systemCtx, image.UnparsedInstance(imageSrc, nil))
image, err := imagev5.FromUnparsedImage(ctx, systemCtx, imagev5.UnparsedInstance(imageSrc, nil))
if err != nil {
return "", "", fmt.Errorf("error parsing manifest for for image %s: %w", imageName, err)
return "", "", fmt.Errorf("error parsing manifest for image %s: %w", imageName, err)
}

rawConfiguration, err := image.OCIConfig(ctx)
if err != nil {
return "", "", fmt.Errorf("error getting image config blob for for image %s: %w", imageName, err)
return "", "", fmt.Errorf("error getting image config blob for image %s: %w", imageName, err)
}

configOutput, err := json.MarshalIndent(rawConfiguration, "", " ")

if manifest.imageCache == nil {
manifest.imageCache = make(map[ImageEntry]ImageManifest)
}
manifest.imageCache[imageEntry] = ImageManifest{string(rawManifest), string(configOutput)}

return string(rawManifest), string(configOutput), nil
return string(rawManifest), string(configOutput), err
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package printer
package manifest

import (
"context"
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -13,6 +13,9 @@ import (
)

func Test_GetImageManifest(t *testing.T) {
if os.Getenv("CI") != "" {
t.Skip("Skipping test in CI to avoid rate limits")
}
tests := []struct {
name string
input string
Expand Down Expand Up @@ -48,7 +51,7 @@ func Test_GetImageManifest(t *testing.T) {
manifestPath: "alpine_manifest.json",
configPath: "alpine_config.json",
hostOS: "windows",
error: "error parsing manifest for for image docker://alpine:3.14.0: choosing image instance: no image found in manifest list for architecture amd64, variant \"\", OS windows",
error: "error parsing manifest for image docker://alpine:3.14.0: choosing image instance: no image found in manifest list for architecture amd64, variant \"\", OS windows",
},
}
mc := NewManifestConfiguration()
Expand All @@ -61,7 +64,6 @@ func Test_GetImageManifest(t *testing.T) {
expectedConfig := string(inputConfig)[:len(inputConfig)-1]

manifest, config, err := mc.GetImageManifest(context.Background(), tt.hostOS, tt.input)
fmt.Println("err", err)
if len(tt.error) > 0 {
assert.EqualError(t, err, tt.error)
return
Expand Down
1 change: 1 addition & 0 deletions internal/modules/overview/overview.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ func (co *Overview) ActionPaths() map[string]action.DispatcherFunc {
octant.NewCronJobResume(co.dashConfig.ObjectStore(), co.dashConfig.ClusterClient()),
octant.NewObjectUpdaterDispatcher(co.dashConfig.ObjectStore()),
octant.NewApplyYaml(co.logger, co.dashConfig.ObjectStore()),
octant.NewManifest(co.logger),
}

return dispatchers.ToActionPaths()
Expand Down
1 change: 1 addition & 0 deletions internal/octant/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
ActionOverviewServiceEditor = "action.octant.dev/serviceEditor"
ActionDeploymentConfiguration = "action.octant.dev/deploymentConfiguration"
ActionUpdateObject = "action.octant.dev/update"
ActionGetManifest = "action.octant.dev/manifest"
)

func sendAlert(alerter action.Alerter, alertType action.AlertType, message string, expiration *time.Time) {
Expand Down
42 changes: 42 additions & 0 deletions internal/octant/manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package octant

import (
"context"
"fmt"

"github.com/vmware-tanzu/octant/internal/manifest"
"github.com/vmware-tanzu/octant/pkg/action"
"github.com/vmware-tanzu/octant/pkg/log"
)

type Manifest struct {
logger log.Logger
}

var _ action.Dispatcher = (*Manifest)(nil)

func NewManifest(logger log.Logger) *Manifest {
return &Manifest{logger: logger}
}

func (m *Manifest) ActionName() string {
return ActionGetManifest
}

func (m *Manifest) Handle(ctx context.Context, _ action.Alerter, payload action.Payload) error {
m.logger.With("payload", payload).Debugf("received action payload")
image, err := payload.String("image")
if err != nil {
return err
}
hostOS, err := payload.String("host")
if err != nil {
return err
}

_, _, err = manifest.ManifestManager.GetImageManifest(ctx, hostOS, image)
if err != nil {
return fmt.Errorf("getting manifest for image %s: %w", image, err)
}
return nil
}
26 changes: 15 additions & 11 deletions internal/printer/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ package printer
import (
"context"
"fmt"
"path"
"sort"
"strings"

"github.com/vmware-tanzu/octant/internal/api"
"github.com/vmware-tanzu/octant/internal/util/json"

"github.com/vmware-tanzu/octant/internal/log"
"github.com/vmware-tanzu/octant/internal/manifest"
"github.com/vmware-tanzu/octant/internal/util/json"
"github.com/vmware-tanzu/octant/internal/util/kubernetes"

"path"
"sort"
"strings"
"github.com/vmware-tanzu/octant/pkg/action"

"github.com/vmware-tanzu/octant/internal/octant"

Expand Down Expand Up @@ -128,12 +128,16 @@ func (cc *ContainerConfiguration) Create() (*component.Summary, error) {
sections.AddText("Image ID", containerStatus.ImageID)
}

manifest, configuration, err := ManifestManager.GetImageManifest(cc.context, hostOS, c.Image)
if err == nil {
sections.Add("Image Manifest", component.NewJSONEditor(manifest, true))
sections.Add("Image Configuration", component.NewJSONEditor(configuration, true))
if !manifest.ManifestManager.HasEntry(hostOS, c.Image) {
sections.Add("Image Manifest", component.NewButton("Show Manifest", action.CreatePayload(octant.ActionGetManifest, map[string]interface{}{"host": hostOS, "image": c.Image})))
} else {
sections.Add("Image Manifest", component.NewText(fmt.Sprintf("Unable to load image manifest %s", err)))
manifest, configuration, err := manifest.ManifestManager.GetImageManifest(cc.context, hostOS, c.Image)
if err == nil {
sections.Add("Image Manifest", component.NewJSONEditor(manifest, true))
sections.Add("Image Configuration", component.NewJSONEditor(configuration, true))
} else {
sections.Add("Image Manifest", component.NewText(fmt.Sprintf("Unable to load image manifest %s", err)))
}
}

hostPorts := describeContainerHostPorts(c.Ports)
Expand Down
Loading