File: registry.go

package info (click to toggle)
singularity-container 4.0.3%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 21,672 kB
  • sloc: asm: 3,857; sh: 2,125; ansic: 1,677; awk: 414; makefile: 110; python: 99
file content (93 lines) | stat: -rw-r--r-- 2,668 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright (c) 2023, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package library

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/containers/image/v5/types"
	scslibrary "github.com/sylabs/scs-library-client/client"
	"github.com/sylabs/singularity/v4/internal/pkg/remote/endpoint"
	"github.com/sylabs/singularity/v4/pkg/sylog"
)

// libraryRegistry holds information necessary to interact with an OCI registry
// backing a library.
type libraryRegistry struct {
	library  string
	registry string
	ud       *userData
}

// newLibraryRegisty retrieves URI and authentication information for the
// backing registry of the library associated with endpoint ep.
func newLibraryRegistry(ep *endpoint.Config, LibraryConfig *scslibrary.Config) (*libraryRegistry, error) {
	epLibraryURI, err := ep.GetServiceURI(endpoint.Library)
	if err != nil {
		return nil, err
	}

	if LibraryConfig.BaseURL != epLibraryURI {
		return nil, fmt.Errorf("OCI-SIF push/pull to/from location other than current remote is not supported")
	}

	sylog.Debugf("Finding OCI registry URI")
	registryURI, err := ep.RegistryURI()
	if err != nil {
		return nil, err
	}
	ru, err := url.Parse(registryURI)
	if err != nil {
		return nil, err
	}
	registry := strings.TrimSuffix(ru.Host+ru.Path, "/")

	lr := libraryRegistry{
		library:  LibraryConfig.BaseURL,
		registry: registry,
	}

	if ep.Token != "" {
		sylog.Debugf("Fetching OCI registry token")
		ud, err := getUserData(LibraryConfig)
		if err != nil {
			return nil, err
		}
		lr.ud = ud
	}

	return &lr, nil
}

// convertRef converts the provided library ref into an OCI reference referring
// to the library's backing OCI registry.
func (lr *libraryRegistry) convertRef(libraryRef scslibrary.Ref) (string, error) {
	if libraryRef.Host != "" {
		return "", fmt.Errorf("push to location other than current remote is not supported")
	}
	ref := fmt.Sprintf("docker://%s/%s", lr.registry, libraryRef.Path)
	if len(libraryRef.Tags) > 1 {
		return "", fmt.Errorf("cannot push/pull with more than one tag")
	}
	if len(libraryRef.Tags) > 0 {
		ref = ref + ":" + libraryRef.Tags[0]
	}
	return ref, nil
}

// authConfig returns a DockerAuthConfig with current token to authenticate
// against the library's backing OCI registry, if logged in - nil otherwise.
func (lr *libraryRegistry) authConfig() *types.DockerAuthConfig {
	if lr.ud == nil {
		return nil
	}
	return &types.DockerAuthConfig{
		Username: lr.ud.Username,
		Password: lr.ud.OidcMeta.Secret,
	}
}