* feat: add imagesearch provider * update * update * update * update url and queries * add func getProviderTypeByHost --------- Signed-off-by: wenhaozhou <wenhaozhou@yunify.com> Signed-off-by: hongming <coder.scala@gmail.com> Co-authored-by: wenhaozhou <wenhaozhou@yunify.com>
100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
/*
|
|
* Please refer to the LICENSE file in the root directory of the project.
|
|
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
|
*/
|
|
|
|
package dockerhub
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"k8s.io/klog/v2"
|
|
|
|
"kubesphere.io/kubesphere/pkg/models/registries/imagesearch"
|
|
)
|
|
|
|
const (
|
|
DockerHubRegisterProvider = "DockerHubRegistryProvider"
|
|
dockerHubSearchUrl = "v2/search/repositories?query=%s"
|
|
dockerHubHost = "https://hub.docker.com"
|
|
)
|
|
|
|
func init() {
|
|
imagesearch.RegistrySearchProvider(&dockerHubSearchProviderFactory{})
|
|
}
|
|
|
|
var _ imagesearch.SearchProvider = &dockerHubSearchProvider{}
|
|
|
|
type dockerHubSearchProvider struct {
|
|
HttpClient *http.Client `json:"-" yaml:"-"`
|
|
}
|
|
|
|
type searchResponse struct {
|
|
Results []result `json:"results"`
|
|
}
|
|
|
|
type result struct {
|
|
RepoName string `json:"repo_name"`
|
|
}
|
|
|
|
func (d dockerHubSearchProvider) Search(imageName string, config imagesearch.SearchConfig) (*imagesearch.Results, error) {
|
|
url := fmt.Sprintf("%s/%s", dockerHubHost, fmt.Sprintf(dockerHubSearchUrl, imageName))
|
|
request, err := http.NewRequest(http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if config.Username != "" {
|
|
authCode := fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", config.Username, config.Password))))
|
|
request.Header.Set("Authorization", authCode)
|
|
}
|
|
|
|
resp, err := d.HttpClient.Do(request)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
bytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
klog.Errorf("search images failed with status code: %d, %s", resp.StatusCode, string(bytes))
|
|
return nil, fmt.Errorf("search images failed with status code: %d", resp.StatusCode)
|
|
}
|
|
|
|
searchResp := &searchResponse{}
|
|
err = json.Unmarshal(bytes, searchResp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
imageResult := &imagesearch.Results{
|
|
Entries: make([]string, 0),
|
|
}
|
|
for _, v := range searchResp.Results {
|
|
imageResult.Entries = append(imageResult.Entries, v.RepoName)
|
|
}
|
|
|
|
imageResult.Total = int64(len(imageResult.Entries))
|
|
|
|
return imageResult, nil
|
|
}
|
|
|
|
var _ imagesearch.SearchProviderFactory = &dockerHubSearchProviderFactory{}
|
|
|
|
type dockerHubSearchProviderFactory struct{}
|
|
|
|
func (d dockerHubSearchProviderFactory) Type() string {
|
|
return DockerHubRegisterProvider
|
|
}
|
|
|
|
func (d dockerHubSearchProviderFactory) Create(_ map[string]interface{}) (imagesearch.SearchProvider, error) {
|
|
var provider dockerHubSearchProvider
|
|
provider.HttpClient = http.DefaultClient
|
|
return provider, nil
|
|
}
|