• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / deployments / 1197570064

01 Mar 2024 06:24PM UTC coverage: 52.222% (-28.4%) from 80.645%
1197570064

Pull #998

gitlab-ci

web-flow
chore: bump github.com/Azure/azure-sdk-for-go/sdk/azcore

Bumps [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) from 1.9.1 to 1.10.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.9.1...sdk/azcore/v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azcore
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #998: chore: bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.9.1 to 1.10.0

5218 of 9992 relevant lines covered (52.22%)

0.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

10.58
/client/workflows/client.go
1
// Copyright 2023 Northern.tech AS
2
//
3
//        Licensed under the Apache License, Version 2.0 (the "License");
4
//        you may not use this file except in compliance with the License.
5
//        You may obtain a copy of the License at
6
//
7
//            http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//        Unless required by applicable law or agreed to in writing, software
10
//        distributed under the License is distributed on an "AS IS" BASIS,
11
//        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//        See the License for the specific language governing permissions and
13
//        limitations under the License.
14

15
package workflows
16

17
import (
18
        "bytes"
19
        "context"
20
        "encoding/json"
21
        "io"
22
        "net/http"
23
        "strings"
24
        "time"
25

26
        "github.com/mendersoftware/go-lib-micro/config"
27
        "github.com/mendersoftware/go-lib-micro/identity"
28
        "github.com/mendersoftware/go-lib-micro/log"
29
        "github.com/mendersoftware/go-lib-micro/requestid"
30
        "github.com/mendersoftware/go-lib-micro/rest_utils"
31
        "github.com/pkg/errors"
32

33
        dconfig "github.com/mendersoftware/deployments/config"
34
        "github.com/mendersoftware/deployments/model"
35
)
36

37
const (
38
        healthURL                          = "/api/v1/health"
39
        generateArtifactURL                = "/api/v1/workflow/generate_artifact"
40
        reindexReportingURL                = "/api/v1/workflow/reindex_reporting"
41
        reindexReportingDeploymentURL      = "/api/v1/workflow/reindex_reporting_deployment"
42
        reindexReportingDeploymentBatchURL = "/api/v1/workflow/reindex_reporting_deployment/batch"
43
        defaultTimeout                     = 5 * time.Second
44
)
45

46
type DeviceDeploymentShortInfo struct {
47
        ID           string
48
        DeviceID     string
49
        DeploymentID string
50
}
51

52
// Client is the workflows client
53
//
54
//go:generate ../../utils/mockgen.sh
55
type Client interface {
56
        CheckHealth(ctx context.Context) error
57
        StartGenerateArtifact(
58
                ctx context.Context,
59
                multipartGenerateImageMsg *model.MultipartGenerateImageMsg,
60
        ) error
61
        StartReindexReporting(c context.Context, device string) error
62
        StartReindexReportingDeployment(c context.Context, device, deployment, id string) error
63
        StartReindexReportingDeploymentBatch(c context.Context, info []DeviceDeploymentShortInfo) error
64
}
65

66
// NewClient returns a new workflows client
67
func NewClient() Client {
1✔
68
        workflowsBaseURL := config.Config.GetString(dconfig.SettingWorkflows)
1✔
69
        return &client{
1✔
70
                baseURL:    workflowsBaseURL,
1✔
71
                httpClient: &http.Client{Timeout: defaultTimeout},
1✔
72
        }
1✔
73
}
1✔
74

75
type client struct {
76
        baseURL    string
77
        httpClient *http.Client
78
}
79

80
func (c *client) CheckHealth(ctx context.Context) error {
×
81
        var (
×
82
                apiErr rest_utils.ApiError
×
83
                client http.Client
×
84
        )
×
85

×
86
        if ctx == nil {
×
87
                ctx = context.Background()
×
88
        }
×
89
        if _, ok := ctx.Deadline(); !ok {
×
90
                var cancel context.CancelFunc
×
91
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
×
92
                defer cancel()
×
93
        }
×
94
        req, _ := http.NewRequestWithContext(
×
95
                ctx, "GET", c.baseURL+healthURL, nil,
×
96
        )
×
97

×
98
        rsp, err := client.Do(req)
×
99
        if err != nil {
×
100
                return err
×
101
        }
×
102
        defer rsp.Body.Close()
×
103
        if rsp.StatusCode >= http.StatusOK && rsp.StatusCode < 300 {
×
104
                return nil
×
105
        }
×
106
        decoder := json.NewDecoder(rsp.Body)
×
107
        err = decoder.Decode(&apiErr)
×
108
        if err != nil {
×
109
                return errors.Errorf("health check HTTP error: %s", rsp.Status)
×
110
        }
×
111
        return &apiErr
×
112
}
113

114
func (c *client) StartGenerateArtifact(
115
        ctx context.Context,
116
        multipartGenerateImageMsg *model.MultipartGenerateImageMsg,
117
) error {
1✔
118
        l := log.FromContext(ctx)
1✔
119
        l.Debugf("Submit generate artifact: tenantID=%s, artifactID=%s",
1✔
120
                multipartGenerateImageMsg.TenantID, multipartGenerateImageMsg.ArtifactID)
1✔
121

1✔
122
        workflowsURL := c.baseURL + generateArtifactURL
1✔
123

1✔
124
        payload, _ := json.Marshal(multipartGenerateImageMsg)
1✔
125
        req, err := http.NewRequest("POST", workflowsURL, strings.NewReader(string(payload)))
1✔
126
        if err != nil {
1✔
127
                return err
×
128
        }
×
129

130
        res, err := c.httpClient.Do(req)
1✔
131
        if err != nil {
1✔
132
                return errors.Wrapf(err, "failed to start workflow: generate_artifact")
×
133
        }
×
134
        defer res.Body.Close()
1✔
135
        if res.StatusCode != http.StatusCreated {
1✔
136
                body, err := io.ReadAll(res.Body)
×
137
                if err != nil {
×
138
                        body = []byte("<failed to read>")
×
139
                }
×
140
                l.Errorf("generate artifact failed with status %v, response text: %s",
×
141
                        res.StatusCode, body)
×
142
                return errors.New("failed to start workflow: generate_artifact")
×
143
        }
144
        return nil
1✔
145
}
146

147
func (c *client) StartReindexReporting(ctx context.Context, device string) error {
×
148
        if _, ok := ctx.Deadline(); !ok {
×
149
                var cancel context.CancelFunc
×
150
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
×
151
                defer cancel()
×
152
        }
×
153
        tenantID := ""
×
154
        if ident := identity.FromContext(ctx); ident != nil {
×
155
                tenantID = ident.Tenant
×
156
        }
×
157
        wflow := ReindexWorkflow{
×
158
                RequestID: requestid.FromContext(ctx),
×
159
                TenantID:  tenantID,
×
160
                DeviceID:  device,
×
161
                Service:   ServiceDeployments,
×
162
        }
×
163
        payload, _ := json.Marshal(wflow)
×
164
        req, err := http.NewRequestWithContext(ctx,
×
165
                "POST",
×
166
                c.baseURL+reindexReportingURL,
×
167
                bytes.NewReader(payload),
×
168
        )
×
169
        if err != nil {
×
170
                return errors.Wrap(err, "workflows: error preparing HTTP request")
×
171
        }
×
172

173
        req.Header.Set("Content-Type", "application/json")
×
174

×
175
        rsp, err := c.httpClient.Do(req)
×
176
        if err != nil {
×
177
                return errors.Wrap(err, "workflows: failed to trigger reporting reindex")
×
178
        }
×
179
        defer rsp.Body.Close()
×
180

×
181
        if rsp.StatusCode < 300 {
×
182
                return nil
×
183
        }
×
184

185
        if rsp.StatusCode == http.StatusNotFound {
×
186
                workflowURIparts := strings.Split(reindexReportingURL, "/")
×
187
                workflowName := workflowURIparts[len(workflowURIparts)-1]
×
188
                return errors.New(`workflows: workflow "` + workflowName + `" not defined`)
×
189
        }
×
190

191
        return errors.Errorf(
×
192
                "workflows: unexpected HTTP status from workflows service: %s",
×
193
                rsp.Status,
×
194
        )
×
195
}
196

197
func (c *client) StartReindexReportingDeployment(ctx context.Context,
198
        device, deployment, id string) error {
×
199
        if _, ok := ctx.Deadline(); !ok {
×
200
                var cancel context.CancelFunc
×
201
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
×
202
                defer cancel()
×
203
        }
×
204
        tenantID := ""
×
205
        if ident := identity.FromContext(ctx); ident != nil {
×
206
                tenantID = ident.Tenant
×
207
        }
×
208
        wflow := ReindexDeploymentWorkflow{
×
209
                RequestID:    requestid.FromContext(ctx),
×
210
                TenantID:     tenantID,
×
211
                DeviceID:     device,
×
212
                DeploymentID: deployment,
×
213
                ID:           id,
×
214
                Service:      ServiceDeployments,
×
215
        }
×
216
        payload, _ := json.Marshal(wflow)
×
217
        req, err := http.NewRequestWithContext(ctx,
×
218
                "POST",
×
219
                c.baseURL+reindexReportingDeploymentURL,
×
220
                bytes.NewReader(payload),
×
221
        )
×
222
        if err != nil {
×
223
                return errors.Wrap(err, "workflows: error preparing HTTP request")
×
224
        }
×
225

226
        req.Header.Set("Content-Type", "application/json")
×
227

×
228
        rsp, err := c.httpClient.Do(req)
×
229
        if err != nil {
×
230
                return errors.Wrap(err, "workflows: failed to trigger reporting reindex deployment")
×
231
        }
×
232
        defer rsp.Body.Close()
×
233

×
234
        if rsp.StatusCode < 300 {
×
235
                return nil
×
236
        }
×
237

238
        if rsp.StatusCode == http.StatusNotFound {
×
239
                workflowURIparts := strings.Split(reindexReportingDeploymentURL, "/")
×
240
                workflowName := workflowURIparts[len(workflowURIparts)-1]
×
241
                return errors.New(`workflows: workflow "` + workflowName + `" not defined`)
×
242
        }
×
243

244
        return errors.Errorf(
×
245
                "workflows: unexpected HTTP status from workflows service: %s",
×
246
                rsp.Status,
×
247
        )
×
248
}
249

250
func (c *client) StartReindexReportingDeploymentBatch(ctx context.Context,
251
        info []DeviceDeploymentShortInfo) error {
×
252
        if _, ok := ctx.Deadline(); !ok {
×
253
                var cancel context.CancelFunc
×
254
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
×
255
                defer cancel()
×
256
        }
×
257
        tenantID := ""
×
258
        if ident := identity.FromContext(ctx); ident != nil {
×
259
                tenantID = ident.Tenant
×
260
        }
×
261
        reqID := requestid.FromContext(ctx)
×
262
        wflows := make([]ReindexDeploymentWorkflow, len(info))
×
263
        for i, d := range info {
×
264
                wflows[i] = ReindexDeploymentWorkflow{
×
265
                        RequestID:    reqID,
×
266
                        TenantID:     tenantID,
×
267
                        DeviceID:     d.DeviceID,
×
268
                        DeploymentID: d.DeploymentID,
×
269
                        ID:           d.ID,
×
270
                        Service:      ServiceDeployments,
×
271
                }
×
272
        }
×
273
        payload, _ := json.Marshal(wflows)
×
274
        req, err := http.NewRequestWithContext(ctx,
×
275
                "POST",
×
276
                c.baseURL+reindexReportingDeploymentBatchURL,
×
277
                bytes.NewReader(payload),
×
278
        )
×
279
        if err != nil {
×
280
                return errors.Wrap(err, "workflows: error preparing HTTP request")
×
281
        }
×
282

283
        req.Header.Set("Content-Type", "application/json")
×
284

×
285
        rsp, err := c.httpClient.Do(req)
×
286
        if err != nil {
×
287
                return errors.Wrap(err, "workflows: failed to trigger reporting reindex deployment")
×
288
        }
×
289
        defer rsp.Body.Close()
×
290

×
291
        if rsp.StatusCode < 300 {
×
292
                return nil
×
293
        }
×
294

295
        if rsp.StatusCode == http.StatusNotFound {
×
296
                workflowURIparts := strings.Split(reindexReportingDeploymentURL, "/")
×
297
                workflowName := workflowURIparts[len(workflowURIparts)-1]
×
298
                return errors.New(`workflows: workflow "` + workflowName + `" not defined`)
×
299
        }
×
300

301
        return errors.Errorf(
×
302
                "workflows: unexpected HTTP status from workflows service: %s",
×
303
                rsp.Status,
×
304
        )
×
305
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc