mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License.AGPL.txt in the project root for license information.
|
|
|
|
package oci_tool
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"time"
|
|
|
|
"github.com/containerd/containerd/remotes"
|
|
"github.com/containerd/containerd/remotes/docker"
|
|
"github.com/docker/distribution/reference"
|
|
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
func Resolve(ctx context.Context, ref string) (string, error) {
|
|
newCtx, cancel := context.WithTimeout(ctx, time.Second*30)
|
|
defer cancel()
|
|
res := docker.NewResolver(docker.ResolverOptions{})
|
|
|
|
name, desc, err := res.Resolve(newCtx, ref)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
pref, err := reference.ParseNamed(name)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
cref, err := reference.WithDigest(pref, desc.Digest)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return cref.String(), nil
|
|
}
|
|
|
|
func interactiveFetchManifestOrIndex(ctx context.Context, res remotes.Resolver, ref string) (name string, result *ociv1.Manifest, err error) {
|
|
resolved, desc, err := res.Resolve(ctx, ref)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("cannot resolve %v: %w", ref, err)
|
|
}
|
|
|
|
fetcher, err := res.Fetcher(ctx, resolved)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
in, err := fetcher.Fetch(ctx, desc)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
defer in.Close()
|
|
buf, err := ioutil.ReadAll(in)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
var mf ociv1.Manifest
|
|
err = json.Unmarshal(buf, &mf)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("cannot unmarshal manifest: %w", err)
|
|
}
|
|
|
|
if mf.Config.Size != 0 {
|
|
return resolved, &mf, nil
|
|
}
|
|
return "", nil, nil
|
|
}
|
|
|
|
func ResolveIDEVersion(ctx context.Context, ref string) (string, error) {
|
|
newCtx, cancel := context.WithTimeout(ctx, time.Second*30)
|
|
defer cancel()
|
|
res := docker.NewResolver(docker.ResolverOptions{})
|
|
|
|
name, mf, err := interactiveFetchManifestOrIndex(newCtx, res, ref)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
fetcher, err := res.Fetcher(ctx, name)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
cfgin, err := fetcher.Fetch(ctx, mf.Config)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer cfgin.Close()
|
|
|
|
var tmp ManifestJSON
|
|
|
|
err = json.NewDecoder(cfgin).Decode(&tmp)
|
|
if err != nil {
|
|
return "", nil
|
|
}
|
|
return tmp.Config.Labels.Version, nil
|
|
}
|
|
|
|
type ManifestJSON struct {
|
|
Config struct {
|
|
Labels struct {
|
|
Version string `json:"io.gitpod.ide.version"`
|
|
} `json:"Labels"`
|
|
} `json:"config"`
|
|
}
|