package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/docker/distribution"
"github.com/docker/distribution/manifest"
"github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/schema2"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
log "github.com/sirupsen/logrus"
)
func GetImageManifest(TargetUrl string) (*v1.Manifest, string, int64, error) {
rep, body, errors := NewGoRequest().
Get(TargetUrl).
Set("Content-Type", "application/vnd.docker.distribution.manifest.list.v2+json").
End()
if errors != nil {
log.Errorf("fetch manifest url:%v failed:%v", TargetUrl, errors)
return nil, "", 0, fmt.Errorf("fetch manifest url:%v failed:%v", TargetUrl, errors)
}
defer rep.Body.Close()
if rep.StatusCode != http.StatusOK {
log.Errorf("fetch manifest url:%v failed:%v,get httpcode:%v", TargetUrl, body, rep.StatusCode)
return nil, "", 0, fmt.Errorf("fetch manifest url:%v failed:%v,get httpcode:%v", TargetUrl, body, rep.StatusCode)
}
var manifest = new(v1.Manifest)
json.Unmarshal([]byte(body), &manifest)
log.Infof("get digest:%s", rep.Header.Get("Docker-Content-Digest"))
log.Infof("get contentlength:%v", rep.ContentLength)
return manifest, rep.Header.Get("Docker-Content-Digest"), rep.ContentLength, nil
}
func CreateAllManifestList(projectname, imageName, version, amddigestid, armdigestid string, amdSize, armSize int64) error {
var manifestList = manifestlist.ManifestList{
Versioned: manifest.Versioned{
SchemaVersion: 2,
MediaType: manifestlist.MediaTypeManifestList,
},
Manifests: []manifestlist.ManifestDescriptor{
{
Descriptor: distribution.Descriptor{
Digest: digest.Digest(armdigestid),
Size: armSize,
MediaType: schema2.MediaTypeManifest,
},
Platform: manifestlist.PlatformSpec{
Architecture: "arm64",
OS: "linux",
},
}, {
Descriptor: distribution.Descriptor{
Digest: digest.Digest(amddigestid),
Size: amdSize,
MediaType: schema2.MediaTypeManifest,
},
Platform: manifestlist.PlatformSpec{
Architecture: "amd64",
OS: "linux",
},
},
},
}
core := "harbor.cmo21.com"
TargetUrl := "https://" + core + "/v2/" + projectname + "/" + imageName + "/manifests/" + version
log.Infof("put manifestlist url:%v", TargetUrl)
rep, body, errors := NewGoRequest().
Put(TargetUrl).
Set("Content-Type", "application/vnd.docker.distribution.manifest.list.v2+json").
Send(manifestList).
End()
if errors != nil {
log.Errorf("put harbor manifest %v failed:%v", TargetUrl, errors)
return fmt.Errorf("put harbor manifest %v failed:%v", TargetUrl, errors)
}
defer rep.Body.Close()
if rep.StatusCode != http.StatusCreated {
log.Errorf("put harbor manifest url:%s,get httpcode:%v,get body:%v", TargetUrl, rep.StatusCode, body)
return fmt.Errorf("put harbor manifest url:%s,get httpcode:%v,get body:%v", TargetUrl, rep.StatusCode, body)
}
return nil
}
package main
import ()
func main() {
_, amddigest, amdsize,err := GetImageManifest("https://harbor.cmo21.com/v2/container/nginx-liuwei/manifests/v1-amd64")
if err != nil {
return
}
_, armdigest, armsize,err := GetImageManifest("https://harbor.cmo21.com/v2/container/nginx-liuwei/manifests/v1-arm64")
if err != nil {
return
}
err = CreateAllManifestList("container", "nginx-liuwei", "v1", amddigest, armdigest, amdsize, armsize)
if err != nil {
return
}
}