mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-14 11:57:59 +00:00
passes 1st e2e test
This commit is contained in:
parent
d45469acc7
commit
f83926c5e6
7 changed files with 435 additions and 3 deletions
|
@ -58,5 +58,7 @@ kubectl run --rm \
|
|||
--env="AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET:-}" \
|
||||
--env="TENANT_ID=${TENANT_ID:-}" \
|
||||
--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"}}' \
|
||||
e2e --image=local/external-secrets-e2e:test
|
||||
|
|
40
e2e/suite/gitlab/gitlab.go
Normal file
40
e2e/suite/gitlab/gitlab.go
Normal file
|
@ -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
e2e/suite/gitlab/provider.go
Normal file
139
e2e/suite/gitlab/provider.go
Normal file
|
@ -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())
|
||||
}
|
|
@ -19,5 +19,6 @@ import (
|
|||
_ "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/gcp"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/gitlab"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/vault"
|
||||
)
|
||||
|
|
32
pkg/provider/gitlab/fake/fake.go
Normal file
32
pkg/provider/gitlab/fake/fake.go
Normal file
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,8 @@ import (
|
|||
"fmt"
|
||||
|
||||
// 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"
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -130,7 +134,7 @@ func (g *Gitlab) NewClient(ctx context.Context, store esv1alpha1.GenericStore, k
|
|||
// Create a new Gitlab client with credentials
|
||||
gitlabClient, err := gitlab.NewClient(string(cliStore.credentials), nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create client: %v", err)
|
||||
log.Logf("Failed to create client: %v", err)
|
||||
}
|
||||
g.client = gitlabClient
|
||||
g.projectID = cliStore.store.ProjectID
|
||||
|
@ -148,6 +152,7 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDat
|
|||
// "protected": false,
|
||||
// "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
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -13,6 +13,219 @@ limitations under the License.
|
|||
*/
|
||||
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
|
||||
|
||||
// func TestCreateGitlabClient(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue