Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(controller)!: Key-only artifacts. Fixes #3184 #4618

Merged
merged 16 commits into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions api/jsonschema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3340,7 +3340,6 @@
}
},
"required": [
"bucket",
"key"
],
"type": "object"
Expand Down Expand Up @@ -3478,7 +3477,6 @@
}
},
"required": [
"addresses",
"path"
],
"type": "object"
Expand Down Expand Up @@ -3936,10 +3934,6 @@
}
},
"required": [
"endpoint",
"bucket",
"accessKeySecret",
"secretKeySecret",
"key"
],
"type": "object"
Expand Down Expand Up @@ -4202,10 +4196,6 @@
}
},
"required": [
"endpoint",
"bucket",
"accessKeySecret",
"secretKeySecret",
"key"
],
"type": "object"
Expand Down
10 changes: 0 additions & 10 deletions api/openapi-spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -6741,7 +6741,6 @@
"description": "GCSArtifact is the location of a GCS artifact",
"type": "object",
"required": [
"bucket",
"key"
],
"properties": {
Expand Down Expand Up @@ -6848,7 +6847,6 @@
"description": "HDFSArtifact is the location of an HDFS artifact",
"type": "object",
"required": [
"addresses",
"path"
],
"properties": {
Expand Down Expand Up @@ -7329,10 +7327,6 @@
"description": "OSSArtifact is the location of an Alibaba Cloud OSS artifact",
"type": "object",
"required": [
"endpoint",
"bucket",
"accessKeySecret",
"secretKeySecret",
"key"
],
"properties": {
Expand Down Expand Up @@ -7575,10 +7569,6 @@
"description": "S3Artifact is the location of an S3 artifact",
"type": "object",
"required": [
"endpoint",
"bucket",
"accessKeySecret",
"secretKeySecret",
"key"
],
"properties": {
Expand Down
78 changes: 78 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package config

import (
"fmt"
"path"

apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"

wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
"github.com/argoproj/argo/workflow/common"
)

var EmptyConfigFunc = func() interface{} { return &Config{} }
Expand Down Expand Up @@ -138,6 +140,41 @@ func (a *ArtifactRepository) IsArchiveLogs() bool {
return a != nil && a.ArchiveLogs != nil && *a.ArchiveLogs
}

type ArtifactRepositoryType interface {
IntoArtifactLocation(l *wfv1.ArtifactLocation)
}

func (a *ArtifactRepository) Get() ArtifactRepositoryType {
if a == nil {
return nil
} else if a.Artifactory != nil {
return a.Artifactory
} else if a.GCS != nil {
return a.GCS
} else if a.HDFS != nil {
return a.HDFS
} else if a.OSS != nil {
return a.OSS
} else if a.S3 != nil {
return a.S3
}
return nil
}

// ToArtifactLocation returns the artifact location set with default template key:
// key = `{{workflow.name}}/{{pod.name}}`
func (a *ArtifactRepository) ToArtifactLocation() *wfv1.ArtifactLocation {
if a == nil {
return nil
}
l := &wfv1.ArtifactLocation{ArchiveLogs: a.ArchiveLogs}
v := a.Get()
if v != nil {
v.IntoArtifactLocation(l)
}
return l
}

type PersistConfig struct {
NodeStatusOffload bool `json:"nodeStatusOffLoad,omitempty"`
// Archive workflows to persistence.
Expand Down Expand Up @@ -212,6 +249,14 @@ type S3ArtifactRepository struct {
KeyPrefix string `json:"keyPrefix,omitempty"`
}

func (r *S3ArtifactRepository) IntoArtifactLocation(l *wfv1.ArtifactLocation) {
k := r.KeyFormat
if k == "" {
k = path.Join(r.KeyPrefix, common.DefaultArchivePattern)
}
l.S3 = &wfv1.S3Artifact{S3Bucket: r.S3Bucket, Key: k}
}

// OSSArtifactRepository defines the controller configuration for an OSS artifact repository
type OSSArtifactRepository struct {
wfv1.OSSBucket `json:",inline"`
Expand All @@ -220,6 +265,14 @@ type OSSArtifactRepository struct {
KeyFormat string `json:"keyFormat,omitempty"`
}

func (r *OSSArtifactRepository) IntoArtifactLocation(l *wfv1.ArtifactLocation) {
k := r.KeyFormat
if k == "" {
k = common.DefaultArchivePattern
}
l.OSS = &wfv1.OSSArtifact{OSSBucket: r.OSSBucket, Key: k}
}

// GCSArtifactRepository defines the controller configuration for a GCS artifact repository
type GCSArtifactRepository struct {
wfv1.GCSBucket `json:",inline"`
Expand All @@ -228,13 +281,30 @@ type GCSArtifactRepository struct {
KeyFormat string `json:"keyFormat,omitempty"`
}

func (r *GCSArtifactRepository) IntoArtifactLocation(l *wfv1.ArtifactLocation) {
k := r.KeyFormat
if k == "" {
k = common.DefaultArchivePattern
}
l.GCS = &wfv1.GCSArtifact{GCSBucket: r.GCSBucket, Key: k}
}

// ArtifactoryArtifactRepository defines the controller configuration for an artifactory artifact repository
type ArtifactoryArtifactRepository struct {
wfv1.ArtifactoryAuth `json:",inline"`
// RepoURL is the url for artifactory repo.
RepoURL string `json:"repoURL,omitempty"`
}

func (r *ArtifactoryArtifactRepository) IntoArtifactLocation(l *wfv1.ArtifactLocation) {
u := ""
if r.RepoURL != "" {
u = r.RepoURL + "/"
}
u = fmt.Sprintf("%s%s", u, common.DefaultArchivePattern)
l.Artifactory = &wfv1.ArtifactoryArtifact{ArtifactoryAuth: r.ArtifactoryAuth, URL: u}
}

// HDFSArtifactRepository defines the controller configuration for an HDFS artifact repository
type HDFSArtifactRepository struct {
wfv1.HDFSConfig `json:",inline"`
Expand All @@ -246,6 +316,14 @@ type HDFSArtifactRepository struct {
Force bool `json:"force,omitempty"`
}

func (r *HDFSArtifactRepository) IntoArtifactLocation(l *wfv1.ArtifactLocation) {
p := r.PathFormat
if p == "" {
p = common.DefaultArchivePattern
}
l.HDFS = &wfv1.HDFSArtifact{HDFSConfig: r.HDFSConfig, Path: p, Force: r.Force}
}

// MetricsConfig defines a config for a metrics server
type MetricsConfig struct {
// Enabled controls metric emission. Default is true, set "enabled: false" to turn off
Expand Down
54 changes: 54 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,60 @@ import (
"k8s.io/utils/pointer"
)

func TestArtifactRepository(t *testing.T) {
t.Run("Nil", func(t *testing.T) {
var r *ArtifactRepository
assert.Nil(t, r.Get())
l := r.ToArtifactLocation()
assert.Nil(t, l)
})
t.Run("ArchiveLogs", func(t *testing.T) {
r := &ArtifactRepository{Artifactory: &ArtifactoryArtifactRepository{}, ArchiveLogs: pointer.BoolPtr(true)}
l := r.ToArtifactLocation()
assert.Equal(t, pointer.BoolPtr(true), l.ArchiveLogs)
})
t.Run("Artifactory", func(t *testing.T) {
r := &ArtifactRepository{Artifactory: &ArtifactoryArtifactRepository{RepoURL: "http://my-repo"}}
assert.IsType(t, &ArtifactoryArtifactRepository{}, r.Get())
l := r.ToArtifactLocation()
if assert.NotNil(t, l.Artifactory) {
assert.Equal(t, "http://my-repo/{{workflow.name}}/{{pod.name}}", l.Artifactory.URL)
}
})
t.Run("GCS", func(t *testing.T) {
r := &ArtifactRepository{GCS: &GCSArtifactRepository{}}
assert.IsType(t, &GCSArtifactRepository{}, r.Get())
l := r.ToArtifactLocation()
if assert.NotNil(t, l.GCS) {
assert.Equal(t, "{{workflow.name}}/{{pod.name}}", l.GCS.Key)
}
})
t.Run("HDFS", func(t *testing.T) {
r := &ArtifactRepository{HDFS: &HDFSArtifactRepository{}}
assert.IsType(t, &HDFSArtifactRepository{}, r.Get())
l := r.ToArtifactLocation()
if assert.NotNil(t, l.HDFS) {
assert.Equal(t, "{{workflow.name}}/{{pod.name}}", l.HDFS.Path)
}
})
t.Run("OSS", func(t *testing.T) {
r := &ArtifactRepository{OSS: &OSSArtifactRepository{}}
assert.IsType(t, &OSSArtifactRepository{}, r.Get())
l := r.ToArtifactLocation()
if assert.NotNil(t, l.OSS) {
assert.Equal(t, "{{workflow.name}}/{{pod.name}}", l.OSS.Key)
}
})
t.Run("S3", func(t *testing.T) {
r := &ArtifactRepository{S3: &S3ArtifactRepository{KeyPrefix: "my-key-prefix"}}
assert.IsType(t, &S3ArtifactRepository{}, r.Get())
l := r.ToArtifactLocation()
if assert.NotNil(t, l.S3) {
assert.Equal(t, "my-key-prefix/{{workflow.name}}/{{pod.name}}", l.S3.Key)
}
})
}

func TestArtifactRepository_IsArchiveLogs(t *testing.T) {
assert.False(t, (&ArtifactRepository{}).IsArchiveLogs())
assert.False(t, (&ArtifactRepository{ArchiveLogs: pointer.BoolPtr(false)}).IsArchiveLogs())
Expand Down
4 changes: 3 additions & 1 deletion docs/artifact-repository-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ metadata:
# if you want to use this config map by default - name it "artifact-repositories"
name: artifact-repositories
annotations:
# if you want to use a specific key, put that's key into this annotation
# v3.0 and after - if you want to use a specific key, put that's key into this annotation
workflows.argoproj.io/default-artifact-repository: default-v1
data:
default-v1: |
Expand All @@ -40,4 +40,6 @@ spec:
key: my-key # default can be set by the annotation
```

This feature gives maximum benefit when used with [key-only artifacts](key-only-artifacts.md).

Reference: [fields.md#artifactrepositoryref](fields.md#artifactrepositoryref).
Loading