Skip to content

Commit

Permalink
feat:Including import credentials for project via secretRef
Browse files Browse the repository at this point in the history
  • Loading branch information
Frank Kouokam committed May 8, 2024
1 parent bc056bb commit 53872da
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 3 deletions.
15 changes: 14 additions & 1 deletion apis/projects/v1alpha1/project_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ type ContainerExpirationPolicyAttributes struct {
NameRegex *string `url:"name_regex,omitempty" json:"name_regex,omitempty"`
}

// Struct representing the secret name and the secret namespace to use when importing a project with secret
type ImportUrlSecretRef struct {
Name string `json:"secretName"`
Namespace string `json:"secretNamespace"`
UsernameKey string `json:"username" default:"username"`
PasswordKey string `json:"password" default:"password"`
}

// ProjectParameters define the desired state of a Gitlab Project
type ProjectParameters struct {
// Set whether or not merge requests can be merged with skipped jobs.
Expand Down Expand Up @@ -244,10 +252,15 @@ type ProjectParameters struct {
// +immutable
GroupWithProjectTemplatesID *int `json:"groupWithProjectTemplatesId,omitempty"`

// URL to import repository from.
// URL to import repository from. Provided credentials in the URL will be overwritten in case a valid secretRef is present in ImportUrlSecretRef.
// +optional
// +kubebuilder:validation:MinLength=11
ImportURL *string `json:"importUrl,omitempty"`

// Secret to use when importing project with secret. Provided credentials in ImportUrl will be overwitten with the credentials found in ImportUrlSecretRel.
// +optional
ImportUrlSecretRef *ImportUrlSecretRef `json:"importUrlSecretRef,omitempty"`

// false by default.
// +optional
// +immutable
Expand Down
20 changes: 20 additions & 0 deletions apis/projects/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 24 additions & 2 deletions package/crds/projects.gitlab.crossplane.io_projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,30 @@ spec:
to be true.
type: integer
importUrl:
description: URL to import repository from.
type: string
description: URL to import repository from. Provided credentials
in the URL will be overwritten in case a valid secretRef is
present in ImportUrlSecretRef.
minLength: 11
type: string
importUrlSecretRef:
description: Secret to use when importing project with secret.
Provided credentials in ImportUrl will be overwitten with the
credentials found in ImportUrlSecretRel.
properties:
password:
type: string
secretName:
type: string
secretNamespace:
type: string
username:
type: string
required:
- password
- secretName
- secretNamespace
- username
type: object
initializeWithReadme:
description: false by default.
type: boolean
Expand Down
60 changes: 60 additions & 0 deletions pkg/controller/projects/projects/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"strconv"

"github.com/xanzy/go-gitlab"
"k8s.io/apimachinery/pkg/types"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
Expand All @@ -41,6 +42,10 @@ import (
"github.com/crossplane-contrib/provider-gitlab/pkg/clients"
"github.com/crossplane-contrib/provider-gitlab/pkg/clients/projects"
"github.com/crossplane-contrib/provider-gitlab/pkg/features"

"net/url"

corev1 "k8s.io/api/core/v1"
)

const (
Expand All @@ -50,6 +55,10 @@ const (
errUpdateFailed = "cannot update Gitlab project"
errDeleteFailed = "cannot delete Gitlab project"
errGetFailed = "cannot retrieve Gitlab project with"
errNoImportSecret = "cannot retrieve secret for import"
errUsernameNotFound = "No username in secret for import project"
errPasswordNotFound = "No password in secret for import project"
errParseUrlFailed = "Could not parse the provided importUrl"
)

// SetupProject adds a controller that reconciles Projects.
Expand Down Expand Up @@ -150,6 +159,57 @@ func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.Ext
return managed.ExternalCreation{}, errors.New(errNotProject)
}

keySecretRef := cr.Spec.ForProvider.ImportUrlSecretRef
importUrl := cr.Spec.ForProvider.ImportURL

// User has provided secret for the import
secretRefIsNotEmpty := keySecretRef != nil && keySecretRef.Namespace != "" && keySecretRef.Name != ""
keysAreNotEmpty := keySecretRef != nil && keySecretRef.PasswordKey != "" && keySecretRef.UsernameKey != ""
importUrlIsNotEmpty := importUrl != nil && *importUrl != ""

if secretRefIsNotEmpty && keysAreNotEmpty && importUrlIsNotEmpty {
// Retrieve secret from k8s
namespacedName := types.NamespacedName{
Namespace: keySecretRef.Namespace,
Name: keySecretRef.Name,
}

secret := &corev1.Secret{}

err := e.kube.Get(ctx, namespacedName, secret)

if err != nil {
return managed.ExternalCreation{}, errors.Wrap(err, errNoImportSecret)
}

// Obtain the password from the secret.
password := string(secret.Data[keySecretRef.PasswordKey])
if password == "" {
return managed.ExternalCreation{}, errors.Wrap(err, errPasswordNotFound)
}

// Obtain the username from the secret.
username := string(secret.Data[keySecretRef.UsernameKey])
if username == "" {
return managed.ExternalCreation{}, errors.Wrap(err, errUsernameNotFound)
}

// manipulate url to add the secret. If secret is already in the url, it should be overridden
// https://username:[email protected]
parsedUrl, err := url.Parse(*importUrl)

if err != nil {
return managed.ExternalCreation{}, errors.Wrap(err, errParseUrlFailed)
}

userInfo := url.UserPassword(username, password)

parsedUrl.User = userInfo

// Override importUrl with the manipulated URL containing the credentials found in ImportSecretRef.
*importUrl = parsedUrl.String()
}

prj, _, err := e.client.CreateProject(
projects.GenerateCreateProjectOptions(cr.Name, &cr.Spec.ForProvider),
gitlab.WithContext(ctx),
Expand Down

0 comments on commit 53872da

Please sign in to comment.