diff --git a/harness/cd/approval.go b/harness/cd/approval.go new file mode 100644 index 00000000..775fdb13 --- /dev/null +++ b/harness/cd/approval.go @@ -0,0 +1,141 @@ +package cd + +import ( + "fmt" + + "github.com/harness/harness-go-sdk/harness/cd/graphql" +) + +// Helper type for accessing all application related crud methods +type ApprovalClient struct { + ApiClient *ApiClient +} + +// CRUD +func (ac *ApprovalClient) GetApprovalDetails(applicationId string, executionId string) (*graphql.ApprovalDetailsPayload, error) { + query := &GraphQLQuery{ + Query: fmt.Sprintf(`query($applicationId: String!, $executionId: String!) { + approvalDetails(applicationId: $applicationId, executionId: $executionId) { + approvalDetails { + %s + } + } + }`, approvalDetailsFields), + Variables: map[string]interface{}{ + "applicationId": applicationId, + "executionId": executionId, + }, + } + + res := struct { + ApprovalDetails graphql.ApprovalDetailsPayload + }{} + ac.ApiClient.ExecuteGraphQLQuery(query, &res) + + return &res.ApprovalDetails, nil +} + +func (ac *ApprovalClient) ApproveOrRejectApprovals(input *graphql.ApproveOrRejectApprovalsInput) (*graphql.ApproveOrRejectApprovalsInputPayload, error) { + + query := &GraphQLQuery{ + Query: `mutation approveOrRejectApprovals ($approvalInput: ApproveOrRejectApprovalsInput!) { + approveOrRejectApprovals(input: $approvalInput) + { + success + clientMutationId + } + }`, + Variables: map[string]interface{}{ + "approvalInput": &input, + }, + } + + res := &struct { + ApproveOrRejectApprovalsInputPayload *graphql.ApproveOrRejectApprovalsInputPayload + }{} + err := ac.ApiClient.ExecuteGraphQLQuery(query, &res) + + if err != nil { + return nil, err + } + + return res.ApproveOrRejectApprovalsInputPayload, nil +} + +var approvalDetailsFields = ` +approvalId +approvalType +stepName +stageName +startedAt +triggeredBy { + name + email +} +willExpireAt +... on UserGroupApprovalDetails { + approvers + approvalId + approvalType + stepName + stageName + startedAt + executionId + triggeredBy { + name + email + } + willExpireAt + variables { + name + value + } +} +... on ShellScriptDetails { + approvalId + approvalType + retryInterval + stageName + stepName + startedAt + triggeredBy { + email + name + } + willExpireAt +} +... on SNOWApprovalDetails { + approvalCondition + approvalId + approvalType + currentStatus + rejectionCondition + stageName + startedAt + stepName + ticketType + ticketUrl + triggeredBy { + email + name + } + willExpireAt +} +... on JiraApprovalDetails { + approvalCondition + approvalId + approvalType + currentStatus + issueKey + issueUrl + rejectionCondition + stepName + stageName + startedAt + triggeredBy { + email + name + } + willExpireAt +} +` diff --git a/harness/cd/approval_test.go b/harness/cd/approval_test.go new file mode 100644 index 00000000..517bc27e --- /dev/null +++ b/harness/cd/approval_test.go @@ -0,0 +1,14 @@ +package cd + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestApprovalDetails(t *testing.T) { + c := getClient() + approval, err := c.ApprovalClient.GetApprovalDetails("q_nsFwL5TUq4Jsq00vNGRQ-gf39sw", "ntUxF8b_SRuSWLckvPkODw") + require.NoError(t, err) + require.NotNil(t, approval) +} diff --git a/harness/cd/client.go b/harness/cd/client.go index 5ee7814e..4a160ca9 100644 --- a/harness/cd/client.go +++ b/harness/cd/client.go @@ -46,6 +46,7 @@ type ApiClient struct { UserClient *UserClient TagClient *TagClient TriggerClient *TriggerClient + ApprovalClient *ApprovalClient } func DefaultConfig() *Config { @@ -101,6 +102,7 @@ func NewClient(cfg *Config) (*ApiClient, error) { // API Services c.ApplicationClient = (*ApplicationClient)(&c.common) + c.ApprovalClient = (*ApprovalClient)(&c.common) c.CloudProviderClient = (*CloudProviderClient)(&c.common) c.ConfigAsCodeClient = (*ConfigAsCodeClient)(&c.common) c.ConnectorClient = (*ConnectorClient)(&c.common) diff --git a/harness/cd/graphql/enum_approval_action_types.go b/harness/cd/graphql/enum_approval_action_types.go new file mode 100644 index 00000000..59dc6112 --- /dev/null +++ b/harness/cd/graphql/enum_approval_action_types.go @@ -0,0 +1,20 @@ +package graphql + +type ApprovalActionType string + +var ApprovalActionTypes = struct { + Approve ApprovalActionType + Reject ApprovalActionType +}{ + Approve: "APPROVE", + Reject: "REJECT", +} + +var ApprovalActionTypeList = []string{ + ApprovalActionTypes.Approve.String(), + ApprovalActionTypes.Reject.String(), +} + +func (d ApprovalActionType) String() string { + return string(d) +} diff --git a/harness/cd/graphql/model_approve_or_reject_approvals_input.go b/harness/cd/graphql/model_approve_or_reject_approvals_input.go new file mode 100644 index 00000000..f2d04164 --- /dev/null +++ b/harness/cd/graphql/model_approve_or_reject_approvals_input.go @@ -0,0 +1,11 @@ +package graphql + +type ApproveOrRejectApprovalsInput struct { + Action ApprovalActionType `json:"action,omitempty"` + ApplicationId string `json:"applicationId,omitempty"` + ApprovalId string `json:"approvalId,omitempty"` + ClientMutationId string `json:"clientMutationId,omitempty"` + Comments string `json:"comments,omitempty"` + ExecutionId string `json:"executionId,omitempty"` + VariableInputs []*ApprovalVariable `json:"variableInputs,omitempty"` +} diff --git a/harness/cd/graphql/types.go b/harness/cd/graphql/types.go index fe367ed2..aad72869 100644 --- a/harness/cd/graphql/types.go +++ b/harness/cd/graphql/types.go @@ -847,3 +847,30 @@ type CEClusterHealth struct { LastEventTimestamp float64 `json:"lastEventTimestamp,omitempty"` Messages []string `json:"messages"` } + +type ApprovalVariable struct { + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` +} + +type ApprovalDetailsPayload struct { + ApprovalDetails []*Approval `json:"approvalDetails,omitempty"` +} + +type Approval struct { + ApprovalId string `json:"approvalId,omitempty"` + ApprovalType ApprovalStepType `json:"approvalType,omitempty"` + StepName string `json:"stepName,omitempty"` + StageName string `json:"stageName,omitempty"` + StartedAt *time.Time `json:"startedAt,omitempty"` + TriggeredBy User `json:"triggeredBy,omitempty"` + WillExpireAt *time.Time `json:"willExpireAt,omitempty"` + Approvers []string `json:"approvers,omitempty"` + ExecutionId string `json:"executionId,omitempty"` + Variables []*ApprovalVariable `json:"variables,omitempty"` +} + +type ApproveOrRejectApprovalsInputPayload struct { + ClientMutationId string `json:"clientMutationId,omitempty"` + Success bool `json:"success,omitempty"` +}