feat: master/agent phase 1 — live inventory (#6) #19
@@ -0,0 +1,43 @@
|
|||||||
|
// Package imageref splits container image references into repository, tag
|
||||||
|
// and digest.
|
||||||
|
package imageref
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Ref is an image reference split into its parts. Tag and Digest are empty
|
||||||
|
// when the reference has none.
|
||||||
|
type Ref struct {
|
||||||
|
Repo string
|
||||||
|
Tag string
|
||||||
|
Digest string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse splits ref into repository, tag and digest. A colon before the last
|
||||||
|
// "/" belongs to a registry host and port ("localhost:5000/foo"), not a tag.
|
||||||
|
func Parse(ref string) Ref {
|
||||||
|
var r Ref
|
||||||
|
if at := strings.Index(ref, "@"); at >= 0 {
|
||||||
|
r.Digest = ref[at+1:]
|
||||||
|
ref = ref[:at]
|
||||||
|
}
|
||||||
|
slash := strings.LastIndex(ref, "/")
|
||||||
|
last := ref[slash+1:]
|
||||||
|
if colon := strings.Index(last, ":"); colon >= 0 {
|
||||||
|
r.Tag = last[colon+1:]
|
||||||
|
ref = ref[:slash+1+colon]
|
||||||
|
}
|
||||||
|
r.Repo = ref
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// String reassembles the reference as repo[:tag][@digest].
|
||||||
|
func (r Ref) String() string {
|
||||||
|
s := r.Repo
|
||||||
|
if r.Tag != "" {
|
||||||
|
s += ":" + r.Tag
|
||||||
|
}
|
||||||
|
if r.Digest != "" {
|
||||||
|
s += "@" + r.Digest
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package imageref
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
in string
|
||||||
|
want Ref
|
||||||
|
}{
|
||||||
|
{"postgres", Ref{Repo: "postgres"}},
|
||||||
|
{"postgres:17.10", Ref{Repo: "postgres", Tag: "17.10"}},
|
||||||
|
{"gitea/gitea:1.27.3@sha256:87a6", Ref{Repo: "gitea/gitea", Tag: "1.27.3", Digest: "sha256:87a6"}},
|
||||||
|
{"lscr.io/linuxserver/jellyfin@sha256:0f42", Ref{Repo: "lscr.io/linuxserver/jellyfin", Digest: "sha256:0f42"}},
|
||||||
|
{"localhost:5000/foo", Ref{Repo: "localhost:5000/foo"}},
|
||||||
|
{"localhost:5000/foo:v1", Ref{Repo: "localhost:5000/foo", Tag: "v1"}},
|
||||||
|
{"localhost:5000/foo:v1@sha256:ab", Ref{Repo: "localhost:5000/foo", Tag: "v1", Digest: "sha256:ab"}},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.in, func(t *testing.T) {
|
||||||
|
got := Parse(c.in)
|
||||||
|
assert.Equal(t, c.want, got)
|
||||||
|
assert.Equal(t, c.in, got.String(), "String must round-trip")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user