Skip to content

Commit

Permalink
moved slackOrder function into a k8s native job
Browse files Browse the repository at this point in the history
  • Loading branch information
ca7alindev committed Sep 25, 2024
1 parent 94a4a5c commit 58facb3
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 60 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ jobs:
- name: Build and push slack-notify
run: docker build -f internal/slack-notify/Dockerfile . -t ${REGISTRY}/${{ github.repository }}/slack-notify:${SHORT_GITHUB_SHA} && docker push ${REGISTRY}/${{ github.repository }}/slack-notify:${SHORT_GITHUB_SHA}

- name: Build and push slack-order
run: docker build -f internal/slack-order/Dockerfile . -t ${REGISTRY}/${{ github.repository }}/slack-order:${SHORT_GITHUB_SHA} && docker push ${REGISTRY}/${{ github.repository }}/slack-order:${SHORT_GITHUB_SHA}

- name: Build function image
run: docker build . -t ${REGISTRY}/${{ github.repository }}:${SHORT_GITHUB_SHA}

Expand Down
1 change: 1 addition & 0 deletions example/composition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ spec:
providerConfigRef: "kndp-kubernetes-provider-config"
deploymentImage: "ghcr.io/kndpio/function-poll/slack-collector:d7a4b"
cronJobImage: "ghcr.io/kndpio/function-poll/slack-notify:d7a4b"
jobImage: "ghcr.io/kndpio/function-poll/slack-order:d7a4b"
deploymentName: "slack-collector"
serviceAccountName: "slack-collector"
70 changes: 66 additions & 4 deletions fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,73 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
resultText, _ := xr.Resource.GetString("spec.messages.result")

if checkDueOrderTimeAndVoteCount(xr, currentTimestamp, users) {
if d {
f.log.Info("Poll is done")
} else {
if !d {
xr.Resource.SetBool("status.done", true)
slackchannel.SlackOrder(input, api, xr, f.log, resultText)
results, _ := slackchannel.PatchVoters(xr, f.log)
job := composed.Unstructured{
Unstructured: unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "kubernetes.crossplane.io/v1alpha2",
"kind": "Object",
"metadata": map[string]interface{}{
"name": "slack-notify-job",
},
"spec": map[string]interface{}{
"forProvider": map[string]interface{}{
"manifest": map[string]interface{}{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": map[string]interface{}{
"name": "slack-notify-job",
"namespace": "default",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"restartPolicy": "OnFailure",
"serviceAccountName": input.ServiceAccountName,
"containers": []interface{}{
map[string]interface{}{
"name": "poll-container",
"image": input.JobImage,
"env": []interface{}{
map[string]interface{}{
"name": "RESULT_TEXT",
"value": resultText,
},
map[string]interface{}{
"name": "RESULTS",
"value": results,
},
map[string]interface{}{
"name": "POLL_NAME",
"value": pollName,
},
map[string]interface{}{
"name": "POLL_TITLE",
"value": pollTitle,
},
},
"envFrom": []interface{}{
map[string]interface{}{
"secretRef": map[string]interface{}{
"name": secretName,
},
},
},
},
},
},
},
},
},
},
"providerConfigRef": map[string]interface{}{"name": input.ProviderConfigRef},
},
},
},
}
desired[resource.Name(job.GetName())] = &resource.DesiredComposed{Resource: &job}
}
xr.Resource.SetManagedFields(nil)
response.SetDesiredCompositeResource(rsp, xr)
Expand Down
1 change: 1 addition & 0 deletions input/v1beta1/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ type Input struct {
DeploymentImage string `json:"deploymentImage"`
ServiceAccountName string `json:"serviceAccountName"`
CronJobImage string `json:"cronJobImage"`
JobImage string `json:"jobImage"`
}
12 changes: 12 additions & 0 deletions internal/slack-order/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM golang:1.23-alpine as build
LABEL org.opencontainers.image.source=https://github.com/kndpio/function-poll

WORKDIR /build
COPY ./internal/slack-order .
RUN go mod tidy
RUN go build -o slack-order

FROM golang:1.23-alpine
WORKDIR /app
COPY --from=build /build/slack-order /app/
CMD [ "./slack-order" ]
13 changes: 13 additions & 0 deletions internal/slack-order/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module slack-order

go 1.23.1

require github.com/slack-go/slack v0.14.0

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
)
22 changes: 22 additions & 0 deletions internal/slack-order/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/slack-go/slack v0.14.0 h1:6c0UTfbRnvRssZUsZ2qe0Iu07VAMPjRqOa6oX8ewF4k=
github.com/slack-go/slack v0.14.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
50 changes: 50 additions & 0 deletions internal/slack-order/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package main

import (
"fmt"
"os"

"github.com/slack-go/slack"
)

var (
channelId = os.Getenv("SLACK_CHANEL_ID")
token = os.Getenv("SLACK_API_TOKEN")
channelID = os.Getenv("SLACK_CHANEL_ID")
pollName = os.Getenv("POLL_NAME")
pollTitle = os.Getenv("POLL_TITLE")
resultText = os.Getenv("RESULT_TEXT")
results = os.Getenv("RESULTS")
)

// SlackOrder sends an order notification via Slack.
func SlackOrder(api *slack.Client) {

attachment := slack.Attachment{
Color: "#f9a41b",
CallbackID: pollTitle,
Title: pollTitle,
TitleLink: pollTitle,
Text: resultText + results,
MarkdownIn: []string{},
}

channelID, timestamp, err := api.PostMessage(
channelId,
slack.MsgOptionText("", false),
slack.MsgOptionAttachments(attachment),
slack.MsgOptionAsUser(true),
)

if err != nil {
fmt.Println("error sending slack message", "warning", err)
} else {
fmt.Println("message successfully sent to channel", channelID, timestamp)
}

}

func main() {
api := slack.New(token)
SlackOrder(api)
}
67 changes: 11 additions & 56 deletions internal/slackchannel/slackchannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
package slackchannel

import (
"os"
"strconv"
"strings"

"github.com/slack-go/slack"
Expand All @@ -12,12 +10,6 @@ import (

"github.com/crossplane/function-sdk-go/logging"
"github.com/crossplane/function-sdk-go/resource"
"github.com/crossplane/function-template-go/input/v1beta1"
)

var (
channelId = os.Getenv("SLACK_CHANEL_ID")
pollTitle string
)

// Voter represents the structure of an Voter reference.
Expand Down Expand Up @@ -52,14 +44,14 @@ type Poll struct {
} `json:"status"`
}

// UserVoted checks if the user should receive a message based on status
func UserVoted(voters []Voter, userName string) bool {
for _, Voter := range voters {
if Voter.Name == userName {
return Voter.Status == ""
func countUsers(voters []Voter) int {
count := 0
for _, voter := range voters {
if strings.EqualFold(voter.Status, "yes") {
count++
}
}
return true
return count
}

// ProcessSlackMembers gets and process slack members
Expand All @@ -83,51 +75,14 @@ func ProcessSlackMembers(api *slack.Client, channelID string, logger logging.Log
return realUsers, nil
}

func countUsers(voters []Voter) int {
count := 0
for _, voter := range voters {
if strings.EqualFold(voter.Status, "yes") {
count++
}
}
return count
}

// SlackOrder sends an order notification via Slack.
func SlackOrder(input *v1beta1.Input, api *slack.Client, xr *resource.Composite, logger logging.Logger, resultText string) *resource.Composite {
pollTitle, _ = xr.Resource.GetString("spec.title")

// PatchVoters patch status.voters key with an empty array.
func PatchVoters(xr *resource.Composite, logger logging.Logger) (*resource.Composite, int) {
poll := Poll{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(xr.Resource.Object, &poll); err != nil {
logger.Info("error converting Unstructured to Poll:", err)
}
textContent := countUsers(poll.Status.Voters)

attachment := slack.Attachment{
Color: "#f9a41b",
CallbackID: pollTitle,
Title: pollTitle,
TitleLink: pollTitle,
Text: resultText + strconv.Itoa(textContent),
MarkdownIn: []string{},
}

channelID, timestamp, err := api.PostMessage(
channelId,
slack.MsgOptionText("", false),
slack.MsgOptionAttachments(attachment),
slack.MsgOptionAsUser(true),
)

if err != nil {
logger.Info("error sending slack message", "warning", err)
} else {
logger.Info("message successfully sent to channel", channelID, timestamp)
}
voters := countUsers(poll.Status.Voters)
poll.Status.Voters = []Voter{}
xr.Resource.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(&poll)
if err != nil {
logger.Info("error converting Poll to Unstructured:", err)
}
return xr
xr.Resource.Object, _ = runtime.DefaultUnstructuredConverter.ToUnstructured(&poll)
return xr, voters
}

0 comments on commit 58facb3

Please sign in to comment.