Skip to content

Commit

Permalink
feat(ref): fluxcd#1017 added name field for gitref
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher Paul Haar <[email protected]>
  • Loading branch information
Christopher Paul Haar committed Feb 6, 2023
1 parent ae3a81e commit cb37490
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 9 deletions.
8 changes: 7 additions & 1 deletion api/v1beta2/gitrepository_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,19 @@ type GitRepositoryRef struct {
// +optional
SemVer string `json:"semver,omitempty"`

// Commit SHA to check out, takes precedence over all reference fields.
// Commit SHA to check out, takes precedence over Branch, Tag and SemVer.
//
// When GitRepositorySpec.GitImplementation is set to 'go-git', this can be
// combined with Branch to shallow clone the branch, in which the commit is
// expected to exist.
// +optional
Commit string `json:"commit,omitempty"`

// Name to checkout, takes precedence over all reference fields.
//
// If Name is found for both Branch and Tag, Tag is used
// +optional
Name string `json:"name,omitempty"`
}

// GitRepositoryVerification specifies the Git commit signature verification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,11 +476,16 @@ spec:
is performed."
type: string
commit:
description: "Commit SHA to check out, takes precedence over all
reference fields. \n When GitRepositorySpec.GitImplementation
description: "Commit SHA to check out, takes precedence over Branch,
Tag and SemVer. \n When GitRepositorySpec.GitImplementation
is set to 'go-git', this can be combined with Branch to shallow
clone the branch, in which the commit is expected to exist."
type: string
name:
description: "Name to checkout, takes precedence over all reference
fields. \n If Name is found for both Branch and Tag, Tag is
used"
type: string
semver:
description: SemVer tag expression to check out, takes precedence
over Tag.
Expand Down
53 changes: 47 additions & 6 deletions controllers/gitrepository_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"time"

securejoin "github.com/cyphar/filepath-securejoin"
gogitv5 "github.com/fluxcd/go-git/v5"
gogitv5config "github.com/fluxcd/go-git/v5/config"
"github.com/fluxcd/pkg/runtime/logger"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -771,12 +773,6 @@ func (r *GitRepositoryReconciler) gitCheckout(ctx context.Context,
RecurseSubmodules: obj.Spec.RecurseSubmodules,
ShallowClone: true,
}
if ref := obj.Spec.Reference; ref != nil {
cloneOpts.Branch = ref.Branch
cloneOpts.Commit = ref.Commit
cloneOpts.Tag = ref.Tag
cloneOpts.SemVer = ref.SemVer
}

// Only if the object has an existing artifact in storage, attempt to
// short-circuit clone operation. reconcileStorage has already verified
Expand Down Expand Up @@ -806,6 +802,51 @@ func (r *GitRepositoryReconciler) gitCheckout(ctx context.Context,
}
defer gitReader.Close()

if ref := obj.Spec.Reference; ref != nil {
if ref.Name != "" {
remoteConfig := &gogitv5config.RemoteConfig{
Name: "origin",
URLs: []string{obj.Spec.URL},
}

rem, err := util.NewGitName(remoteConfig)
if err != nil {
e := serror.NewGeneric(
fmt.Errorf("failed to create Git remote: %w", err),
sourcev1.GitOperationFailedReason,
)
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
return nil, e
}
o := gogitv5.ListOptions{}
o.Auth, o.CABundle, err = util.AuthGit(authOpts)
if err != nil {
e := serror.NewGeneric(
fmt.Errorf("failed to auth for Git remote: %w", err),
sourcev1.GitOperationFailedReason,
)
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
return nil, e
}

commitFromName, err := rem.GetGitCommitForName(ref.Name, &o)
if err != nil {
e := serror.NewGeneric(
fmt.Errorf("failed to determine commit from name: %w", err),
sourcev1.GitOperationFailedReason,
)
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
return nil, e
}
cloneOpts.Commit = commitFromName
} else {
cloneOpts.Branch = ref.Branch
cloneOpts.Commit = ref.Commit
cloneOpts.Tag = ref.Tag
cloneOpts.SemVer = ref.SemVer
}
}

commit, err := gitReader.Clone(gitCtx, obj.Spec.URL, cloneOpts)
if err != nil {
e := serror.NewGeneric(
Expand Down
57 changes: 57 additions & 0 deletions internal/util/commit_for_name.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2021 The Flux authors
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 util

import (
"errors"

"github.com/fluxcd/go-git/v5"
"github.com/fluxcd/go-git/v5/config"
"github.com/fluxcd/go-git/v5/storage/memory"
)

type GitName struct {
rem git.Remote
}

func (g *GitName) GetGitCommitForName(name string, o *git.ListOptions) (string, error) {
refs, err := g.rem.List(o)
if err != nil {
return "", err
}

branchCommit := ""
for _, ref := range refs {
if ref.Name().Short() == name {
if ref.Name().IsTag() {
return ref.Hash().String(), nil
} else if ref.Name().IsBranch() {
branchCommit = ref.Hash().String()
}
}
}

if branchCommit != "" {
return branchCommit, nil
}

return "", errors.New("no commit found for name:" + name)
}

func NewGitName(config *config.RemoteConfig) (GitName, error) {
return GitName{rem: *git.NewRemote(memory.NewStorage(), config)}, nil
}
60 changes: 60 additions & 0 deletions internal/util/gogitv5_transport_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
Copyright 2021 The Flux authors
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 util

import (
"github.com/fluxcd/go-git/v5/plumbing/transport"
"github.com/fluxcd/go-git/v5/plumbing/transport/http"
gogit "github.com/fluxcd/go-git/v5/plumbing/transport/ssh"
git "github.com/fluxcd/pkg/git"
"golang.org/x/crypto/ssh"
)

func AuthGit(authOpts *git.AuthOptions) (transport.AuthMethod, []byte, error) {

if authOpts.Transport == git.HTTPS {
if authOpts.BearerToken != "" {
return &http.TokenAuth{
Token: authOpts.BearerToken,
}, authOpts.CAFile, nil
}
return &http.BasicAuth{
Username: authOpts.Username,
Password: authOpts.Password,
}, authOpts.CAFile, nil
}

if authOpts.Transport == git.SSH {
if authOpts.Identity != nil {
var signer ssh.Signer
if authOpts.Password != "" {
var err error
signer, err = ssh.ParsePrivateKeyWithPassphrase([]byte(authOpts.Identity), []byte(authOpts.Password))
if err != nil {
return nil, nil, err
}
}
//ToDo(haarchri): ssh: must specify HostKeyCallback"
return &gogit.PublicKeys{
User: "git",
Signer: signer,
}, authOpts.CAFile, nil
}
}

return nil, nil, nil
}

0 comments on commit cb37490

Please sign in to comment.