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

mendersoftware / deployments / 843450222

pending completion
843450222

Pull #854

gitlab-ci

Alf-Rune Siqveland
chore: Add `--throttle` flag to `propagate-reporting` command
Pull Request #854: chore: Add `--throttle` flag to `propagate-reporting` command

8 of 11 new or added lines in 1 file covered. (72.73%)

434 existing lines in 4 files now uncovered.

6943 of 8758 relevant lines covered (79.28%)

70.43 hits per line

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

63.64
/client/inventory/client.go
1
// Copyright 2021 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 inventory
16

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

25
        "github.com/mendersoftware/go-lib-micro/config"
26
        "github.com/mendersoftware/go-lib-micro/log"
27
        "github.com/mendersoftware/go-lib-micro/rest_utils"
28
        "github.com/pkg/errors"
29

30
        dconfig "github.com/mendersoftware/deployments/config"
31
        "github.com/mendersoftware/deployments/model"
32
)
33

34
const (
35
        healthURL          = "/api/internal/v1/inventory/health"
36
        searchURL          = "/api/internal/v2/inventory/tenants/:tenantId/filters/search"
37
        getDeviceGroupsURL = "/api/internal/v1/inventory/tenants/:tenantId/devices/:deviceId/groups"
38

39
        defaultTimeout = 5 * time.Second
40

41
        hdrTotalCount = "X-Total-Count"
42
)
43

44
// Errors
45
var (
46
        ErrFilterNotFound = errors.New("Filter with given ID not found in the inventory.")
47
        ErrDevNotFound    = errors.New("Device with given ID not found in the inventory.")
48
)
49

50
// Client is the inventory client
51
//go:generate ../../utils/mockgen.sh
52
type Client interface {
53
        CheckHealth(ctx context.Context) error
54
        Search(
55
                ctx context.Context,
56
                tenantId string,
57
                searchParams model.SearchParams,
58
        ) ([]model.InvDevice, int, error)
59
        GetDeviceGroups(ctx context.Context, tenantId, deviceId string) ([]string, error)
60
}
61

62
// NewClient returns a new inventory client
63
func NewClient() Client {
5✔
64
        var timeout time.Duration
5✔
65
        baseURL := config.Config.GetString(dconfig.SettingInventoryAddr)
5✔
66
        timeoutStr := config.Config.GetString(dconfig.SettingInventoryTimeout)
5✔
67

5✔
68
        t, err := strconv.Atoi(timeoutStr)
5✔
69
        if err != nil {
9✔
70
                timeout = defaultTimeout
4✔
71
        } else {
5✔
72
                timeout = time.Duration(t) * time.Second
1✔
73
        }
1✔
74

75
        return &client{
5✔
76
                baseURL:    baseURL,
5✔
77
                httpClient: &http.Client{Timeout: timeout},
5✔
78
        }
5✔
79
}
80

81
type client struct {
82
        baseURL    string
83
        httpClient *http.Client
84
}
85

86
func (c *client) CheckHealth(ctx context.Context) error {
8✔
87
        var (
8✔
88
                apiErr rest_utils.ApiError
8✔
89
                client http.Client
8✔
90
        )
8✔
91

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

8✔
104
        rsp, err := client.Do(req)
8✔
105
        if err != nil {
10✔
106
                return err
2✔
107
        }
2✔
108
        defer rsp.Body.Close()
6✔
109

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

121
func (c *client) Search(
122
        ctx context.Context,
123
        tenantId string,
124
        searchParams model.SearchParams,
UNCOV
125
) ([]model.InvDevice, int, error) {
×
126
        l := log.FromContext(ctx)
×
127
        l.Debugf("Search")
×
128

×
129
        repl := strings.NewReplacer(":tenantId", tenantId)
×
130
        url := c.baseURL + repl.Replace(searchURL)
×
131

×
132
        payload, _ := json.Marshal(searchParams)
×
133
        req, err := http.NewRequest("POST", url, strings.NewReader(string(payload)))
×
134
        if err != nil {
×
135
                return nil, -1, err
×
136
        }
×
137
        req.Header.Set("Content-Type", "application/json")
×
138

×
139
        rsp, err := c.httpClient.Do(req)
×
140
        if err != nil {
×
141
                return nil, -1, errors.Wrap(err, "search devices request failed")
×
142
        }
×
143
        defer rsp.Body.Close()
×
144

×
145
        if rsp.StatusCode != http.StatusOK {
×
146
                return nil, -1, errors.Errorf(
×
147
                        "search devices request failed with unexpected status %v",
×
148
                        rsp.StatusCode,
×
149
                )
×
150
        }
×
151

UNCOV
152
        devs := []model.InvDevice{}
×
153
        if err := json.NewDecoder(rsp.Body).Decode(&devs); err != nil {
×
154
                return nil, -1, errors.Wrap(err, "error parsing search devices response")
×
155
        }
×
156

UNCOV
157
        totalCountStr := rsp.Header.Get(hdrTotalCount)
×
158
        totalCount, err := strconv.Atoi(totalCountStr)
×
159
        if err != nil {
×
160
                return nil, -1, errors.Wrap(err, "error parsing "+hdrTotalCount+" header")
×
161
        }
×
162

UNCOV
163
        return devs, totalCount, nil
×
164
}
165

166
func (c *client) GetDeviceGroups(ctx context.Context, tenantId, deviceId string) ([]string, error) {
7✔
167
        repl := strings.NewReplacer(":tenantId", tenantId, ":deviceId", deviceId)
7✔
168
        url := c.baseURL + repl.Replace(getDeviceGroupsURL)
7✔
169

7✔
170
        if ctx == nil {
7✔
UNCOV
171
                ctx = context.Background()
×
172
        }
×
173
        if _, ok := ctx.Deadline(); !ok {
12✔
174
                var cancel context.CancelFunc
5✔
175
                ctx, cancel = context.WithTimeout(ctx, defaultTimeout)
5✔
176
                defer cancel()
5✔
177
        }
5✔
178
        req, err := http.NewRequestWithContext(
7✔
179
                ctx, "GET", url, nil,
7✔
180
        )
7✔
181
        if err != nil {
7✔
UNCOV
182
                return nil, err
×
183
        }
×
184

185
        rsp, err := c.httpClient.Do(req)
7✔
186
        if err != nil {
7✔
UNCOV
187
                return nil, errors.Wrap(err, "get device groups request failed")
×
188
        }
×
189
        defer rsp.Body.Close()
7✔
190

7✔
191
        if rsp.StatusCode != http.StatusOK {
12✔
192
                if rsp.StatusCode == http.StatusNotFound {
8✔
193
                        return []string{}, nil
3✔
194
                }
3✔
195
                return nil, errors.Errorf(
2✔
196
                        "get device groups request failed with unexpected status: %v",
2✔
197
                        rsp.StatusCode,
2✔
198
                )
2✔
199
        }
200

201
        res := model.DeviceGroups{}
3✔
202
        if err := json.NewDecoder(rsp.Body).Decode(&res); err != nil {
3✔
UNCOV
203
                return nil, errors.Wrap(err, "error parsing device groups response")
×
204
        }
×
205

206
        return res.Groups, nil
3✔
207
}
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