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

mendersoftware / iot-manager / 1401702106

05 Aug 2024 08:32PM UTC coverage: 87.577%. Remained the same
1401702106

push

gitlab-ci

web-flow
Merge pull request #295 from mendersoftware/dependabot/docker/docker-dependencies-03b04ac819

chore: bump golang from 1.22.4-alpine3.19 to 1.22.5-alpine3.19 in the docker-dependencies group

3264 of 3727 relevant lines covered (87.58%)

11.44 hits per line

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

100.0
/client/workflows/client.go
1
// Copyright 2022 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
        "net/http"
22
        "strings"
23
        "time"
24

25
        "github.com/mendersoftware/go-lib-micro/identity"
26
        "github.com/mendersoftware/go-lib-micro/requestid"
27
        "github.com/mendersoftware/go-lib-micro/rest.utils"
28
        "github.com/pkg/errors"
29

30
        common "github.com/mendersoftware/iot-manager/client"
31
)
32

33
const (
34
        URICheckHealth     = "/api/v1/health"
35
        URIProvisionDevice = "/api/v1/workflow/provision_external_device"
36
)
37

38
const (
39
        defaultTimeout = time.Duration(10) * time.Second
40
)
41

42
// Client is the workflows client
43
//
44
//go:generate ../../utils/mockgen.sh
45
type Client interface {
46
        CheckHealth(ctx context.Context) error
47
        ProvisionExternalDevice(ctx context.Context, devID string, config map[string]string) error
48
}
49

50
type Options struct {
51
        Client *http.Client
52
}
53

54
func NewOptions(opts ...*Options) *Options {
28✔
55
        ret := new(Options)
28✔
56
        for _, opt := range opts {
51✔
57
                if opt == nil {
33✔
58
                        continue
10✔
59
                }
60
                if opt.Client != nil {
26✔
61
                        ret.Client = opt.Client
13✔
62
                }
13✔
63
        }
64
        return ret
28✔
65
}
66

67
func (opts *Options) SetClient(client *http.Client) *Options {
13✔
68
        opts.Client = client
13✔
69
        return opts
13✔
70
}
13✔
71

72
// NewClient returns a new workflows client
73
func NewClient(url string, opts ...*Options) Client {
15✔
74
        opt := NewOptions(opts...)
15✔
75
        if opt.Client == nil {
17✔
76
                opt.Client = new(http.Client)
2✔
77
        }
2✔
78

79
        return &client{
15✔
80
                url:    strings.TrimRight(url, "/"),
15✔
81
                Client: opt.Client,
15✔
82
        }
15✔
83
}
84

85
type client struct {
86
        url string
87
        *http.Client
88
}
89

90
func (c *client) CheckHealth(ctx context.Context) error {
8✔
91
        var (
8✔
92
                apiErr rest.Error
8✔
93
        )
8✔
94

8✔
95
        if ctx == nil {
10✔
96
                ctx = context.Background()
2✔
97
        }
2✔
98
        if _, ok := ctx.Deadline(); !ok {
12✔
99
                var cancel context.CancelFunc
4✔
100
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
4✔
101
                defer cancel()
4✔
102
        }
4✔
103
        req, _ := http.NewRequestWithContext(
8✔
104
                ctx, "GET", c.url+URICheckHealth, nil,
8✔
105
        )
8✔
106

8✔
107
        rsp, err := c.Do(req)
8✔
108
        if err != nil {
10✔
109
                return err
2✔
110
        }
2✔
111
        defer rsp.Body.Close()
6✔
112
        if rsp.StatusCode >= http.StatusOK && rsp.StatusCode < 300 {
8✔
113
                return nil
2✔
114
        }
2✔
115
        decoder := json.NewDecoder(rsp.Body)
4✔
116
        err = decoder.Decode(&apiErr)
4✔
117
        if err != nil {
6✔
118
                return errors.Errorf("health check HTTP error: %s", rsp.Status)
2✔
119
        }
2✔
120
        return &apiErr
2✔
121
}
122

123
func (c *client) ProvisionExternalDevice(
124
        ctx context.Context,
125
        devID string,
126
        config map[string]string,
127
) error {
11✔
128
        if ctx == nil {
13✔
129
                ctx = context.Background()
2✔
130
        }
2✔
131
        if _, ok := ctx.Deadline(); !ok {
22✔
132
                var cancel context.CancelFunc
11✔
133
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
11✔
134
                defer cancel()
11✔
135
        }
11✔
136

137
        var workflow = struct {
11✔
138
                TenantID  string            `json:"tenant_id"`
11✔
139
                DeviceID  string            `json:"device_id"`
11✔
140
                RequestID string            `json:"request_id"`
11✔
141
                Provider  string            `json:"provider"`
11✔
142
                Config    map[string]string `json:"configuration"`
11✔
143
        }{
11✔
144
                DeviceID:  devID,
11✔
145
                RequestID: requestid.FromContext(ctx),
11✔
146
                Config:    config,
11✔
147
                Provider:  "Azure",
11✔
148
        }
11✔
149

11✔
150
        if id := identity.FromContext(ctx); id != nil {
14✔
151
                workflow.TenantID = id.Tenant
3✔
152
        }
3✔
153

154
        b, _ := json.Marshal(workflow)
11✔
155
        req, err := http.NewRequestWithContext(ctx,
11✔
156
                http.MethodPost,
11✔
157
                c.url+URIProvisionDevice,
11✔
158
                bytes.NewReader(b))
11✔
159
        if err != nil {
13✔
160
                return errors.Wrap(err, "workflows: failed to prepare request")
2✔
161
        }
2✔
162
        rsp, err := c.Do(req)
9✔
163
        if err != nil {
11✔
164
                return errors.Wrap(err, "workflows: failed to execute request")
2✔
165
        }
2✔
166
        defer rsp.Body.Close()
7✔
167

7✔
168
        if rsp.StatusCode >= 400 {
9✔
169
                return common.NewHTTPError(rsp.StatusCode)
2✔
170
        }
2✔
171
        return nil
5✔
172
}
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