Skip to content

Commit

Permalink
added end to end tracing for tfbuddy
Browse files Browse the repository at this point in the history
  • Loading branch information
mplachter committed May 1, 2023
1 parent 7128f3e commit fe33056
Show file tree
Hide file tree
Showing 31 changed files with 598 additions and 296 deletions.
4 changes: 3 additions & 1 deletion cmd/tfc_lock.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"context"
"fmt"
"os"

Expand All @@ -14,7 +15,8 @@ var tfcLockCmd = &cobra.Command{
Short: "Lock a Terraform workspace.",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
tfc_utils.LockUnlockWorkspace(tfcToken, tfcWorkspace, true, "Locked from MR")
ctx := context.Background()
tfc_utils.LockUnlockWorkspace(ctx, tfcToken, tfcWorkspace, true, "Locked from MR")
},
PreRunE: func(cmd *cobra.Command, args []string) error {
if tfcWorkspace == "" {
Expand Down
4 changes: 3 additions & 1 deletion cmd/tfc_unlock.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"context"
"fmt"
"os"

Expand All @@ -14,7 +15,8 @@ var tfcUnlockCmd = &cobra.Command{
Short: "Unlock a Terraform workspace.",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
tfc_utils.LockUnlockWorkspace(tfcToken, tfcWorkspace, false, "")
ctx := context.Background()
tfc_utils.LockUnlockWorkspace(ctx, tfcToken, tfcWorkspace, false, "")
},
PreRunE: func(cmd *cobra.Command, args []string) error {
if tfcWorkspace == "" {
Expand Down
41 changes: 30 additions & 11 deletions pkg/gitlab_hooks/comment_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/zapier/tfbuddy/pkg/tfc_trigger"
"github.com/zapier/tfbuddy/pkg/vcs"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
)

// processNoteEvent processes GitLab Webhooks for Note events
Expand All @@ -28,7 +29,7 @@ func (w *GitlabEventWorker) processNoteEvent(ctx context.Context, event vcs.MRCo
opts, err := comment_actions.ParseCommentCommand(event.GetAttributes().GetNote())
if err != nil {
if err == comment_actions.ErrOtherTFTool {
w.postMessageToMergeRequest(event, "Use tfc to interact with tfbuddy")
w.postMessageToMergeRequest(ctx, event, "Use tfc to interact with tfbuddy")
}
if err == comment_actions.ErrNotTFCCommand || err == comment_actions.ErrOtherTFTool {
gitlabWebHookIgnored.WithLabelValues("comment", "not-tfc-command", proj).Inc()
Expand Down Expand Up @@ -56,17 +57,27 @@ func (w *GitlabEventWorker) processNoteEvent(ctx context.Context, event vcs.MRCo
trigger.SetMergeRequestDiscussionID(event.GetAttributes().GetDiscussionID())
}

span.SetAttributes(
attribute.String("agent", opts.Args.Agent),
attribute.String("command", opts.Args.Command),
attribute.String("branch", opts.TriggerOpts.Branch),
attribute.String("commit_sha", opts.TriggerOpts.CommitSHA),
attribute.String("project_name", opts.TriggerOpts.ProjectNameWithNamespace),
attribute.Int("merge_request_iid", opts.TriggerOpts.MergeRequestIID),
attribute.String("vcs_provider", opts.TriggerOpts.VcsProvider),
)

// TODO: support additional commands and arguments (e.g. destroy, refresh, lock, unlock)
// TODO: this should be refactored and be agnostic to the VCS type
switch opts.Args.Command {
case "apply":
log.Info().Msg("Got TFC apply command")
if !w.checkApproval(ctx, event) {
w.postMessageToMergeRequest(event, ":no_entry: Apply failed. Merge Request requires approval.")
w.postMessageToMergeRequest(ctx, event, ":no_entry: Apply failed. Merge Request requires approval.")
return proj, nil
}
if !w.checkForMergeConflicts(ctx, event) {
w.postMessageToMergeRequest(event, ":no_entry: Apply failed. Merge Request has conflicts that need to be resolved.")
w.postMessageToMergeRequest(ctx, event, ":no_entry: Apply failed. Merge Request has conflicts that need to be resolved.")
return proj, nil
}
case "lock":
Expand All @@ -82,13 +93,13 @@ func (w *GitlabEventWorker) processNoteEvent(ctx context.Context, event vcs.MRCo
if tfError == nil && executedWorkspaces != nil {
if len(executedWorkspaces.Errored) > 0 {
for _, failedWS := range executedWorkspaces.Errored {
w.postMessageToMergeRequest(event, fmt.Sprintf(":no_entry: %s could not be run because: %s", failedWS.Name, failedWS.Error))
w.postMessageToMergeRequest(ctx, event, fmt.Sprintf(":no_entry: %s could not be run because: %s", failedWS.Name, failedWS.Error))
}
return proj, nil
}
}
if tfError != nil {
w.postMessageToMergeRequest(event, fmt.Sprintf(":no_entry: could not be run because: %s", tfError.Error()))
w.postMessageToMergeRequest(ctx, event, fmt.Sprintf(":no_entry: could not be run because: %s", tfError.Error()))
}
return proj, tfError

Expand All @@ -100,9 +111,9 @@ func (w *GitlabEventWorker) checkApproval(ctx context.Context, event vcs.MRComme

mrIID := event.GetMR().GetInternalID()
proj := event.GetProject().GetPathWithNamespace()
approvals, err := w.gl.GetMergeRequestApprovals(mrIID, proj)
approvals, err := w.gl.GetMergeRequestApprovals(ctx, mrIID, proj)
if err != nil {
w.postErrorToMergeRequest(event, fmt.Errorf("could not get MergeRequest from GitlabAPI: %v", err))
w.postErrorToMergeRequest(ctx, event, fmt.Errorf("could not get MergeRequest from GitlabAPI: %v", err))
return false
}

Expand All @@ -117,15 +128,19 @@ func (w *GitlabEventWorker) checkForMergeConflicts(ctx context.Context, event vc
proj := event.GetProject().GetPathWithNamespace()
mr, err := w.gl.GetMergeRequest(ctx, mrIID, proj)
if err != nil {
w.postErrorToMergeRequest(event, fmt.Errorf("could not get MergeRequest from GitlabAPI: %v", err))
w.postErrorToMergeRequest(ctx, event, fmt.Errorf("could not get MergeRequest from GitlabAPI: %v", err))
return false
}
// fail if the MR has conflicts only.
return !mr.HasConflicts()
}

func (w *GitlabEventWorker) postMessageToMergeRequest(event vcs.MRCommentEvent, msg string) {
func (w *GitlabEventWorker) postMessageToMergeRequest(ctx context.Context, event vcs.MRCommentEvent, msg string) {
ctx, span := otel.Tracer("GitlabHooks").Start(context.Background(), "postMessageToMergeRequest")
defer span.End()

if err := w.gl.CreateMergeRequestComment(
ctx,
event.GetMR().GetInternalID(),
event.GetProject().GetPathWithNamespace(),
msg,
Expand All @@ -134,6 +149,10 @@ func (w *GitlabEventWorker) postMessageToMergeRequest(event vcs.MRCommentEvent,
}
}

func (w *GitlabEventWorker) postErrorToMergeRequest(event vcs.MRCommentEvent, err error) {
w.postMessageToMergeRequest(event, fmt.Sprintf(":fire: <br> Error: %v", err))
func (w *GitlabEventWorker) postErrorToMergeRequest(ctx context.Context, event vcs.MRCommentEvent, err error) {
ctx, span := otel.Tracer("GitlabHooks").Start(context.Background(), "postErrorToMergeRequest")
defer span.End()
span.RecordError(err)

w.postMessageToMergeRequest(ctx, event, fmt.Sprintf(":fire: <br> Error: %v", err))
}
8 changes: 4 additions & 4 deletions pkg/gitlab_hooks/comment_actions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func TestProcessNoteEventPlanError(t *testing.T) {
defer mockCtrl.Finish()

mockGitClient := mocks.NewMockGitClient(mockCtrl)
mockGitClient.EXPECT().CreateMergeRequestComment(101, "zapier/service-tf-buddy", ":no_entry: could not be run because: something went wrong")
mockGitClient.EXPECT().CreateMergeRequestComment(gomock.Any(), 101, "zapier/service-tf-buddy", ":no_entry: could not be run because: something went wrong")
mockApiClient := mocks.NewMockApiClient(mockCtrl)
mockStreamClient := mocks.NewMockStreamClient(mockCtrl)
mockProject := mocks.NewMockProject(mockCtrl)
Expand Down Expand Up @@ -257,7 +257,7 @@ func TestProcessNoteEventPlanFailedWorkspace(t *testing.T) {
defer mockCtrl.Finish()
testSuite := mocks.CreateTestSuite(mockCtrl, mocks.TestOverrides{}, t)

testSuite.MockGitClient.EXPECT().CreateMergeRequestComment(101, testSuite.MetaData.ProjectNameNS, ":no_entry: service-tf-buddy could not be run because: could not fetch upstream").Return(nil)
testSuite.MockGitClient.EXPECT().CreateMergeRequestComment(gomock.Any(), 101, testSuite.MetaData.ProjectNameNS, ":no_entry: service-tf-buddy could not be run because: could not fetch upstream").Return(nil)

mockLastCommit := mocks.NewMockCommit(mockCtrl)

Expand Down Expand Up @@ -314,8 +314,8 @@ func TestProcessNoteEventPlanFailedMultipleWorkspaces(t *testing.T) {
testSuite := mocks.CreateTestSuite(mockCtrl, mocks.TestOverrides{}, t)

gomock.InOrder(
testSuite.MockGitClient.EXPECT().CreateMergeRequestComment(101, testSuite.MetaData.ProjectNameNS, ":no_entry: service-tf-buddy could not be run because: could not fetch upstream").Return(nil),
testSuite.MockGitClient.EXPECT().CreateMergeRequestComment(101, testSuite.MetaData.ProjectNameNS, ":no_entry: service-tf-buddy-staging could not be run because: workspace has been modified on target branch").Return(nil),
testSuite.MockGitClient.EXPECT().CreateMergeRequestComment(gomock.Any(), 101, testSuite.MetaData.ProjectNameNS, ":no_entry: service-tf-buddy could not be run because: could not fetch upstream").Return(nil),
testSuite.MockGitClient.EXPECT().CreateMergeRequestComment(gomock.Any(), 101, testSuite.MetaData.ProjectNameNS, ":no_entry: service-tf-buddy-staging could not be run because: workspace has been modified on target branch").Return(nil),
)
mockLastCommit := mocks.NewMockCommit(mockCtrl)
mockLastCommit.EXPECT().GetSHA().Return("abvc12345")
Expand Down
8 changes: 4 additions & 4 deletions pkg/mocks/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ func (ts *TestSuite) InitTestSuite() {
ts.MockGitDisc.EXPECT().GetMRNotes().Return([]vcs.MRNote{ts.MockMRNote}).AnyTimes()

ts.MockGitClient.EXPECT().GetMergeRequest(gomock.Any(), ts.MetaData.MRIID, ts.MetaData.ProjectNameNS).Return(ts.MockGitMR, nil).AnyTimes()
ts.MockGitClient.EXPECT().GetMergeRequestModifiedFiles(ts.MetaData.MRIID, ts.MetaData.ProjectNameNS).Return([]string{"main.tf"}, nil).AnyTimes()
ts.MockGitClient.EXPECT().GetRepoFile(ts.MetaData.ProjectNameNS, ".tfbuddy.yaml", ts.MetaData.SourceBranch).Return(ts.MetaData.TFBuddyConfig, nil).AnyTimes()
ts.MockGitClient.EXPECT().CloneMergeRequest(ts.MetaData.ProjectNameNS, gomock.Any(), gomock.Any()).Return(ts.MockGitRepo, nil).AnyTimes()
ts.MockGitClient.EXPECT().CreateMergeRequestDiscussion(ts.MetaData.MRIID, ts.MetaData.ProjectNameNS, &RegexMatcher{regex: regexp.MustCompile("Starting TFC apply for Workspace: `([A-z\\-]){1,}/([A-z\\-]){1,}`.")}).Return(ts.MockGitDisc, nil).AnyTimes()
ts.MockGitClient.EXPECT().GetMergeRequestModifiedFiles(gomock.Any(), ts.MetaData.MRIID, ts.MetaData.ProjectNameNS).Return([]string{"main.tf"}, nil).AnyTimes()
ts.MockGitClient.EXPECT().GetRepoFile(gomock.Any(), ts.MetaData.ProjectNameNS, ".tfbuddy.yaml", ts.MetaData.SourceBranch).Return(ts.MetaData.TFBuddyConfig, nil).AnyTimes()
ts.MockGitClient.EXPECT().CloneMergeRequest(gomock.Any(), ts.MetaData.ProjectNameNS, gomock.Any(), gomock.Any()).Return(ts.MockGitRepo, nil).AnyTimes()
ts.MockGitClient.EXPECT().CreateMergeRequestDiscussion(gomock.Any(), ts.MetaData.MRIID, ts.MetaData.ProjectNameNS, &RegexMatcher{regex: regexp.MustCompile("Starting TFC apply for Workspace: `([A-z\\-]){1,}/([A-z\\-]){1,}`.")}).Return(ts.MockGitDisc, nil).AnyTimes()

ts.MockApiClient.EXPECT().GetWorkspaceByName(gomock.Any(), gomock.Any(), gomock.Any()).Return(&tfe.Workspace{ID: "service-tfbuddy"}, nil).AnyTimes()
ts.MockApiClient.EXPECT().GetTagsByQuery(gomock.Any(), gomock.Any(), "tfbuddylock").AnyTimes()
Expand Down
66 changes: 58 additions & 8 deletions pkg/mocks/mock_runstream.go

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

16 changes: 8 additions & 8 deletions pkg/mocks/mock_tfc_api.go

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

Loading

0 comments on commit fe33056

Please sign in to comment.