package controller
import (
"context"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
"strings"
"time"
"crypto/tls"
apimodel "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/api/util/bcode"
"github.com/goodrain/rainbond/builder/sources/registry"
httputil "github.com/goodrain/rainbond/util/http"
"github.com/sirupsen/logrus"
"net/http"
"net/url"
)
type Registry struct {
}
type RepositoryTags struct {
Registry string `json:"registry"`
Repository string `json:"repository"`
Tags []string `json:"tags"`
Total int `json:"total"`
}
func (r2 *Registry) CheckRegistry(w http.ResponseWriter, r *http.Request) {
var req apimodel.SearchByDomainRequest
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil)
if !ok {
return
}
if !strings.Contains(req.Domain, "://") {
req.Domain = "//" + req.Domain
}
parse, err := url.Parse(req.Domain)
if err != nil {
logrus.Errorf("parse url error %s", err.Error())
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
return
}
options := make([]name.Option, 0)
if parse.Scheme == "http" {
options = append(options, name.Insecure)
}
tr := http.DefaultTransport.(*http.Transport).Clone()
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
registryCfg, err := name.NewRegistry(parse.Host, options...)
if err != nil {
logrus.Errorf("parse registry error %s", err.Error())
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
return
}
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
_, err = transport.NewWithContext(ctx, registryCfg, &authn.Basic{
Username: req.UserName,
Password: req.Password,
}, tr, []string{})
if err != nil {
logrus.Errorf("check registry error %s", err.Error())
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
return
}
httputil.ReturnSuccess(r, w, true)
}
func (r2 *Registry) GetAllRepo(w http.ResponseWriter, r *http.Request) {
var req apimodel.SearchByDomainRequest
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil)
if !ok {
return
}
c, err := registry.NewInsecure(req.Domain, req.UserName, req.Password)
if err != nil {
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
logrus.Errorf("get repositories error %s", err.Error())
return
}
repositories, err := c.Repositories()
if err != nil {
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
logrus.Errorf("get repositories error %s", err.Error())
return
}
httputil.ReturnSuccess(r, w, repositories)
}
func (r2 *Registry) GetTagsByRepoName(w http.ResponseWriter, r *http.Request) {
var req apimodel.SearchByDomainRequest
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil)
if !ok {
return
}
var regURL string
if strings.HasSuffix(req.Domain, "/") {
regURL = req.Domain + r.URL.Query().Get("repo")
} else {
regURL = req.Domain + "/" + r.URL.Query().Get("repo")
}
repo, err := name.NewRepository(regURL)
if err != nil {
logrus.Errorf("parse registry error %s", err.Error())
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
return
}
authenticator := authn.FromConfig(authn.AuthConfig{
Username: req.UserName,
Password: req.Password,
})
tags, err := remote.List(repo, remote.WithAuth(authenticator))
if err != nil {
logrus.Errorf("get tags error %s", err.Error())
httputil.ReturnBcodeError(r, w, bcode.NewBadRequest(err.Error()))
return
}
httputil.ReturnSuccess(r, w, &RepositoryTags{
Registry: repo.RegistryStr(),
Repository: repo.RepositoryStr(),
Tags: tags,
Total: len(tags),
})
}