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

mendersoftware / reporting / 738346025

pending completion
738346025

Pull #87

gitlab-ci

Fabio Tranchitella
feat: add support to index the device deployment data in the indexer
Pull Request #87: MEN-5930: index device deployment objects

641 of 884 new or added lines in 15 files covered. (72.51%)

1 existing line in 1 file now uncovered.

2556 of 3139 relevant lines covered (81.43%)

16.26 hits per line

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

95.62
/api/http/management_devices.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 http
16

17
import (
18
        "context"
19
        "net/http"
20
        "os"
21
        "strconv"
22
        "strings"
23

24
        "github.com/gin-gonic/gin"
25
        "github.com/pkg/errors"
26

27
        "github.com/mendersoftware/go-lib-micro/identity"
28
        "github.com/mendersoftware/go-lib-micro/rbac"
29
        "github.com/mendersoftware/go-lib-micro/rest.utils"
30

31
        "github.com/mendersoftware/reporting/model"
32
)
33

34
type attributes struct {
35
        Limit      int         `json:"limit"`
36
        Count      int         `json:"count"`
37
        Attributes []attribute `json:"attributes"`
38
}
39

40
type attribute struct {
41
        Name  string `json:"name"`
42
        Scope string `json:"scope"`
43
}
44

45
func (mc *ManagementController) AggregateDevices(c *gin.Context) {
10✔
46
        ctx := c.Request.Context()
10✔
47

10✔
48
        params, err := parseAggregateDevicesParams(ctx, c)
10✔
49
        if err != nil {
14✔
50
                rest.RenderError(c,
4✔
51
                        http.StatusBadRequest,
4✔
52
                        errors.Wrap(err, "malformed request body"),
4✔
53
                )
4✔
54
                return
4✔
55
        }
4✔
56

57
        res, err := mc.reporting.AggregateDevices(ctx, params)
6✔
58
        if err != nil {
8✔
59
                rest.RenderError(c,
2✔
60
                        http.StatusInternalServerError,
2✔
61
                        err,
2✔
62
                )
2✔
63
                return
2✔
64
        }
2✔
65

66
        c.JSON(http.StatusOK, res)
4✔
67
}
68

69
func parseAggregateDevicesParams(ctx context.Context, c *gin.Context) (
70
        *model.AggregateParams, error) {
10✔
71
        var aggregateParams model.AggregateParams
10✔
72

10✔
73
        err := c.ShouldBindJSON(&aggregateParams)
10✔
74
        if err != nil {
12✔
75
                return nil, err
2✔
76
        }
2✔
77

78
        if id := identity.FromContext(ctx); id != nil {
16✔
79
                aggregateParams.TenantID = id.Tenant
8✔
80
        } else {
8✔
NEW
81
                return nil, errors.New("missing tenant ID from the context")
×
NEW
82
        }
×
83

84
        if scope := rbac.ExtractScopeFromHeader(c.Request); scope != nil {
8✔
NEW
85
                aggregateParams.Groups = scope.DeviceGroups
×
NEW
86
        }
×
87

88
        if err := aggregateParams.Validate(); err != nil {
10✔
89
                return nil, err
2✔
90
        }
2✔
91

92
        return &aggregateParams, nil
6✔
93
}
94

95
func (mc *ManagementController) DeviceAttrs(c *gin.Context) {
10✔
96
        ctx := c.Request.Context()
10✔
97

10✔
98
        var tenantID string
10✔
99
        if id := identity.FromContext(ctx); id != nil && id.Tenant != "" {
18✔
100
                tenantID = id.Tenant
8✔
101
        } else {
10✔
102
                rest.RenderError(c,
2✔
103
                        http.StatusBadRequest,
2✔
104
                        errors.New("missing tenant ID from the context"),
2✔
105
                )
2✔
106
                return
2✔
107
        }
2✔
108

109
        mapping, err := mc.reporting.GetMapping(ctx, tenantID)
8✔
110
        if err != nil {
10✔
111
                rest.RenderError(c,
2✔
112
                        http.StatusInternalServerError,
2✔
113
                        errors.Wrap(err, "failed to retrieve the mapping"),
2✔
114
                )
2✔
115
                return
2✔
116
        } else if mapping == nil {
10✔
117
                mapping = &model.Mapping{}
2✔
118
        }
2✔
119

120
        attributesList := make([]attribute, 0, len(mapping.Inventory))
6✔
121
        for _, attr := range mapping.Inventory {
10✔
122
                parts := strings.SplitN(attr, string(os.PathSeparator), 2)
4✔
123
                attributesList = append(attributesList, attribute{
4✔
124
                        Name:  parts[1],
4✔
125
                        Scope: parts[0],
4✔
126
                })
4✔
127
        }
4✔
128
        res := &attributes{
6✔
129
                Limit:      model.MaxMappingInventoryAttributes,
6✔
130
                Count:      len(mapping.Inventory),
6✔
131
                Attributes: attributesList,
6✔
132
        }
6✔
133

6✔
134
        c.JSON(http.StatusOK, res)
6✔
135
}
136

137
func (mc *ManagementController) SearchDevices(c *gin.Context) {
21✔
138
        ctx := c.Request.Context()
21✔
139
        params, err := parseSearchDevicesParams(ctx, c)
21✔
140
        if err != nil {
25✔
141
                rest.RenderError(c,
4✔
142
                        http.StatusBadRequest,
4✔
143
                        errors.Wrap(err, "malformed request body"),
4✔
144
                )
4✔
145
                return
4✔
146
        }
4✔
147

148
        res, total, err := mc.reporting.SearchDevices(ctx, params)
17✔
149
        if err != nil {
19✔
150
                rest.RenderError(c,
2✔
151
                        http.StatusInternalServerError,
2✔
152
                        err,
2✔
153
                )
2✔
154
                return
2✔
155
        }
2✔
156

157
        pageLinkHdrs(c, params.Page, params.PerPage, total)
15✔
158

15✔
159
        c.Header(hdrTotalCount, strconv.Itoa(total))
15✔
160
        c.JSON(http.StatusOK, res)
15✔
161
}
162

163
func parseSearchDevicesParams(ctx context.Context, c *gin.Context) (*model.SearchParams, error) {
37✔
164
        var searchParams model.SearchParams
37✔
165

37✔
166
        err := c.ShouldBindJSON(&searchParams)
37✔
167
        if err != nil {
39✔
168
                return nil, err
2✔
169
        }
2✔
170

171
        if id := identity.FromContext(ctx); id != nil {
70✔
172
                searchParams.TenantID = id.Tenant
35✔
173
        } else {
35✔
NEW
174
                return nil, errors.New("missing tenant ID from the context")
×
NEW
175
        }
×
176

177
        if scope := rbac.ExtractScopeFromHeader(c.Request); scope != nil {
37✔
178
                searchParams.Groups = scope.DeviceGroups
2✔
179
        }
2✔
180

181
        if searchParams.PerPage <= 0 {
62✔
182
                searchParams.PerPage = ParamPerPageDefault
27✔
183
        }
27✔
184
        if searchParams.Page <= 0 {
62✔
185
                searchParams.Page = ParamPageDefault
27✔
186
        }
27✔
187

188
        if err := searchParams.Validate(); err != nil {
39✔
189
                return nil, err
4✔
190
        }
4✔
191

192
        return &searchParams, nil
31✔
193
}
194

195
func (mc *ManagementController) SearchDeviceAttrs(c *gin.Context) {
6✔
196
        ctx := c.Request.Context()
6✔
197

6✔
198
        id := identity.FromContext(ctx)
6✔
199
        res, err := mc.reporting.GetSearchableInvAttrs(ctx, id.Tenant)
6✔
200
        if err != nil {
8✔
201
                rest.RenderError(c,
2✔
202
                        http.StatusInternalServerError,
2✔
203
                        err,
2✔
204
                )
2✔
205
                return
2✔
206
        }
2✔
207

208
        c.JSON(http.StatusOK, res)
4✔
209
}
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