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

mendersoftware / reporting / 1571619767

13 Sep 2024 10:52AM UTC coverage: 85.292% (+0.06%) from 85.235%
1571619767

push

gitlab-ci

web-flow
Merge pull request #202 from mzedel/chore/deprecate

Chore/deprecate

2998 of 3515 relevant lines covered (85.29%)

14.21 hits per line

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

78.15
/app/reporting/reporting_deployments.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 reporting
16

17
import (
18
        "context"
19
        "encoding/json"
20

21
        "github.com/pkg/errors"
22

23
        "github.com/mendersoftware/reporting/model"
24
)
25

26
// AggregateDeployments aggregates deployments data
27
func (app *app) AggregateDeployments(
28
        ctx context.Context,
29
        aggregateParams *model.AggregateDeploymentsParams,
30
) ([]model.DeviceAggregation, error) {
4✔
31
        searchParams := &model.DeploymentsSearchParams{
4✔
32
                Filters:          aggregateParams.Filters,
4✔
33
                DeploymentGroups: aggregateParams.DeploymentGroups,
4✔
34
                TenantID:         aggregateParams.TenantID,
4✔
35
        }
4✔
36
        query, err := model.BuildDeploymentsQuery(*searchParams)
4✔
37
        if err != nil {
4✔
38
                return nil, err
×
39
        }
×
40
        if searchParams.TenantID != "" {
8✔
41
                query = query.Must(model.M{
4✔
42
                        "term": model.M{
4✔
43
                                model.FieldNameTenantID: searchParams.TenantID,
4✔
44
                        },
4✔
45
                })
4✔
46
        }
4✔
47

48
        aggregations, err := model.BuildDeploymentsAggregations(aggregateParams.Aggregations)
4✔
49
        if err != nil {
4✔
50
                return nil, err
×
51
        }
×
52

53
        query = query.WithSize(0).With(map[string]interface{}{
4✔
54
                "aggs": aggregations,
4✔
55
        })
4✔
56
        esRes, err := app.store.AggregateDeployments(ctx, query)
4✔
57
        if err != nil {
4✔
58
                return nil, err
×
59
        }
×
60

61
        aggregationsS, ok := esRes["aggregations"].(map[string]interface{})
4✔
62
        if !ok {
4✔
63
                return nil, errors.New("can't process store aggregations slice")
×
64
        }
×
65
        res, err := app.storeToDeviceAggregations(ctx, searchParams.TenantID, aggregationsS)
4✔
66
        if err != nil {
4✔
67
                return nil, err
×
68
        }
×
69

70
        return res, nil
4✔
71
}
72

73
// SearchDevices searches device data
74
func (app *app) SearchDeployments(
75
        ctx context.Context,
76
        searchParams *model.DeploymentsSearchParams,
77
) ([]model.Deployment, int, error) {
14✔
78
        query, err := model.BuildDeploymentsQuery(*searchParams)
14✔
79
        if err != nil {
15✔
80
                return nil, 0, err
1✔
81
        }
1✔
82

83
        if searchParams.TenantID != "" {
20✔
84
                query = query.Must(model.M{
7✔
85
                        "term": model.M{
7✔
86
                                model.FieldNameTenantID: searchParams.TenantID,
7✔
87
                        },
7✔
88
                })
7✔
89
        }
7✔
90

91
        if len(searchParams.DeviceIDs) > 0 {
15✔
92
                query = query.Must(model.M{
2✔
93
                        "terms": model.M{
2✔
94
                                model.FieldNameDeviceID: searchParams.DeviceIDs,
2✔
95
                        },
2✔
96
                })
2✔
97
        }
2✔
98

99
        if len(searchParams.DeploymentIDs) > 0 {
14✔
100
                query = query.Must(model.M{
1✔
101
                        "terms": model.M{
1✔
102
                                model.FieldNameDeploymentID: searchParams.DeploymentIDs,
1✔
103
                        },
1✔
104
                })
1✔
105
        }
1✔
106

107
        esRes, err := app.store.SearchDeployments(ctx, query)
13✔
108
        if err != nil {
14✔
109
                return nil, 0, err
1✔
110
        }
1✔
111

112
        res, total, err := app.storeToDeployments(ctx, searchParams.TenantID, esRes)
12✔
113
        if err != nil {
13✔
114
                return nil, 0, err
1✔
115
        }
1✔
116

117
        return res, total, err
11✔
118
}
119

120
// storeToInventoryDevs translates ES results directly to inventory devices
121
func (a *app) storeToDeployments(
122
        ctx context.Context, tenantID string, storeRes map[string]interface{},
123
) ([]model.Deployment, int, error) {
12✔
124
        depls := []model.Deployment{}
12✔
125

12✔
126
        hitsM, ok := storeRes["hits"].(map[string]interface{})
12✔
127
        if !ok {
12✔
128
                return nil, 0, errors.New("can't process store hits map")
×
129
        }
×
130

131
        hitsTotalM, ok := hitsM["total"].(map[string]interface{})
12✔
132
        if !ok {
12✔
133
                return nil, 0, errors.New("can't process total hits struct")
×
134
        }
×
135

136
        total, ok := hitsTotalM["value"].(float64)
12✔
137
        if !ok {
13✔
138
                return nil, 0, errors.New("can't process total hits value")
1✔
139
        }
1✔
140

141
        hitsS, ok := hitsM["hits"].([]interface{})
11✔
142
        if !ok {
11✔
143
                return nil, 0, errors.New("can't process store hits slice")
×
144
        }
×
145

146
        for _, v := range hitsS {
22✔
147
                res, err := a.storeToDeployment(ctx, tenantID, v)
11✔
148
                if err != nil {
11✔
149
                        return nil, 0, err
×
150
                }
×
151

152
                depls = append(depls, *res)
11✔
153
        }
154

155
        return depls, int(total), nil
11✔
156
}
157

158
func (a *app) storeToDeployment(ctx context.Context, tenantID string,
159
        storeRes interface{}) (*model.Deployment, error) {
11✔
160
        resM, ok := storeRes.(map[string]interface{})
11✔
161
        if !ok {
11✔
162
                return nil, errors.New("can't process individual hit")
×
163
        }
×
164

165
        // if query has a 'fields' clause, use 'fields' instead of '_source'
166
        sourceM, ok := resM["_source"].(map[string]interface{})
11✔
167
        if !ok {
12✔
168
                sourceM, ok = resM["fields"].(map[string]interface{})
1✔
169
                if !ok {
1✔
170
                        return nil, errors.New("can't process hit's '_source' nor 'fields'")
×
171
                }
×
172
        }
173

174
        source, err := json.Marshal(sourceM)
11✔
175
        if err != nil {
11✔
176
                return nil, errors.Wrap(err, "unable to marshal result into JSON")
×
177
        }
×
178

179
        ret := &model.Deployment{}
11✔
180
        err = json.Unmarshal(source, ret)
11✔
181
        if err != nil {
11✔
182
                return nil, errors.Wrap(err, "unable to unmarshal result from JSON")
×
183
        }
×
184

185
        return ret, nil
11✔
186
}
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