Skip to content

Commit f02389b

Browse files
authored
Support tokenId feature (#10)
* bump argocd deps to 1.5.4, use cristalhq/jwt/v2 in place of go-jose/jwt, wip at tokenId feature support * added project-scoped tokenMutexes, instead of provider instance token mutexes * added featureVersionConstraint unit tests * workaround for 1.5.3+ redis install issues with buggy simultaneous login limit feature
1 parent 18afe61 commit f02389b

20 files changed

+3206
-396
lines changed

.github/workflows/acceptance.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Acceptance Tests
1+
name: Tests
22
on:
33
push:
44
branches: ["master"]
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
argocd_version: ["v1.5.2", "v1.4.3"]
14+
argocd_version: ["v1.5.4", "v1.4.3"]
1515
steps:
1616
- uses: actions/checkout@v1
1717
- uses: actions/setup-go@v1
@@ -26,13 +26,21 @@ jobs:
2626
restore-keys: |
2727
${{ runner.os }}-go-
2828
29-
- name: Install Kind
30-
run: GO111MODULE=on go get sigs.k8s.io/kind
29+
- name: Install Kustomize
30+
run: |
31+
curl -sL "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
32+
chmod +x ./kustomize
33+
34+
- name: Install Kind 0.8.1
35+
run: |
36+
curl -sLo ./kind https://kind.sigs.k8s.io/dl/v0.8.1/kind-$(uname)-amd64
37+
chmod +x ./kind
3138
3239
- name: Set up ArgoCD ${{ matrix.argocd_version }}
3340
env:
3441
ARGOCD_VERSION: ${{ matrix.argocd_version }}
3542
run: |
43+
curl https://raw.githubusercontent.com/argoproj/argo-cd/${ARGOCD_VERSION}/manifests/install.yaml > manifests/install/install.yml
3644
sh scripts/testacc_prepare_env.sh
3745
kubectl port-forward -n argocd service/argocd-server --address 127.0.0.1 8080:443&
3846
until $(nc -z 127.0.0.1 8080); do sleep 2;done

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.idea
22
terraform-provider-argocd
3+
./manifests/install/install.yml

argocd/features.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package argocd
2+
3+
import (
4+
"fmt"
5+
"github.com/Masterminds/semver"
6+
argoCDApiClient "github.com/argoproj/argo-cd/pkg/apiclient"
7+
"github.com/argoproj/argo-cd/pkg/apiclient/version"
8+
)
9+
10+
const (
11+
featureTokenIDs = iota
12+
)
13+
14+
var (
15+
featureVersionConstraintsMap = map[int]*semver.Version{
16+
featureTokenIDs: semver.MustParse("1.5.3"),
17+
}
18+
)
19+
20+
type ServerInterface struct {
21+
ApiClient argoCDApiClient.Client
22+
ServerVersion *semver.Version
23+
ServerVersionMessage *version.VersionMessage
24+
}
25+
26+
// Checks that a specific feature is available for the current ArgoCD server version.
27+
// 'feature' argument must match one of the predefined feature* constants.
28+
func (p ServerInterface) isFeatureSupported(feature int) (bool, error) {
29+
versionConstraint, ok := featureVersionConstraintsMap[feature]
30+
if !ok {
31+
return false, fmt.Errorf("feature constraint is not handled by the provider")
32+
}
33+
if i := versionConstraint.Compare(p.ServerVersion); i == 1 {
34+
return false, nil
35+
}
36+
return true, nil
37+
}

argocd/features_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package argocd
2+
3+
import (
4+
"fmt"
5+
"github.com/Masterminds/semver"
6+
"github.com/argoproj/argo-cd/pkg/apiclient/version"
7+
"math/rand"
8+
"testing"
9+
)
10+
11+
const (
12+
semverEquals = iota
13+
semverGreater
14+
semverLess
15+
)
16+
17+
func serverInterfaceTestData(argocdVersion string, semverOperator int) ServerInterface {
18+
19+
v, err := semver.NewVersion(argocdVersion)
20+
if err != nil {
21+
panic(err)
22+
}
23+
incPatch := rand.Int63n(100)
24+
incMinor := rand.Int63n(100)
25+
incMajor := rand.Int63n(100)
26+
27+
switch semverOperator {
28+
case semverEquals:
29+
case semverGreater:
30+
if v, err = semver.NewVersion(
31+
fmt.Sprintf("%d.%d.%d",
32+
v.Major()+incMajor,
33+
v.Minor()+incMinor,
34+
v.Patch()+incPatch,
35+
)); err != nil {
36+
panic(err)
37+
}
38+
39+
case semverLess:
40+
if v, err = semver.NewVersion(
41+
fmt.Sprintf("%d.%d.%d",
42+
v.Major()-incMajor%v.Major(),
43+
v.Minor()-incMinor%v.Minor(),
44+
v.Patch()-incPatch%v.Patch(),
45+
)); err != nil {
46+
panic(err)
47+
}
48+
default:
49+
panic("unsupported semver test semverOperator")
50+
}
51+
52+
vm := &version.VersionMessage{
53+
Version: v.String(),
54+
}
55+
return ServerInterface{
56+
ApiClient: nil,
57+
ServerVersion: v,
58+
ServerVersionMessage: vm,
59+
}
60+
}
61+
62+
func TestServerInterface_isFeatureSupported(t *testing.T) {
63+
type args struct {
64+
feature int
65+
}
66+
tests := []struct {
67+
name string
68+
fields ServerInterface
69+
args args
70+
want bool
71+
wantErr bool
72+
}{
73+
{
74+
name: "featureTokenID-1.5.3",
75+
fields: serverInterfaceTestData("1.5.3", semverEquals),
76+
args: args{feature: featureTokenIDs},
77+
want: true,
78+
wantErr: false,
79+
},
80+
{
81+
name: "featureTokenID-1.5.3+",
82+
fields: serverInterfaceTestData("1.5.3", semverGreater),
83+
args: args{feature: featureTokenIDs},
84+
want: true,
85+
wantErr: false,
86+
},
87+
{
88+
name: "featureTokenID-1.5.3-",
89+
fields: serverInterfaceTestData("1.5.3", semverLess),
90+
args: args{feature: featureTokenIDs},
91+
want: false,
92+
wantErr: false,
93+
},
94+
}
95+
for _, tt := range tests {
96+
t.Run(tt.name, func(t *testing.T) {
97+
p := ServerInterface{
98+
ApiClient: tt.fields.ApiClient,
99+
ServerVersion: tt.fields.ServerVersion,
100+
ServerVersionMessage: tt.fields.ServerVersionMessage,
101+
}
102+
got, err := p.isFeatureSupported(tt.args.feature)
103+
if (err != nil) != tt.wantErr {
104+
t.Errorf("isFeatureSupported() error = %v, wantErr %v", err, tt.wantErr)
105+
return
106+
}
107+
if got != tt.want {
108+
t.Errorf("isFeatureSupported() got = %v, want %v", got, tt.want)
109+
}
110+
})
111+
}
112+
}

argocd/provider.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package argocd
22

33
import (
44
"context"
5+
"fmt"
6+
"github.com/Masterminds/semver"
57
argoCDApiClient "github.com/argoproj/argo-cd/pkg/apiclient"
68
"github.com/argoproj/argo-cd/pkg/apiclient/session"
79
"github.com/argoproj/argo-cd/util"
10+
"github.com/golang/protobuf/ptypes/empty"
811
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
912
"github.com/hashicorp/terraform-plugin-sdk/terraform"
1013
)
@@ -165,6 +168,31 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
165168
}
166169
}
167170

168-
client, err := argoCDApiClient.NewClient(&opts)
169-
return client, err
171+
apiClient, err := argoCDApiClient.NewClient(&opts)
172+
if err != nil {
173+
return nil, err
174+
}
175+
// Get API version
176+
acCloser, versionClient, err := apiClient.NewVersionClient()
177+
if err != nil {
178+
return nil, err
179+
}
180+
defer util.Close(acCloser)
181+
182+
serverVersionMessage, err := versionClient.Version(context.Background(), &empty.Empty{})
183+
if err != nil {
184+
return nil, err
185+
}
186+
if serverVersionMessage == nil {
187+
return nil, fmt.Errorf("could not get server version information")
188+
}
189+
serverVersion, err := semver.NewVersion(serverVersionMessage.Version)
190+
if err != nil {
191+
return nil, fmt.Errorf("could not parse server semantic version: %s", serverVersionMessage.Version)
192+
}
193+
194+
return ServerInterface{
195+
apiClient,
196+
serverVersion,
197+
serverVersionMessage}, err
170198
}

argocd/resource_argocd_project.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
argoCDApiClient "github.com/argoproj/argo-cd/pkg/apiclient"
87
argoCDProject "github.com/argoproj/argo-cd/pkg/apiclient/project"
98
argoCDAppv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
109
"github.com/argoproj/argo-cd/util"
@@ -35,8 +34,10 @@ func resourceArgoCDProjectCreate(d *schema.ResourceData, meta interface{}) error
3534
if err != nil {
3635
return err
3736
}
38-
client := meta.(argoCDApiClient.Client)
39-
closer, c, err := client.NewProjectClient()
37+
38+
server := meta.(ServerInterface)
39+
apiClient := server.ApiClient
40+
closer, c, err := apiClient.NewProjectClient()
4041
if err != nil {
4142
return err
4243
}
@@ -81,8 +82,9 @@ func resourceArgoCDProjectCreate(d *schema.ResourceData, meta interface{}) error
8182
}
8283

8384
func resourceArgoCDProjectRead(d *schema.ResourceData, meta interface{}) error {
84-
client := meta.(argoCDApiClient.Client)
85-
closer, c, err := client.NewProjectClient()
85+
server := meta.(ServerInterface)
86+
apiClient := server.ApiClient
87+
closer, c, err := apiClient.NewProjectClient()
8688
if err != nil {
8789
return err
8890
}
@@ -123,8 +125,10 @@ func resourceArgoCDProjectUpdate(d *schema.ResourceData, meta interface{}) error
123125
if err != nil {
124126
return err
125127
}
126-
client := meta.(argoCDApiClient.Client)
127-
closer, c, err := client.NewProjectClient()
128+
129+
server := meta.(ServerInterface)
130+
apiClient := server.ApiClient
131+
closer, c, err := apiClient.NewProjectClient()
128132
if err != nil {
129133
return err
130134
}
@@ -167,8 +171,9 @@ func resourceArgoCDProjectUpdate(d *schema.ResourceData, meta interface{}) error
167171
}
168172

169173
func resourceArgoCDProjectDelete(d *schema.ResourceData, meta interface{}) error {
170-
client := meta.(argoCDApiClient.Client)
171-
closer, c, err := client.NewProjectClient()
174+
server := meta.(ServerInterface)
175+
apiClient := server.ApiClient
176+
closer, c, err := apiClient.NewProjectClient()
172177
if err != nil {
173178
return err
174179
}

argocd/resource_argocd_project_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func TestAccArgoCDProject(t *testing.T) {
5555
// Check with the same name for rapid project recreation robustness
5656
{
5757
Config: testAccArgoCDProjectSimple(name),
58-
Check: resource.ComposeAggregateTestCheckFunc(
58+
Check: resource.ComposeTestCheckFunc(
5959
resource.TestCheckResourceAttrSet(
6060
"argocd_project.simple",
6161
"metadata.0.uid",
@@ -78,7 +78,7 @@ func TestAccArgoCDProject_tokensCoexistence(t *testing.T) {
7878
"test-acc-"+acctest.RandString(10),
7979
4,
8080
),
81-
Check: resource.ComposeAggregateTestCheckFunc(
81+
Check: resource.ComposeTestCheckFunc(
8282
resource.TestCheckResourceAttrSet(
8383
"argocd_project.coexistence",
8484
"metadata.0.uid",

0 commit comments

Comments
 (0)