mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
Merge pull request #118 from tsnaik/cli-tls-verify
cli: add option to ignore TLS verification
This commit is contained in:
commit
b2ef9ab124
6 changed files with 148 additions and 90 deletions
|
@ -2,6 +2,7 @@ package cli
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
|
@ -14,17 +15,23 @@ import (
|
|||
zotErrors "github.com/anuvu/zot/errors"
|
||||
)
|
||||
|
||||
var httpClient *http.Client = createHTTPClient() //nolint: gochecknoglobals
|
||||
var httpClient *http.Client //nolint: gochecknoglobals
|
||||
|
||||
const httpTimeout = 5 * time.Second
|
||||
|
||||
func createHTTPClient() *http.Client {
|
||||
func createHTTPClient(verifyTLS bool) *http.Client {
|
||||
var tr = http.DefaultTransport.(*http.Transport).Clone()
|
||||
if !verifyTLS {
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint: gosec
|
||||
}
|
||||
|
||||
return &http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: tr,
|
||||
}
|
||||
}
|
||||
|
||||
func makeGETRequest(url, username, password string, resultsPtr interface{}) (http.Header, error) {
|
||||
func makeGETRequest(url, username, password string, verifyTLS bool, resultsPtr interface{}) (http.Header, error) {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
|
||||
if err != nil {
|
||||
|
@ -33,6 +40,10 @@ func makeGETRequest(url, username, password string, resultsPtr interface{}) (htt
|
|||
|
||||
req.SetBasicAuth(username, password)
|
||||
|
||||
if httpClient == nil {
|
||||
httpClient = createHTTPClient(verifyTLS)
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -74,9 +85,9 @@ type manifestJob struct {
|
|||
url string
|
||||
username string
|
||||
password string
|
||||
outputFormat string
|
||||
imageName string
|
||||
tagName string
|
||||
config searchConfig
|
||||
manifestResp manifestResponse
|
||||
}
|
||||
|
||||
|
@ -116,7 +127,7 @@ func (p *requestsPool) startRateLimiter() {
|
|||
func (p *requestsPool) doJob(job *manifestJob) {
|
||||
defer p.waitGroup.Done()
|
||||
|
||||
header, err := makeGETRequest(job.url, job.username, job.password, &job.manifestResp)
|
||||
header, err := makeGETRequest(job.url, job.username, job.password, *job.config.verifyTLS, &job.manifestResp)
|
||||
if err != nil {
|
||||
if isContextDone(p.context) {
|
||||
return
|
||||
|
@ -143,7 +154,7 @@ func (p *requestsPool) doJob(job *manifestJob) {
|
|||
},
|
||||
}
|
||||
|
||||
str, err := image.string(job.outputFormat)
|
||||
str, err := image.string(*job.config.outputFormat)
|
||||
if err != nil {
|
||||
if isContextDone(p.context) {
|
||||
return
|
||||
|
|
|
@ -205,6 +205,7 @@ func addConfig(configPath, configName, url string) error {
|
|||
configMap := make(map[string]interface{})
|
||||
configMap["url"] = url
|
||||
configMap[nameKey] = configName
|
||||
addDefaultConfigs(configMap)
|
||||
configs = append(configs, configMap)
|
||||
|
||||
err = saveConfigMapToFile(configPath, configs)
|
||||
|
@ -215,6 +216,16 @@ func addConfig(configPath, configName, url string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func addDefaultConfigs(config map[string]interface{}) {
|
||||
if _, ok := config[showspinnerConfig]; !ok {
|
||||
config[showspinnerConfig] = true
|
||||
}
|
||||
|
||||
if _, ok := config[verifyTLSConfig]; !ok {
|
||||
config[verifyTLSConfig] = true
|
||||
}
|
||||
}
|
||||
|
||||
func getConfigValue(configPath, configName, key string) (string, error) {
|
||||
configs, err := getConfigMapFromFile(configPath)
|
||||
if err != nil {
|
||||
|
@ -227,6 +238,7 @@ func getConfigValue(configPath, configName, key string) (string, error) {
|
|||
|
||||
for _, val := range configs {
|
||||
configMap := val.(map[string]interface{})
|
||||
addDefaultConfigs(configMap)
|
||||
|
||||
name := configMap[nameKey]
|
||||
if name == configName {
|
||||
|
@ -257,6 +269,7 @@ func resetConfigValue(configPath, configName, key string) error {
|
|||
|
||||
for _, val := range configs {
|
||||
configMap := val.(map[string]interface{})
|
||||
addDefaultConfigs(configMap)
|
||||
|
||||
name := configMap[nameKey]
|
||||
if name == configName {
|
||||
|
@ -290,6 +303,7 @@ func setConfigValue(configPath, configName, key, value string) error {
|
|||
|
||||
for _, val := range configs {
|
||||
configMap := val.(map[string]interface{})
|
||||
addDefaultConfigs(configMap)
|
||||
|
||||
name := configMap[nameKey]
|
||||
if name == configName {
|
||||
|
@ -326,6 +340,7 @@ func getAllConfig(configPath, configName string) (string, error) {
|
|||
|
||||
for _, value := range configs {
|
||||
configMap := value.(map[string]interface{})
|
||||
addDefaultConfigs(configMap)
|
||||
|
||||
name := configMap[nameKey]
|
||||
if name == configName {
|
||||
|
@ -353,7 +368,8 @@ const (
|
|||
supportedOptions = `
|
||||
Useful variables:
|
||||
url zot server URL
|
||||
showspinner show spinner while loading data [true/false]`
|
||||
showspinner show spinner while loading data [true/false]
|
||||
verify-tls verify TLS Certificate verification of the server [default: true]`
|
||||
|
||||
nameKey = "_name"
|
||||
|
||||
|
@ -361,6 +377,9 @@ Useful variables:
|
|||
oneArg = 1
|
||||
twoArgs = 2
|
||||
threeArgs = 3
|
||||
|
||||
showspinnerConfig = "showspinner"
|
||||
verifyTLSConfig = "verify-tls"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -14,11 +14,9 @@ import (
|
|||
func NewImageCommand(searchService ImageSearchService) *cobra.Command {
|
||||
searchImageParams := make(map[string]*string)
|
||||
|
||||
var servURL string
|
||||
var servURL, user, outputFormat string
|
||||
|
||||
var user string
|
||||
|
||||
var outputFormat string
|
||||
var isSpinner, verifyTLS bool
|
||||
|
||||
var imageCmd = &cobra.Command{
|
||||
Use: "images [config-name]",
|
||||
|
@ -47,20 +45,35 @@ func NewImageCommand(searchService ImageSearchService) *cobra.Command {
|
|||
}
|
||||
}
|
||||
|
||||
var isSpinner bool
|
||||
|
||||
if len(args) > 0 {
|
||||
var err error
|
||||
isSpinner, err = isSpinnerEnabled(configPath, args[0])
|
||||
isSpinner, err = parseBooleanConfig(configPath, args[0], showspinnerConfig)
|
||||
if err != nil {
|
||||
cmd.SilenceUsage = true
|
||||
return err
|
||||
}
|
||||
verifyTLS, err = parseBooleanConfig(configPath, args[0], verifyTLSConfig)
|
||||
if err != nil {
|
||||
cmd.SilenceUsage = true
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
isSpinner = true
|
||||
}
|
||||
|
||||
err = searchImage(cmd, searchImageParams, searchService, &servURL, &user, &outputFormat, isSpinner)
|
||||
spin := spinner.New(spinner.CharSets[39], spinnerDuration, spinner.WithWriter(cmd.ErrOrStderr()))
|
||||
spin.Prefix = "Searching... "
|
||||
|
||||
searchConfig := searchConfig{
|
||||
params: searchImageParams,
|
||||
searchService: searchService,
|
||||
servURL: &servURL,
|
||||
user: &user,
|
||||
outputFormat: &outputFormat,
|
||||
spinner: spinnerState{spin, isSpinner},
|
||||
verifyTLS: &verifyTLS,
|
||||
resultWriter: cmd.OutOrStdout(),
|
||||
}
|
||||
|
||||
err = searchImage(searchConfig)
|
||||
|
||||
if err != nil {
|
||||
cmd.SilenceUsage = true
|
||||
|
@ -77,22 +90,18 @@ func NewImageCommand(searchService ImageSearchService) *cobra.Command {
|
|||
return imageCmd
|
||||
}
|
||||
|
||||
func isSpinnerEnabled(configPath, configName string) (bool, error) {
|
||||
spinnerConfig, err := getConfigValue(configPath, configName, "showspinner")
|
||||
func parseBooleanConfig(configPath, configName, configParam string) (bool, error) {
|
||||
config, err := getConfigValue(configPath, configName, configParam)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if spinnerConfig == "" {
|
||||
return true, nil // spinner is enabled by default
|
||||
}
|
||||
|
||||
isSpinner, err := strconv.ParseBool(spinnerConfig)
|
||||
val, err := strconv.ParseBool(config)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return isSpinner, nil
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func setupCmdFlags(imageCmd *cobra.Command, searchImageParams map[string]*string, servURL, user, outputFormat *string) {
|
||||
|
@ -103,14 +112,9 @@ func setupCmdFlags(imageCmd *cobra.Command, searchImageParams map[string]*string
|
|||
imageCmd.Flags().StringVarP(outputFormat, "output", "o", "", "Specify output format [text/json/yaml]")
|
||||
}
|
||||
|
||||
func searchImage(cmd *cobra.Command, params map[string]*string,
|
||||
service ImageSearchService, servURL, user, outputFormat *string, isSpinner bool) error {
|
||||
spin := spinner.New(spinner.CharSets[39], spinnerDuration, spinner.WithWriter(cmd.ErrOrStderr()))
|
||||
spin.Prefix = "Searching... "
|
||||
|
||||
func searchImage(searchConfig searchConfig) error {
|
||||
for _, searcher := range getSearchers() {
|
||||
found, err := searcher.search(params, service, servURL, user, outputFormat,
|
||||
cmd.OutOrStdout(), spinnerState{spin, isSpinner})
|
||||
found, err := searcher.search(searchConfig)
|
||||
if found {
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -439,8 +439,8 @@ func uploadManifest(url string) {
|
|||
|
||||
type mockService struct{}
|
||||
|
||||
func (service mockService) getAllImages(ctx context.Context, serverURL, username, password,
|
||||
outputFormat string, channel chan imageListResult, wg *sync.WaitGroup) {
|
||||
func (service mockService) getAllImages(ctx context.Context, config searchConfig, username, password string,
|
||||
channel chan imageListResult, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
image := &imageStruct{}
|
||||
|
@ -453,7 +453,7 @@ func (service mockService) getAllImages(ctx context.Context, serverURL, username
|
|||
},
|
||||
}
|
||||
|
||||
str, err := image.string(outputFormat)
|
||||
str, err := image.string(*config.outputFormat)
|
||||
if err != nil {
|
||||
channel <- imageListResult{"", err}
|
||||
return
|
||||
|
@ -461,8 +461,8 @@ func (service mockService) getAllImages(ctx context.Context, serverURL, username
|
|||
channel <- imageListResult{str, nil}
|
||||
}
|
||||
|
||||
func (service mockService) getImageByName(ctx context.Context, serverURL, username, password,
|
||||
imageName, outputFormat string, channel chan imageListResult, wg *sync.WaitGroup) {
|
||||
func (service mockService) getImageByName(ctx context.Context, config searchConfig,
|
||||
username, password, imageName string, channel chan imageListResult, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
image := &imageStruct{}
|
||||
|
@ -475,7 +475,7 @@ func (service mockService) getImageByName(ctx context.Context, serverURL, userna
|
|||
},
|
||||
}
|
||||
|
||||
str, err := image.string(outputFormat)
|
||||
str, err := image.string(*config.outputFormat)
|
||||
if err != nil {
|
||||
channel <- imageListResult{"", err}
|
||||
return
|
||||
|
|
|
@ -22,8 +22,7 @@ func getSearchers() []searcher {
|
|||
}
|
||||
|
||||
type searcher interface {
|
||||
search(params map[string]*string, searchService ImageSearchService,
|
||||
servURL, user, outputFormat *string, stdWriter io.Writer, spinner spinnerState) (bool, error)
|
||||
search(searchConfig searchConfig) (bool, error)
|
||||
}
|
||||
|
||||
func canSearch(params map[string]*string, requiredParams *set) bool {
|
||||
|
@ -38,15 +37,25 @@ func canSearch(params map[string]*string, requiredParams *set) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
type searchConfig struct {
|
||||
params map[string]*string
|
||||
searchService ImageSearchService
|
||||
servURL *string
|
||||
user *string
|
||||
outputFormat *string
|
||||
verifyTLS *bool
|
||||
resultWriter io.Writer
|
||||
spinner spinnerState
|
||||
}
|
||||
|
||||
type allImagesSearcher struct{}
|
||||
|
||||
func (search allImagesSearcher) search(params map[string]*string, searchService ImageSearchService,
|
||||
servURL, user, outputFormat *string, stdWriter io.Writer, spinner spinnerState) (bool, error) {
|
||||
if !canSearch(params, newSet("")) {
|
||||
func (search allImagesSearcher) search(config searchConfig) (bool, error) {
|
||||
if !canSearch(config.params, newSet("")) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
username, password := getUsernameAndPassword(*user)
|
||||
username, password := getUsernameAndPassword(*config.user)
|
||||
imageErr := make(chan imageListResult)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
@ -54,12 +63,12 @@ func (search allImagesSearcher) search(params map[string]*string, searchService
|
|||
|
||||
wg.Add(1)
|
||||
|
||||
go searchService.getAllImages(ctx, *servURL, username, password, *outputFormat, imageErr, &wg)
|
||||
go config.searchService.getAllImages(ctx, config, username, password, imageErr, &wg)
|
||||
wg.Add(1)
|
||||
|
||||
var errCh chan error = make(chan error, 1)
|
||||
|
||||
go collectImages(outputFormat, stdWriter, &wg, imageErr, cancel, spinner, errCh)
|
||||
go collectImages(config, &wg, imageErr, cancel, errCh)
|
||||
wg.Wait()
|
||||
select {
|
||||
case err := <-errCh:
|
||||
|
@ -71,14 +80,12 @@ func (search allImagesSearcher) search(params map[string]*string, searchService
|
|||
|
||||
type imageByNameSearcher struct{}
|
||||
|
||||
func (search imageByNameSearcher) search(params map[string]*string,
|
||||
searchService ImageSearchService, servURL, user, outputFormat *string,
|
||||
stdWriter io.Writer, spinner spinnerState) (bool, error) {
|
||||
if !canSearch(params, newSet("imageName")) {
|
||||
func (search imageByNameSearcher) search(config searchConfig) (bool, error) {
|
||||
if !canSearch(config.params, newSet("imageName")) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
username, password := getUsernameAndPassword(*user)
|
||||
username, password := getUsernameAndPassword(*config.user)
|
||||
imageErr := make(chan imageListResult)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
@ -86,11 +93,11 @@ func (search imageByNameSearcher) search(params map[string]*string,
|
|||
|
||||
wg.Add(1)
|
||||
|
||||
go searchService.getImageByName(ctx, *servURL, username, password, *params["imageName"], *outputFormat, imageErr, &wg)
|
||||
go config.searchService.getImageByName(ctx, config, username, password, *config.params["imageName"], imageErr, &wg)
|
||||
wg.Add(1)
|
||||
|
||||
var errCh chan error = make(chan error, 1)
|
||||
go collectImages(outputFormat, stdWriter, &wg, imageErr, cancel, spinner, errCh)
|
||||
go collectImages(config, &wg, imageErr, cancel, errCh)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
|
@ -102,38 +109,44 @@ func (search imageByNameSearcher) search(params map[string]*string,
|
|||
}
|
||||
}
|
||||
|
||||
func collectImages(outputFormat *string, stdWriter io.Writer, wg *sync.WaitGroup,
|
||||
imageErr chan imageListResult, cancel context.CancelFunc, spinner spinnerState, errCh chan error) {
|
||||
func collectImages(config searchConfig, wg *sync.WaitGroup, imageErr chan imageListResult,
|
||||
cancel context.CancelFunc, errCh chan error) {
|
||||
var foundResult bool
|
||||
|
||||
defer wg.Done()
|
||||
spinner.startSpinner()
|
||||
config.spinner.startSpinner()
|
||||
|
||||
for {
|
||||
select {
|
||||
case result := <-imageErr:
|
||||
case result, ok := <-imageErr:
|
||||
config.spinner.stopSpinner()
|
||||
|
||||
if !ok {
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
|
||||
if result.Err != nil {
|
||||
spinner.stopSpinner()
|
||||
cancel()
|
||||
errCh <- result.Err
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
spinner.stopSpinner()
|
||||
|
||||
if !foundResult && (*outputFormat == "text" || *outputFormat == "") {
|
||||
if !foundResult && (*config.outputFormat == "text" || *config.outputFormat == "") {
|
||||
var builder strings.Builder
|
||||
|
||||
printImageTableHeader(&builder)
|
||||
fmt.Fprint(stdWriter, builder.String())
|
||||
fmt.Fprint(config.resultWriter, builder.String())
|
||||
}
|
||||
|
||||
foundResult = true
|
||||
|
||||
fmt.Fprint(stdWriter, result.StrValue)
|
||||
fmt.Fprint(config.resultWriter, result.StrValue)
|
||||
case <-time.After(waitTimeout):
|
||||
cancel()
|
||||
config.spinner.stopSpinner()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -211,5 +224,5 @@ func printImageTableHeader(writer io.Writer) {
|
|||
}
|
||||
|
||||
const (
|
||||
waitTimeout = 2 * time.Second
|
||||
waitTimeout = 6 * time.Second
|
||||
)
|
||||
|
|
|
@ -17,9 +17,9 @@ import (
|
|||
)
|
||||
|
||||
type ImageSearchService interface {
|
||||
getAllImages(ctx context.Context, serverURL, username, password,
|
||||
outputFormat string, channel chan imageListResult, wg *sync.WaitGroup)
|
||||
getImageByName(ctx context.Context, serverURL, username, password, imageName, outputFormat string,
|
||||
getAllImages(ctx context.Context, config searchConfig, username, password string,
|
||||
channel chan imageListResult, wg *sync.WaitGroup)
|
||||
getImageByName(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
channel chan imageListResult, wg *sync.WaitGroup)
|
||||
}
|
||||
type searchService struct{}
|
||||
|
@ -28,27 +28,32 @@ func NewImageSearchService() ImageSearchService {
|
|||
return searchService{}
|
||||
}
|
||||
|
||||
func (service searchService) getImageByName(ctx context.Context, url, username, password,
|
||||
imageName, outputFormat string, c chan imageListResult, wg *sync.WaitGroup) {
|
||||
func (service searchService) getImageByName(ctx context.Context, config searchConfig,
|
||||
username, password, imageName string, c chan imageListResult, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
defer close(c)
|
||||
|
||||
p := newSmoothRateLimiter(ctx, wg, c)
|
||||
var localWg sync.WaitGroup
|
||||
p := newSmoothRateLimiter(ctx, &localWg, c)
|
||||
|
||||
wg.Add(1)
|
||||
localWg.Add(1)
|
||||
|
||||
go p.startRateLimiter()
|
||||
wg.Add(1)
|
||||
localWg.Add(1)
|
||||
|
||||
go getImage(ctx, url, username, password, imageName, outputFormat, c, wg, p)
|
||||
go getImage(ctx, config, username, password, imageName, c, &localWg, p)
|
||||
|
||||
localWg.Wait()
|
||||
}
|
||||
|
||||
func (service searchService) getAllImages(ctx context.Context, url, username, password,
|
||||
outputFormat string, c chan imageListResult, wg *sync.WaitGroup) {
|
||||
func (service searchService) getAllImages(ctx context.Context, config searchConfig, username, password string,
|
||||
c chan imageListResult, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
defer close(c)
|
||||
|
||||
catalog := &catalogResponse{}
|
||||
|
||||
catalogEndPoint, err := combineServerAndEndpointURL(url, "/v2/_catalog")
|
||||
catalogEndPoint, err := combineServerAndEndpointURL(*config.servURL, "/v2/_catalog")
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -58,7 +63,7 @@ func (service searchService) getAllImages(ctx context.Context, url, username, pa
|
|||
return
|
||||
}
|
||||
|
||||
_, err = makeGETRequest(catalogEndPoint, username, password, catalog)
|
||||
_, err = makeGETRequest(catalogEndPoint, username, password, *config.verifyTLS, catalog)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -68,23 +73,28 @@ func (service searchService) getAllImages(ctx context.Context, url, username, pa
|
|||
return
|
||||
}
|
||||
|
||||
p := newSmoothRateLimiter(ctx, wg, c)
|
||||
var localWg sync.WaitGroup
|
||||
|
||||
wg.Add(1)
|
||||
p := newSmoothRateLimiter(ctx, &localWg, c)
|
||||
|
||||
localWg.Add(1)
|
||||
|
||||
go p.startRateLimiter()
|
||||
|
||||
for _, repo := range catalog.Repositories {
|
||||
wg.Add(1)
|
||||
localWg.Add(1)
|
||||
|
||||
go getImage(ctx, url, username, password, repo, outputFormat, c, wg, p)
|
||||
go getImage(ctx, config, username, password, repo, c, &localWg, p)
|
||||
}
|
||||
|
||||
localWg.Wait()
|
||||
}
|
||||
func getImage(ctx context.Context, url, username, password, imageName, outputFormat string,
|
||||
|
||||
func getImage(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
c chan imageListResult, wg *sync.WaitGroup, pool *requestsPool) {
|
||||
defer wg.Done()
|
||||
|
||||
tagListEndpoint, err := combineServerAndEndpointURL(url, fmt.Sprintf("/v2/%s/tags/list", imageName))
|
||||
tagListEndpoint, err := combineServerAndEndpointURL(*config.servURL, fmt.Sprintf("/v2/%s/tags/list", imageName))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -95,7 +105,7 @@ func getImage(ctx context.Context, url, username, password, imageName, outputFor
|
|||
}
|
||||
|
||||
tagsList := &tagListResp{}
|
||||
_, err = makeGETRequest(tagListEndpoint, username, password, &tagsList)
|
||||
_, err = makeGETRequest(tagListEndpoint, username, password, *config.verifyTLS, &tagsList)
|
||||
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -109,7 +119,7 @@ func getImage(ctx context.Context, url, username, password, imageName, outputFor
|
|||
for _, tag := range tagsList.Tags {
|
||||
wg.Add(1)
|
||||
|
||||
go addManifestCallToPool(ctx, pool, url, username, password, imageName, tag, outputFormat, c, wg)
|
||||
go addManifestCallToPool(ctx, config, pool, username, password, imageName, tag, c, wg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,13 +132,14 @@ func isContextDone(ctx context.Context) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func addManifestCallToPool(ctx context.Context, p *requestsPool, url, username, password, imageName,
|
||||
tagName, outputFormat string, c chan imageListResult, wg *sync.WaitGroup) {
|
||||
func addManifestCallToPool(ctx context.Context, config searchConfig, p *requestsPool, username, password, imageName,
|
||||
tagName string, c chan imageListResult, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
resultManifest := manifestResponse{}
|
||||
|
||||
manifestEndpoint, err := combineServerAndEndpointURL(url, fmt.Sprintf("/v2/%s/manifests/%s", imageName, tagName))
|
||||
manifestEndpoint, err := combineServerAndEndpointURL(*config.servURL,
|
||||
fmt.Sprintf("/v2/%s/manifests/%s", imageName, tagName))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -143,7 +154,7 @@ func addManifestCallToPool(ctx context.Context, p *requestsPool, url, username,
|
|||
password: password,
|
||||
tagName: tagName,
|
||||
manifestResp: resultManifest,
|
||||
outputFormat: outputFormat,
|
||||
config: config,
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
|
Loading…
Reference in a new issue