1 package create
2
3 import (
4 "context"
5 "errors"
6 "fmt"
7 "regexp"
8
9 "edge-infra.dev/pkg/lib/cli/rags"
10 "edge-infra.dev/pkg/lib/cli/sink"
11 "edge-infra.dev/pkg/lib/gcp/monitoring/dsp/alert"
12 )
13
14 var (
15 patternLabel = regexp.MustCompile(`^([\w\-]+\|[\w\-]+)`)
16 patternProject = regexp.MustCompile(`^ret-edge-(\w+)(-\w+)*`)
17 patternTopic = regexp.MustCompile(`^([\w]+)(-[\w]+)*`)
18 )
19
20 func New() *sink.Command {
21 var (
22 project string
23 policyName string
24 labels string
25 topic string
26 encode = true
27 )
28 cmd := &sink.Command{
29 Use: "create [flags]",
30 Short: "create is used to simulate an incident message to dsp via pubsub",
31 Flags: []*rags.Rag{
32 {
33 Name: "project",
34 Usage: "GCP Project ID where alert policy is located (e.g. ret-edge-dev1-foreman)",
35 Value: &rags.String{Var: &project},
36 Short: "p",
37 Required: true,
38 },
39 {
40 Name: "policyname",
41 Usage: "name of an alert policy",
42 Value: &rags.String{Var: &policyName},
43 Short: "n",
44 Required: true,
45 },
46 {
47 Name: "topic",
48 Usage: "name of the Pub/Sub topic to be used",
49 Value: &rags.String{Var: &topic},
50 Short: "t",
51 Required: true,
52 },
53 {
54 Name: "labels",
55 Usage: "a comma separated list of key|value pairs (separated by |) for labels",
56 Value: &rags.String{Var: &labels},
57 Short: "l",
58 Required: false,
59 },
60 {
61 Name: "encode",
62 Usage: "should the message be base64 encoded (true by default)",
63 Value: &rags.Bool{Var: &encode},
64 Short: "e",
65 Required: false,
66 },
67 },
68 Exec: func(_ context.Context, r sink.Run) error {
69
70 var kvLabels []string
71
72 if len(labels) > 0 {
73
74 kvLabels = alert.SplitLabels(labels)
75 }
76
77 if len(topic) < 1 || !patternTopic.MatchString(topic) {
78 err := errors.New("Pub/Sub topic must be valid and cannot contain spaces")
79 return fmt.Errorf("invalid topic: %w", err)
80 }
81
82 if !ValidateLabels(kvLabels) {
83 err := errors.New("labels need to be a list of key|value pairs separated by commas")
84 return fmt.Errorf("invalid labels: %w", err)
85 }
86
87 if !patternProject.MatchString(project) {
88 err := errors.New("needs to be full name (e.g. ret-edge-dev1-foreman)")
89 return fmt.Errorf("invalid project name: %w", err)
90 }
91
92
93 projectNumber, err := alert.GetProjectNumber(project, r.Log)
94 if err != nil {
95 return fmt.Errorf("failed to get project number: %w", err)
96 }
97
98
99 policy, err := alert.GetAlertPolicy(projectNumber, policyName, r.Log)
100 if err != nil || policy == nil {
101 return fmt.Errorf("failed to get alert policy: %w", err)
102 }
103
104
105 createdIncident, err := alert.CreateIncident(projectNumber, project, kvLabels, policy, r.Log)
106 if err != nil || createdIncident == nil {
107 return fmt.Errorf("failed to create incident: %w", err)
108 }
109
110
111
112 message, err := alert.CreateMessage(*createdIncident, r.Log)
113 if err != nil || message == nil {
114 return fmt.Errorf("failed to create message: %w", err)
115 }
116
117
118
119 responseID, err := alert.PublishMessage(project, message, topic, encode, r.Log)
120 if err != nil || responseID == "" {
121 return fmt.Errorf("failed to publish message: %w", err)
122 }
123 fmt.Printf("published message responseID: %s\n", responseID)
124 return nil
125 },
126 }
127 return cmd
128 }
129
130 func ValidateLabels(labels []string) bool {
131 goodLabel := true
132 for i := 0; i < len(labels); i++ {
133 if !patternLabel.MatchString(labels[i]) {
134 goodLabel = false
135 return goodLabel
136 }
137 }
138 return goodLabel
139 }
140
View as plain text