-
Notifications
You must be signed in to change notification settings - Fork 295
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: added runtime for storing Manifest List
* added client logic for manifest cli * added manifest push Signed-off-by: WYGIN <[email protected]> * WIP refactor code Signed-off-by: WYGIN <[email protected]> * WIP refactor code Signed-off-by: WYGIN <[email protected]> --------- Signed-off-by: WYGIN <[email protected]> Signed-off-by: WYGIN <[email protected]> Co-authored-by: WYGIN <[email protected]>
- Loading branch information
1 parent
a89b275
commit 66b44e0
Showing
20 changed files
with
442 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
package commands_test | ||
package commands_test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package runtime | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/buildpacks/imgutil" | ||
"github.com/google/go-containerregistry/pkg/name" | ||
v1 "github.com/google/go-containerregistry/pkg/v1" | ||
) | ||
|
||
type ImageIndex struct { | ||
Index imgutil.Index | ||
Instances map[string][]ManifestConfig `json:"instance"` | ||
runtime *runtime | ||
} | ||
|
||
type ManifestConfig struct { | ||
Hash v1.Hash `json:"hash"` | ||
OS string `json:"os,omitempty"` | ||
OSVersion string `json:"os-version,omitempty"` | ||
Variant string `json:"variant,omitempty"` | ||
Architecture string `json:"arch,omitempty"` | ||
MediaType imgutil.MediaTypes `json:"mediaType,omitempty"` | ||
Local bool `json:"local,omitempty"` | ||
} | ||
|
||
type PushOptions struct { | ||
ManifestType string | ||
All bool | ||
Insecure bool | ||
} | ||
|
||
type imageIndex interface { | ||
Save(names []string, mimeType string) (string, error) | ||
Push(ctx context.Context, opts PushOptions) (name.Digest, error) | ||
Add(ctx context.Context, ref name.Reference, all bool) (name.Digest, error) | ||
Remove(digest name.Digest) error | ||
Delete(name string) error | ||
} | ||
|
||
func (i *ImageIndex) Save(names []string, mimeType string) (err error) { | ||
for _, name := range names { | ||
ref, err := i.runtime.ParseReference(name) | ||
if err != nil { | ||
return err | ||
} | ||
writeManifest := func(path string) error { | ||
manifest, err := json.MarshalIndent(i.Instances[ref.Identifier()], "", " ") | ||
file, err := os.Create(path) | ||
if err != nil { | ||
return err | ||
} | ||
_, err = file.Write(manifest) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
path := filepath.Join(i.runtime.manifestListPath, makeFilesafeName(ref.Identifier())) | ||
if _, err := os.Stat(filepath.Join(path, makeFilesafeName(name)+".config.json")); err != nil { | ||
fmt.Printf("overriding '%s'...", ref.Name()) | ||
if err := writeManifest(filepath.Join(path, makeFilesafeName(name)+".config.json")); err != nil { | ||
return err | ||
} | ||
} | ||
if err := writeManifest(filepath.Join(path, makeFilesafeName(name)+".config.json")); err != nil { | ||
return err | ||
} | ||
i.Index.Save(path, name, i.runtime.ImageType(mimeType)) | ||
} | ||
return nil | ||
} | ||
|
||
func (i *ImageIndex) Push(ctx context.Context, opts PushOptions) (digest name.Digest, err error) { | ||
for _, manifest := range i.Index.Manifests { | ||
for k, v := range i.Instances { | ||
for _, m := range v { | ||
if m.Hash.String() == manifest.Digest.String() && m.Local { | ||
fmt.Errorf("image: '%s' is not found in registry", k) | ||
} | ||
} | ||
} | ||
} | ||
digest, err = i.Index.Push(ctx, opts) | ||
if err == nil { | ||
fmt.Printf("successfully pushed ImageIndex to registry") | ||
} | ||
return | ||
} | ||
|
||
func (i *ImageIndex) Add(ctx context.Context, ref name.Reference, all bool) (digest name.Digest, err error) { | ||
for _, v := range i.Instances[ref.Identifier()] { | ||
var img string | ||
if image, err := i.runtime.ParseReference(ref.Name()); err == nil { | ||
img = strings.Split(image.Name(), ":")[0] + "@" + v.Hash.String() | ||
} | ||
if image, err := i.runtime.ParseDigest(ref.Name()); err == nil { | ||
img = image.Name() | ||
} | ||
if img == "" { | ||
return digest, fmt.Errorf("unable to parse the reference '%s'", ref.Name()) | ||
} | ||
if all { | ||
i.Index.Add(ctx, img, v.MediaType) | ||
} | ||
} | ||
|
||
return ref.Context().Digest(ref.Identifier()), err | ||
} | ||
|
||
func (i *ImageIndex) Remove(name string) (err error) { | ||
if ref, err := i.runtime.ParseDigest(name); err == nil { | ||
err = i.Index.Remove(ref) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
if ref, err := i.runtime.ParseReference(name); err == nil { | ||
for _, v := range i.Instances[ref.Identifier()] { | ||
name := strings.Split(ref.Name(), ":") | ||
if ref, err := i.runtime.ParseDigest(name[0] + "@" + v.Hash.String()); err == nil { | ||
if err := i.Index.Remove(ref); err == nil { | ||
fmt.Printf("Successfully removed Image '%s'", ref.Name()) | ||
} | ||
} | ||
err = nil | ||
} | ||
} | ||
return | ||
} | ||
|
||
func (i ImageIndex) Delete(name string) error { | ||
if _, err := i.runtime.ParseReference(name); err != nil { | ||
return err | ||
} | ||
|
||
return i.Index.Delete(name) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package runtime | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/buildpacks/imgutil" | ||
"github.com/google/go-containerregistry/pkg/name" | ||
v1 "github.com/google/go-containerregistry/pkg/v1" | ||
|
||
"github.com/buildpacks/pack/internal/config" | ||
) | ||
|
||
type runtime struct { | ||
manifestListPath string | ||
} | ||
|
||
func NewRuntime() (runtime, error) { | ||
if value, ok := os.LookupEnv("XDG_RUNTIME_DIR"); ok { | ||
return runtime{ | ||
manifestListPath: filepath.Join(value, "manifestList"), | ||
}, nil | ||
} | ||
if home, err := config.PackHome(); err == nil { | ||
return runtime{ | ||
manifestListPath: filepath.Join(home, "manifestList"), | ||
}, nil | ||
} | ||
return runtime{}, fmt.Errorf("unable to runtime path") | ||
} | ||
|
||
func (r runtime) LookupImageIndex(name string) (index ImageIndex, err error) { | ||
n, err := r.ParseReference(name) | ||
if err != nil { | ||
return index, err | ||
} | ||
filepath := filepath.Join(r.manifestListPath, makeFilesafeName(n.Name())) | ||
_, err = os.Stat(filepath) | ||
if err != nil { | ||
return | ||
} | ||
manifestBytes, _ := os.ReadFile(filepath) | ||
if err != nil { | ||
return | ||
} | ||
var dockerManifest imgutil.DockerManifestList | ||
var ociImageIndex v1.ImageIndex | ||
if err := json.Unmarshal(manifestBytes, &dockerManifest); err != nil { | ||
return ImageIndex{}, err | ||
} | ||
if err := json.Unmarshal(manifestBytes, &ociImageIndex); err != nil { | ||
return ImageIndex{}, err | ||
} | ||
return ImageIndex{ | ||
docker: dockerManifest, | ||
oci: ociImageIndex, | ||
}, err | ||
} | ||
|
||
func (r runtime) ImageType(format string) (manifestType imgutil.MediaTypes) { | ||
switch format { | ||
case imgutil.ImageIndexTypes.OCI: | ||
return imgutil.ImageIndexTypes.OCI | ||
case imgutil.ImageIndexTypes.Index: | ||
return imgutil.ImageIndexTypes.Index | ||
default: | ||
return imgutil.ImageIndexTypes.Docker | ||
} | ||
} | ||
|
||
func (r runtime) ParseReference(image string) (ref name.Reference, err error) { | ||
return name.ParseReference(image) | ||
} | ||
|
||
func (r runtime) ParseDigest(image string) (ref name.Digest, err error) { | ||
return name.NewDigest(image) | ||
} | ||
|
||
func (r runtime) RemoveManifests(ctx context.Context, names []string) (err error) { | ||
for _, name := range names { | ||
name = makeFilesafeName(name) | ||
if _, err := os.Stat(filepath.Join(r.manifestListPath, name, name)); err == nil { | ||
err := os.Remove(filepath.Join(r.manifestListPath, name)) | ||
if err != nil { | ||
errors = append(errors, err) | ||
} | ||
} | ||
} | ||
return | ||
} | ||
|
||
func makeFilesafeName(ref string) string { | ||
fileName := strings.Replace(ref, ":", "-", -1) | ||
return strings.Replace(fileName, "/", "_", -1) | ||
} |
Oops, something went wrong.