Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/v1alpha1/function_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ type FunctionStatus struct {
Runtime string `json:"runtime"`

Conditions []metav1.Condition `json:"conditions,omitempty"`

Git FunctionStatusGit `json:"git,omitempty"`
}

type FunctionStatusGit struct {
ResolvedBranch string `json:"resolvedBranch,omitempty"`
ObservedCommit string `json:"observedCommit,omitempty"`
LastChecked metav1.Time `json:"lastChecked,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
17 changes: 17 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

10 changes: 10 additions & 0 deletions config/crd/bases/functions.dev_functions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ spec:
- type
type: object
type: array
git:
properties:
lastChecked:
format: date-time
type: string
observedCommit:
type: string
resolvedBranch:
type: string
type: object
name:
type: string
runtime:
Expand Down
9 changes: 9 additions & 0 deletions internal/controller/function_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ func (r *FunctionReconciler) reconcile(ctx context.Context, function *v1alpha1.F
}
defer repo.Cleanup()

r.updateFunctionStatusGit(function, repo)

if err := r.ensureDeployment(ctx, function, repo, metadata); err != nil {
return fmt.Errorf("deploying function failed: %w", err)
}
Expand Down Expand Up @@ -442,3 +444,10 @@ func (r *FunctionReconciler) isMiddlewareLatest(ctx context.Context, metadata *f

return latestMiddleware == functionMiddleware, nil
}

// updateFunctionStatusGit updates the functions status with the Git information
func (r *FunctionReconciler) updateFunctionStatusGit(function *v1alpha1.Function, repo *git.Repository) {
function.Status.Git.ResolvedBranch = repo.Branch
function.Status.Git.ObservedCommit = repo.Commit
function.Status.Git.LastChecked = metav1.Now()
}
64 changes: 61 additions & 3 deletions internal/controller/function_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ var _ = Describe("Function Controller", func() {
type reconcileTestCase struct {
spec functionsdevv1alpha1.FunctionSpec
configureMocks func(*funccli.MockManager, *git.MockManager)
statusChecks func(*functionsdevv1alpha1.FunctionStatus)
}

DescribeTable("should successfully reconcile the resource",
Expand All @@ -101,6 +102,14 @@ var _ = Describe("Function Controller", func() {
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())

if tc.statusChecks != nil {
f := &functionsdevv1alpha1.Function{}
err := k8sClient.Get(ctx, typeNamespacedName, f)
Expect(err).NotTo(HaveOccurred())

tc.statusChecks(&f.Status)
}
},
Entry("should deploy when middleware update required", reconcileTestCase{
spec: defaultSpec,
Expand Down Expand Up @@ -149,6 +158,30 @@ var _ = Describe("Function Controller", func() {
gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "main", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil)
},
}),

Entry("should contain the git information in the status", reconcileTestCase{
spec: functionsdevv1alpha1.FunctionSpec{
Repository: functionsdevv1alpha1.FunctionSpecRepository{
URL: "https://github.com/foo/bar",
Branch: "my-branch",
},
},
configureMocks: func(funcMock *funccli.MockManager, gitMock *git.MockManager) {
funcMock.EXPECT().Describe(mock.Anything, functionName, resourceNamespace).Return(functions.Instance{
Middleware: functions.Middleware{
Version: "v1.0.0",
},
}, nil)
funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v1.0.0", nil)
funcMock.EXPECT().GetMiddlewareVersion(mock.Anything, functionName, resourceNamespace).Return("v1.0.0", nil)

gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "my-branch", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}, WithRepoOptionBranch("my-branch"), WithRepoOptionCommit("foobar")), nil)
},
statusChecks: func(status *functionsdevv1alpha1.FunctionStatus) {
Expect(status.Git.ResolvedBranch).Should(Equal("my-branch"))
Expect(status.Git.ObservedCommit).Should(Equal("foobar"))
},
}),
)
})
})
Expand All @@ -165,7 +198,9 @@ func createFunctionResource(name, namespace string, spec functionsdevv1alpha1.Fu
return k8sClient.Create(ctx, &resource)
}

func createTmpGitRepo(function functions.Function) *git.Repository {
type RepoOption func(*git.Repository)

func createTmpGitRepo(function functions.Function, repoOptions ...RepoOption) *git.Repository {
tempDir, err := os.MkdirTemp("", function.Name)
Expect(err).NotTo(HaveOccurred())

Expand All @@ -176,8 +211,31 @@ func createTmpGitRepo(function functions.Function) *git.Repository {
err = os.WriteFile(funcYamlPath, f, 0644)
Expect(err).NotTo(HaveOccurred())

return &git.Repository{
opts := &git.Repository{
CloneDir: tempDir,
SubPath: ".",
}

for _, repoOption := range repoOptions {
repoOption(opts)
}

return opts
}

func WithRepoOptionSubPath(subPath string) RepoOption {
return func(repo *git.Repository) {
repo.SubPath = subPath
}
}

func WithRepoOptionBranch(branch string) RepoOption {
return func(repo *git.Repository) {
repo.Branch = branch
}
}

func WithRepoOptionCommit(commit string) RepoOption {
return func(repo *git.Repository) {
repo.Commit = commit
}
}
9 changes: 8 additions & 1 deletion internal/git/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
return nil, fmt.Errorf("failed to create temporary directory: %w", err)
}

_, err = git.PlainCloneContext(ctx, targetDir, &git.CloneOptions{
repo, err := git.PlainCloneContext(ctx, targetDir, &git.CloneOptions{
URL: repoUrl,
ReferenceName: plumbing.ReferenceName(reference),
SingleBranch: true,
Expand All @@ -55,9 +55,16 @@ func (m *managerImpl) CloneRepository(ctx context.Context, repoUrl, subPath, ref
return nil, fmt.Errorf("failed to clone repo: %w", err)
}

head, err := repo.Head()
if err != nil {
return nil, fmt.Errorf("failed to find head: %w", err)
}

return &Repository{
CloneDir: targetDir,
SubPath: subPath,
Commit: head.Hash().String(),
Branch: reference,
}, nil
}

Expand Down
2 changes: 2 additions & 0 deletions internal/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
type Repository struct {
CloneDir string
SubPath string
Commit string
Branch string
}

func (r *Repository) Path() string {
Expand Down
Loading