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

mendersoftware / mender-server / 1622978334

13 Jan 2025 03:51PM UTC coverage: 72.802% (-3.8%) from 76.608%
1622978334

Pull #300

gitlab-ci

alfrunes
fix: Deployment device count should not exceed max devices

Added a condition to skip deployments when the device count reaches max
devices.

Changelog: Title
Ticket: MEN-7847
Signed-off-by: Alf-Rune Siqveland <alf.rune@northern.tech>
Pull Request #300: fix: Deployment device count should not exceed max devices

4251 of 6164 branches covered (68.96%)

Branch coverage included in aggregate %.

0 of 18 new or added lines in 1 file covered. (0.0%)

2544 existing lines in 83 files now uncovered.

42741 of 58384 relevant lines covered (73.21%)

21.49 hits per line

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

83.51
/backend/services/inventory/utils/http.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 utils
16

17
import (
18
        "errors"
19
        "fmt"
20
        "math"
21
        "net/url"
22
        "strconv"
23
        "strings"
24

25
        "github.com/ant0ine/go-json-rest/rest"
26
)
27

28
// pagination constants
29
const (
30
        PageName       = "page"
31
        PerPageName    = "per_page"
32
        PageMin        = 1
33
        PageDefault    = 1
34
        PerPageMin     = 1
35
        PerPageMax     = 500
36
        PerPageDefault = 20
37
        LinkHdr        = "Link"
38
        LinkTmpl       = "<%s?%s>; rel=\"%s\""
39
        LinkPrev       = "prev"
40
        LinkNext       = "next"
41
        LinkFirst      = "first"
42
        DefaultScheme  = "http"
43
)
44

45
// error msgs
46
func MsgQueryParmInvalid(name string) string {
1✔
47
        return fmt.Sprintf("Can't parse param %s", name)
1✔
48
}
1✔
49

50
func MsgQueryParmMissing(name string) string {
1✔
51
        return fmt.Sprintf("Missing required param %s", name)
1✔
52
}
1✔
53

54
func MsgQueryParmLimit(name string) string {
1✔
55
        return fmt.Sprintf("Param %s is out of bounds", name)
1✔
56
}
1✔
57

58
func MsgQueryParmOneOf(name string, allowed []string) string {
1✔
59
        return fmt.Sprintf("Param %s must be one of %v", name, allowed)
1✔
60
}
1✔
61

62
// query param parsing/validation
63
func ParseQueryParmUInt(
64
        r *rest.Request,
65
        name string,
66
        required bool,
67
        min,
68
        max,
69
        def uint64,
70
) (uint64, error) {
1✔
71
        strVal := r.URL.Query().Get(name)
1✔
72

1✔
73
        if strVal == "" {
2✔
74
                if required {
2✔
75
                        return 0, errors.New(MsgQueryParmMissing(name))
1✔
76
                } else {
2✔
77
                        return def, nil
1✔
78
                }
1✔
79
        }
80

81
        uintVal, err := strconv.ParseUint(strVal, 10, 32)
1✔
82
        if err != nil {
2✔
83
                return 0, errors.New(MsgQueryParmInvalid(name))
1✔
84
        }
1✔
85

86
        if uintVal < min || uintVal > max {
2✔
87
                return 0, errors.New(MsgQueryParmLimit(name))
1✔
88
        }
1✔
89

90
        return uintVal, nil
1✔
91
}
92

UNCOV
93
func ParseQueryParmBool(r *rest.Request, name string, required bool, def *bool) (*bool, error) {
×
UNCOV
94
        strVal := r.URL.Query().Get(name)
×
UNCOV
95

×
UNCOV
96
        if strVal == "" {
×
UNCOV
97
                if required {
×
98
                        return nil, errors.New(MsgQueryParmMissing(name))
×
UNCOV
99
                } else {
×
UNCOV
100
                        return def, nil
×
UNCOV
101
                }
×
102
        }
103

UNCOV
104
        boolVal, err := strconv.ParseBool(strVal)
×
UNCOV
105
        if err != nil {
×
106
                return nil, errors.New(MsgQueryParmInvalid(name))
×
107
        }
×
108

UNCOV
109
        return &boolVal, nil
×
110
}
111

112
func ParseQueryParmStr(
113
        r *rest.Request,
114
        name string,
115
        required bool,
116
        allowed []string,
117
) (string, error) {
1✔
118
        val := r.URL.Query().Get(name)
1✔
119

1✔
120
        if val == "" {
2✔
121
                if required {
2✔
122
                        return "", errors.New(MsgQueryParmMissing(name))
1✔
123
                }
1✔
124
        } else {
1✔
125
                if allowed != nil && !ContainsString(val, allowed) {
2✔
126
                        return "", errors.New(MsgQueryParmOneOf(name, allowed))
1✔
127
                }
1✔
128
        }
129

130
        val, err := url.QueryUnescape(val)
1✔
131
        if err != nil {
1✔
132
                return "", errors.New(MsgQueryParmInvalid(name))
×
133
        }
×
134

135
        return val, nil
1✔
136
}
137

138
// pagination helpers
139
func ParsePagination(r *rest.Request) (uint64, uint64, error) {
1✔
140
        page, err := ParseQueryParmUInt(r, PageName, false, PageMin, math.MaxUint64, PageDefault)
1✔
141
        if err != nil {
2✔
142
                return 0, 0, err
1✔
143
        }
1✔
144

145
        per_page, err := ParseQueryParmUInt(
1✔
146
                r,
1✔
147
                PerPageName,
1✔
148
                false,
1✔
149
                PerPageMin,
1✔
150
                PerPageMax,
1✔
151
                PerPageDefault,
1✔
152
        )
1✔
153
        if err != nil {
2✔
154
                return 0, 0, err
1✔
155
        }
1✔
156

157
        return page, per_page, nil
1✔
158
}
159

160
func MakePageLinkHdrs(r *rest.Request, page, per_page uint64, has_next bool) []string {
1✔
161
        var links []string
1✔
162

1✔
163
        pathitems := strings.Split(r.URL.Path, "/")
1✔
164
        resource := pathitems[len(pathitems)-1]
1✔
165
        query := r.URL.Query()
1✔
166

1✔
167
        if page > 1 {
2✔
168
                links = append(links, MakeLink(LinkPrev, resource, query, page-1, per_page))
1✔
169
        }
1✔
170

171
        if has_next {
2✔
172
                links = append(links, MakeLink(LinkNext, resource, query, page+1, per_page))
1✔
173
        }
1✔
174

175
        links = append(links, MakeLink(LinkFirst, resource, query, 1, per_page))
1✔
176
        return links
1✔
177
}
178

179
func MakeLink(link_type string, resource string, query url.Values, page, per_page uint64) string {
1✔
180
        query.Set(PageName, strconv.Itoa(int(page)))
1✔
181
        query.Set(PerPageName, strconv.Itoa(int(per_page)))
1✔
182

1✔
183
        return fmt.Sprintf(LinkTmpl, resource, query.Encode(), link_type)
1✔
184
}
1✔
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