-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
artifactrepositories.go
98 lines (88 loc) · 4.03 KB
/
artifactrepositories.go
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
94
95
96
97
98
package artifactrepositories
import (
"context"
"fmt"
"strings"
log "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-workflows/v3/config"
wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
errorsutil "github.com/argoproj/argo-workflows/v3/util/errors"
"github.com/argoproj/argo-workflows/v3/util/retry"
waitutil "github.com/argoproj/argo-workflows/v3/util/wait"
)
//go:generate mockery -name Interface
type Interface interface {
// Resolve Figures out the correct repository to for a workflow.
Resolve(ctx context.Context, ref *wfv1.ArtifactRepositoryRef, workflowNamespace string) (*wfv1.ArtifactRepositoryRefStatus, error)
// Get returns the referenced repository. May return nil (if no default artifact repository is configured).
Get(ctx context.Context, ref *wfv1.ArtifactRepositoryRefStatus) (*config.ArtifactRepository, error)
}
func New(kubernetesInterface kubernetes.Interface, namespace string, defaultArtifactRepository *config.ArtifactRepository) Interface {
return &artifactRepositories{kubernetesInterface, namespace, defaultArtifactRepository}
}
type artifactRepositories struct {
kubernetesInterface kubernetes.Interface
namespace string
defaultArtifactRepository *config.ArtifactRepository
}
func (s *artifactRepositories) Resolve(ctx context.Context, ref *wfv1.ArtifactRepositoryRef, workflowNamespace string) (*wfv1.ArtifactRepositoryRefStatus, error) {
var refs []*wfv1.ArtifactRepositoryRefStatus
if ref != nil {
refs = []*wfv1.ArtifactRepositoryRefStatus{
{Namespace: workflowNamespace, ArtifactRepositoryRef: wfv1.ArtifactRepositoryRef{ConfigMap: ref.ConfigMap, Key: ref.Key}},
{Namespace: s.namespace, ArtifactRepositoryRef: wfv1.ArtifactRepositoryRef{ConfigMap: ref.ConfigMap, Key: ref.Key}},
}
} else {
refs = []*wfv1.ArtifactRepositoryRefStatus{
{Namespace: workflowNamespace},
wfv1.DefaultArtifactRepositoryRefStatus,
}
}
for _, r := range refs {
resolvedRef, _, err := s.get(ctx, r)
if err != nil && (apierr.IsNotFound(err) || strings.Contains(err.Error(), "config map missing key")) {
continue
}
if err != nil {
return nil, fmt.Errorf(`error getting config map for artifact repository ref "%v": %w`, r, err)
}
log.WithField("artifactRepositoryRef", r).Info("resolved artifact repository")
return resolvedRef, nil
}
return nil, fmt.Errorf(`failed to find any artifact repository for artifact repository ref "%v"`, ref)
}
func (s *artifactRepositories) Get(ctx context.Context, ref *wfv1.ArtifactRepositoryRefStatus) (*config.ArtifactRepository, error) {
_, repo, err := s.get(ctx, ref)
return repo, err
}
func (s *artifactRepositories) get(ctx context.Context, ref *wfv1.ArtifactRepositoryRefStatus) (*wfv1.ArtifactRepositoryRefStatus, *config.ArtifactRepository, error) {
if ref.Default {
return ref, s.defaultArtifactRepository, nil
}
var cm *v1.ConfigMap
namespace := ref.Namespace
configMap := ref.GetConfigMapOr("artifact-repositories")
err := waitutil.Backoff(retry.DefaultRetry, func() (bool, error) {
var err error
cm, err = s.kubernetesInterface.CoreV1().ConfigMaps(namespace).Get(ctx, configMap, metav1.GetOptions{})
return !errorsutil.IsTransientErr(err), err
})
if err != nil {
return nil, nil, err
}
key := ref.GetKeyOr(cm.Annotations["workflows.argoproj.io/default-artifact-repository"])
value, ok := cm.Data[key]
if !ok {
return nil, nil, fmt.Errorf(`config map missing key %s for artifact repository ref "%v"`, ref, key)
}
repo := &config.ArtifactRepository{}
// we need the fully filled out ref so we can store it in the workflow status and it will never change
// (even if the config map default annotation is changed)
// this means users can change the default
return &wfv1.ArtifactRepositoryRefStatus{Namespace: namespace, ArtifactRepositoryRef: wfv1.ArtifactRepositoryRef{ConfigMap: configMap, Key: key}}, repo, yaml.Unmarshal([]byte(value), repo)
}