Browse Source

passes 1st e2e test

jabray5 4 years ago
parent
commit
f83926c5e6

+ 2 - 0
e2e/run.sh

@@ -58,5 +58,7 @@ kubectl run --rm \
   --env="AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET:-}" \
   --env="AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET:-}" \
   --env="TENANT_ID=${TENANT_ID:-}" \
   --env="TENANT_ID=${TENANT_ID:-}" \
   --env="VAULT_URL=${VAULT_URL:-}" \
   --env="VAULT_URL=${VAULT_URL:-}" \
+  --env="GITLAB_TOKEN=${GITLAB_TOKEN:-}" \
+  --env="GITLAB_PROJECT_ID=${GITLAB_PROJECT_ID:-}" \
   --overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "external-secrets-e2e"}}' \
   --overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "external-secrets-e2e"}}' \
   e2e --image=local/external-secrets-e2e:test
   e2e --image=local/external-secrets-e2e:test

+ 40 - 0
e2e/suite/gitlab/gitlab.go

@@ -0,0 +1,40 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+limitations under the License.
+*/
+package gitlab
+
+import (
+	"os"
+
+	// nolint
+	. "github.com/onsi/ginkgo"
+	// nolint
+	. "github.com/onsi/ginkgo/extensions/table"
+
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/e2e/suite/common"
+)
+
+var _ = Describe("[gitlab] ", func() {
+	f := framework.New("esogitlab")
+	credentials := os.Getenv("GITLAB_TOKEN")
+	projectID := os.Getenv("GITLAB_PROJECT_ID")
+	prov := newGitlabProvider(f, credentials, projectID)
+
+	DescribeTable("sync secrets", framework.TableFunc(f, prov),
+		Entry(common.SimpleDataSync(f)),
+		// Entry(common.JSONDataWithProperty(f)),
+		// Entry(common.JSONDataFromSync(f)),
+		// Entry(common.NestedJSONWithGJSON(f)),
+		// Entry(common.JSONDataWithTemplate(f)),
+	)
+})

+ 139 - 0
e2e/suite/gitlab/provider.go

@@ -0,0 +1,139 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package gitlab
+
+import (
+	"context"
+
+	// I think I've overwritten the log package I need with the default golang one?
+
+	// nolint
+	. "github.com/onsi/ginkgo"
+
+	// nolint
+	. "github.com/onsi/gomega"
+
+	"github.com/external-secrets/external-secrets/e2e/framework/log"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	gitlab "github.com/xanzy/go-gitlab"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+type gitlabProvider struct {
+	credentials string
+	projectID   string
+	framework   *framework.Framework
+}
+
+func newGitlabProvider(f *framework.Framework, credentials, projectID string) *gitlabProvider {
+	prov := &gitlabProvider{
+		credentials: credentials,
+		projectID:   projectID,
+		framework:   f,
+	}
+	BeforeEach(prov.BeforeEach)
+	return prov
+}
+
+func (s *gitlabProvider) CreateSecret(key, val string) {
+	// ctx := context.Background() -- Don't think we need this here
+	// **Open the client
+	client, err := gitlab.NewClient(s.credentials)
+	Expect(err).ToNot(HaveOccurred())
+	// Open the client**
+
+	// Set variable options
+
+	// Think I need to set below values to passed arguments
+	variable_key := key
+	variable_value := val
+	opt := gitlab.CreateProjectVariableOptions{
+		Key:              &variable_key,
+		Value:            &variable_value,
+		VariableType:     nil,
+		Protected:        nil,
+		Masked:           nil,
+		EnvironmentScope: nil,
+	}
+
+	// Create a variable
+	log.Logf("\n Creating variable on projectID: %s \n", s.projectID)
+	_, _, err = client.ProjectVariables.CreateVariable(s.projectID, &opt)
+
+	Expect(err).ToNot(HaveOccurred())
+	// Versions aren't supported by Gitlab, but we could add
+	// more parameters to test
+}
+
+func (s *gitlabProvider) DeleteSecret(key string) {
+	// ctx := context.Background()
+
+	// **Open a client
+	client, err := gitlab.NewClient(s.credentials)
+	Expect(err).ToNot(HaveOccurred())
+	// Open a client**
+
+	// Delete the secret
+	_, err = client.ProjectVariables.RemoveVariable(s.projectID, key)
+	Expect(err).ToNot(HaveOccurred())
+}
+
+func (s *gitlabProvider) BeforeEach() {
+	By("creating a gitlab variable")
+	gitlabCreds := &v1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "provider-secret",
+			Namespace: s.framework.Namespace.Name,
+		},
+		// Puts access token into StringData
+
+		StringData: map[string]string{
+			"token": s.credentials,
+			"projectID": s.projectID,
+		},
+	}
+	err := s.framework.CRClient.Create(context.Background(), gitlabCreds)
+	Expect(err).ToNot(HaveOccurred())
+
+	// Create a secret store - change these values to match YAML
+	By("creating an secret store for credentials")
+	secretStore := &esv1alpha1.SecretStore{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      s.framework.Namespace.Name,
+			Namespace: s.framework.Namespace.Name,
+		},
+		Spec: esv1alpha1.SecretStoreSpec{
+			Provider: &esv1alpha1.SecretStoreProvider{
+				Gitlab: &esv1alpha1.GitlabProvider{
+					ProjectID: s.projectID,
+					Auth: esv1alpha1.GitlabAuth{
+						SecretRef: esv1alpha1.GitlabSecretRef{
+							AccessToken: esmeta.SecretKeySelector{
+								Name: "provider-secret",
+								Key:  "token",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+
+	err = s.framework.CRClient.Create(context.Background(), secretStore)
+	Expect(err).ToNot(HaveOccurred())
+}

+ 1 - 0
e2e/suite/import.go

@@ -19,5 +19,6 @@ import (
 	_ "github.com/external-secrets/external-secrets/e2e/suite/aws"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/aws"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/azure"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/azure"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/gcp"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/gcp"
+	_ "github.com/external-secrets/external-secrets/e2e/suite/gitlab"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/vault"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/vault"
 )
 )

+ 32 - 0
pkg/provider/gitlab/fake/fake.go

@@ -0,0 +1,32 @@
+package fake
+
+import (
+	"fmt"
+
+	"github.com/IBM/go-sdk-core/core"
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	sm "github.com/xanzy/go-gitlab"
+)
+
+type GitlabMockClient struct {
+	getSecret func(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error)
+}
+
+// Exports the mock client's getSecret function
+func (mc *GitlabMockClient) GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error) {
+	return mc.getSecret(getSecretOptions)
+}
+
+func (mc *GitlabMockClient) WithValue(input *sm.GetSecretOptions, output *sm.GetSecret, err error) {
+	if mc != nil {
+		mc.getSecret = func(paramReq *sm.GetSecretOptions) (*sm.GetSecret, *core.DetailedResponse, error) {
+			// type secretmanagerpb.AccessSecretVersionRequest contains unexported fields
+			// use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp.
+			if !cmp.Equal(paramReq, input, cmpopts.IgnoreUnexported(sm.GetSecret{})) {
+				return nil, nil, fmt.Errorf("unexpected test argument")
+			}
+			return output, nil, err
+		}
+	}
+}

+ 8 - 3
pkg/provider/gitlab/gitlab.go

@@ -19,7 +19,8 @@ import (
 	"fmt"
 	"fmt"
 
 
 	// I think I've overwritten the log package I need with the default golang one?
 	// I think I've overwritten the log package I need with the default golang one?
-	"log"
+	"github.com/external-secrets/external-secrets/e2e/framework/log"
+
 	"os"
 	"os"
 
 
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
@@ -98,7 +99,10 @@ func (c *gClient) setAuth(ctx context.Context) error {
 	if (c.credentials == nil) || (len(c.credentials) == 0) {
 	if (c.credentials == nil) || (len(c.credentials) == 0) {
 		return fmt.Errorf(errMissingSAK)
 		return fmt.Errorf(errMissingSAK)
 	}
 	}
-	c.store.ProjectID = string(credentialsSecret.Data[c.store.ProjectID])
+	// I don't know where ProjectID is being set, but this line breaks it :)
+	// c.store.ProjectID = string(credentialsSecret.Data[c.store.ProjectID])
+
+	log.Logf("\n Set auth with projectID: %s and token: %s \n", c.store.ProjectID, c.store.Auth.SecretRef.AccessToken.Key)
 	return nil
 	return nil
 }
 }
 
 
@@ -130,7 +134,7 @@ func (g *Gitlab) NewClient(ctx context.Context, store esv1alpha1.GenericStore, k
 	// Create a new Gitlab client with credentials
 	// Create a new Gitlab client with credentials
 	gitlabClient, err := gitlab.NewClient(string(cliStore.credentials), nil)
 	gitlabClient, err := gitlab.NewClient(string(cliStore.credentials), nil)
 	if err != nil {
 	if err != nil {
-		log.Fatalf("Failed to create client: %v", err)
+		log.Logf("Failed to create client: %v", err)
 	}
 	}
 	g.client = gitlabClient
 	g.client = gitlabClient
 	g.projectID = cliStore.store.ProjectID
 	g.projectID = cliStore.store.ProjectID
@@ -148,6 +152,7 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDat
 	// 	"protected": false,
 	// 	"protected": false,
 	// 	"masked": true
 	// 	"masked": true
 	// }
 	// }
+	log.Logf("\n Getting variable with projectID: %s and key: %s \n", g.projectID, ref.Key)
 	data, _, err := g.client.ProjectVariables.GetVariable(g.projectID, ref.Key, nil) //Optional 'filter' parameter could be added later
 	data, _, err := g.client.ProjectVariables.GetVariable(g.projectID, ref.Key, nil) //Optional 'filter' parameter could be added later
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err

+ 213 - 0
pkg/provider/gitlab/gitlab_test.go

@@ -13,6 +13,219 @@ limitations under the License.
 */
 */
 package gitlab
 package gitlab
 
 
+import (
+	"context"
+	"fmt"
+	"strings"
+	"testing"
+
+	utilpointer "k8s.io/utils/pointer"
+
+	"github.com/IBM/go-sdk-core/core"
+	gitlab "github.com/xanzy/go-gitlab"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	fakegitlab "github.com/external-secrets/external-secrets/pkg/provider/gitlab/fake"
+)
+
+type secretManagerTestCase struct {
+	mockClient     *fakegitlab.GitlabMockClient
+	apiInput       *gitlab.ListProjectVariablesOptions
+	apiOutput      *gitlab.ProjectVariable
+	ref            *esv1alpha1.ExternalSecretDataRemoteRef
+	serviceURL     *string
+	apiErr         error
+	expectError    string
+	expectedSecret string
+	// for testing secretmap
+	expectedData map[string][]byte
+}
+
+func makeValidSecretManagerTestCase() *secretManagerTestCase {
+	smtc := secretManagerTestCase{
+		mockClient:     &fakegitlab.GitlabMockClient{},
+		apiInput:       makeValidAPIInput(),
+		ref:            makeValidRef(),
+		apiOutput:      makeValidAPIOutput(),
+		serviceURL:     nil,
+		apiErr:         nil,
+		expectError:    "",
+		expectedSecret: "",
+		expectedData:   map[string][]byte{},
+	}
+	smtc.mockClient.WithValue(smtc.apiInput, smtc.apiOutput, smtc.apiErr)
+	return &smtc
+}
+
+func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
+	return &esv1alpha1.ExternalSecretDataRemoteRef{
+		Key:     "test-secret",
+		Version: "default",
+	}
+}
+
+func makeValidAPIInput() *gitlab.ProjectVariable {
+	return &gitlab.CreateProjectVariableOptions{
+		VariableType: core.StringPtr(gitlab.),
+		ID:         utilpointer.StringPtr("test-secret"),
+	}
+}
+
+func makeValidAPIOutput() *sm.GetSecret {
+	secretData := make(map[string]interface{})
+	secretData["payload"] = ""
+
+	return &gitlab.GetSecret{
+		Resources: []gitlab.SecretResourceIntf{
+			&gitlab.SecretResource{
+				Type:       utilpointer.StringPtr("testytype"),
+				Name:       utilpointer.StringPtr("testyname"),
+				SecretData: secretData,
+			},
+		},
+	}
+}
+
+func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase {
+	smtc := makeValidSecretManagerTestCase()
+	for _, fn := range tweaks {
+		fn(smtc)
+	}
+	smtc.mockClient.WithValue(smtc.apiInput, smtc.apiOutput, smtc.apiErr)
+	return smtc
+}
+
+// This case can be shared by both GetSecret and GetSecretMap tests.
+// bad case: set apiErr.
+var setAPIErr = func(smtc *secretManagerTestCase) {
+	smtc.apiErr = fmt.Errorf("oh no")
+	smtc.expectError = "oh no"
+}
+
+var setNilMockClient = func(smtc *secretManagerTestCase) {
+	smtc.mockClient = nil
+	smtc.expectError = errUninitalizedIBMProvider
+}
+
+// test the sm<->gcp interface
+// make sure correct values are passed and errors are handled accordingly.
+func TestIBMSecretManagerGetSecret(t *testing.T) {
+	secretData := make(map[string]interface{})
+	secretValue := "changedvalue"
+	secretData["payload"] = secretValue
+	// good case: default version is set
+	// key is passed in, output is sent back
+	setSecretString := func(smtc *secretManagerTestCase) {
+		resources := []gitlab.SecretResourceIntf{
+			&gitlab.SecretResource{
+				Type:       utilpointer.StringPtr("testytype"),
+				Name:       utilpointer.StringPtr("testyname"),
+				SecretData: secretData,
+			}}
+
+		smtc.apiOutput.Resources = resources
+		smtc.expectedSecret = secretValue
+	}
+
+	// good case: custom version set
+	setCustomKey := func(smtc *secretManagerTestCase) {
+		resources := []gitlab.SecretResourceIntf{
+			&gitlab.SecretResource{
+				Type:       utilpointer.StringPtr("testytype"),
+				Name:       utilpointer.StringPtr("testyname"),
+				SecretData: secretData,
+			}}
+		smtc.ref.Key = "testyname"
+		smtc.apiInput.ID = utilpointer.StringPtr("testyname")
+		smtc.apiOutput.Resources = resources
+		smtc.expectedSecret = secretValue
+	}
+
+	successCases := []*secretManagerTestCase{
+		makeValidSecretManagerTestCase(),
+		makeValidSecretManagerTestCaseCustom(setSecretString),
+		makeValidSecretManagerTestCaseCustom(setCustomKey),
+		makeValidSecretManagerTestCaseCustom(setAPIErr),
+		makeValidSecretManagerTestCaseCustom(setNilMockClient),
+	}
+
+	sm := Gitlab{}
+	for k, v := range successCases {
+		sm.client = v.mockClient
+		out, err := sm.GetSecret(context.Background(), *v.ref)
+		if !ErrorContains(err, v.expectError) {
+			t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
+		}
+		if string(out) != v.expectedSecret {
+			t.Errorf("[%d] unexpected secret: expected %s, got %s", k, v.expectedSecret, string(out))
+		}
+	}
+}
+
+// func TestGetSecretMap(t *testing.T) {
+// 	// good case: default version & deserialization
+// 	setDeserialization := func(smtc *secretManagerTestCase) {
+// 		secretData := make(map[string]interface{})
+// 		secretValue := `{"foo":"bar"}`
+// 		secretData["payload"] = secretValue
+// 		resources := []sm.SecretResourceIntf{
+// 			&sm.SecretResource{
+// 				Type:       utilpointer.StringPtr("testytype"),
+// 				Name:       utilpointer.StringPtr("testyname"),
+// 				SecretData: secretData,
+// 			}}
+// 		smtc.apiOutput.Resources = resources
+// 		smtc.expectedData["foo"] = []byte("bar")
+// 	}
+
+// 	// bad case: invalid json
+// 	setInvalidJSON := func(smtc *secretManagerTestCase) {
+// 		secretData := make(map[string]interface{})
+
+// 		secretData["payload"] = `-----------------`
+
+// 		resources := []sm.SecretResourceIntf{
+// 			&sm.SecretResource{
+// 				Type:       utilpointer.StringPtr("testytype"),
+// 				Name:       utilpointer.StringPtr("testyname"),
+// 				SecretData: secretData,
+// 			}}
+
+// 		smtc.apiOutput.Resources = resources
+
+// 		smtc.expectError = "unable to unmarshal secret: invalid character '-' in numeric literal"
+// 	}
+
+// 	successCases := []*secretManagerTestCase{
+// 		makeValidSecretManagerTestCaseCustom(setDeserialization),
+// 		makeValidSecretManagerTestCaseCustom(setInvalidJSON),
+// 		makeValidSecretManagerTestCaseCustom(setNilMockClient),
+// 		makeValidSecretManagerTestCaseCustom(setAPIErr),
+// 	}
+
+// 	sm := providerIBM{}
+// 	for k, v := range successCases {
+// 		sm.IBMClient = v.mockClient
+// 		out, err := sm.GetSecretMap(context.Background(), *v.ref)
+// 		if !ErrorContains(err, v.expectError) {
+// 			t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
+// 		}
+// 		if err == nil && !reflect.DeepEqual(out, v.expectedData) {
+// 			t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", k, v.expectedData, out)
+// 		}
+// 	}
+// }
+
+func ErrorContains(out error, want string) bool {
+	if out == nil {
+		return want == ""
+	}
+	if want == "" {
+		return false
+	}
+	return strings.Contains(out.Error(), want)
+}
+
 // NOT WORKING CURRENTLY
 // NOT WORKING CURRENTLY
 
 
 // func TestCreateGitlabClient(t *testing.T) {
 // func TestCreateGitlabClient(t *testing.T) {