• 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

84.88
/backend/services/deviceauth/model/device.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
package model
15

16
import (
17
        "encoding/json"
18
        "net/url"
19
        "time"
20

21
        "github.com/asaskevich/govalidator"
22
        "github.com/pkg/errors"
23

24
        "github.com/mendersoftware/mender-server/pkg/ratelimits"
25
)
26

27
const (
28
        DevStatusAccepted = "accepted"
29
        DevStatusRejected = "rejected"
30
        DevStatusPending  = "pending"
31
        DevStatusPreauth  = "preauthorized"
32
        DevStatusNoAuth   = "noauth"
33

34
        DevKeyId           = "_id"
35
        DevKeyIdData       = "id_data"
36
        DevKeyIdDataSha256 = "id_data_sha256"
37
        DevKeyStatus       = "status"
38
)
39

40
var (
41
        DevStatuses = []string{
42
                DevStatusPending,
43
                DevStatusRejected,
44
                DevStatusAccepted,
45
                DevStatusPreauth,
46
                DevStatusNoAuth,
47
        }
48
)
49

50
// note: fields with underscores need the 'bson' decorator
51
// otherwise the underscore will be removed upon write to mongo
52
type Device struct {
53
        Id              string                 `json:"id" bson:"_id,omitempty"`
54
        IdData          string                 `json:"-" bson:"id_data,omitempty"`
55
        IdDataStruct    map[string]interface{} `json:"identity_data" bson:"id_data_struct,omitempty"`
56
        IdDataSha256    []byte                 `json:"-" bson:"id_data_sha256,omitempty"`
57
        Status          string                 `json:"status" bson:",omitempty"`
58
        Decommissioning bool                   `json:"decommissioning" bson:",omitempty"`
59
        CreatedTs       time.Time              `json:"created_ts" bson:"created_ts,omitempty"`
60
        UpdatedTs       time.Time              `json:"updated_ts" bson:"updated_ts,omitempty"`
61
        AuthSets        []AuthSet              `json:"auth_sets" bson:"-"`
62
        CheckInTime     *time.Time             `json:"check_in_time,omitempty" bson:"check_in_time,omitempty"` // nolint:lll
63
        //ApiLimits override tenant-wide quota/burst config
64
        ApiLimits ratelimits.ApiLimits `json:"-" bson:"api_limits"`
65

66
        //object revision which we use when synchronizing status with inventory service
67
        Revision uint   `json:"-" bson:"revision"`
68
        TenantID string `json:"-" bson:"tenant_id"`
69
}
70

71
type DeviceUpdate struct {
72
        PubKey          string                 `json:"-" bson:",omitempty"`
73
        IdData          string                 `json:"id_data" bson:"id_data,omitempty"`
74
        IdDataStruct    map[string]interface{} `bson:"id_data_struct,omitempty"`
75
        IdDataSha256    []byte                 `bson:"id_data_sha256,omitempty"`
76
        Status          string                 `json:"-" bson:",omitempty"`
77
        Decommissioning *bool                  `json:"-" bson:",omitempty"`
78
        UpdatedTs       *time.Time             `json:"updated_ts" bson:"updated_ts,omitempty"`
79
        CheckInTime     *time.Time             `json:"-" bson:"check_in_time,omitempty"`
80
}
81

UNCOV
82
func NewDevice(id, id_data, pubkey string) *Device {
×
UNCOV
83
        now := time.Now()
×
UNCOV
84

×
UNCOV
85
        return &Device{
×
UNCOV
86
                Id:              id,
×
UNCOV
87
                IdData:          id_data,
×
UNCOV
88
                Status:          DevStatusNoAuth,
×
UNCOV
89
                Decommissioning: false,
×
UNCOV
90
                CreatedTs:       now,
×
UNCOV
91
                UpdatedTs:       now,
×
UNCOV
92
                Revision:        1,
×
UNCOV
93
        }
×
UNCOV
94
}
×
95

96
type DeviceFilter struct {
97
        Status []string `json:"status,omitempty"`
98
        IDs    []string `json:"id,omitempty"`
99
}
100

101
func (fltr DeviceFilter) Validate() error {
1✔
102
        for _, stat := range fltr.Status {
2✔
103
                if !govalidator.IsIn(stat, DevStatuses...) {
2✔
104
                        return errors.Errorf(
1✔
105
                                `filter status must be one of: `+
1✔
106
                                        `%s, %s, %s, %s or %s`,
1✔
107
                                DevStatusAccepted, DevStatusPending,
1✔
108
                                DevStatusRejected, DevStatusPreauth,
1✔
109
                                DevStatusNoAuth,
1✔
110
                        )
1✔
111
                }
1✔
112
        }
113
        return nil
1✔
114
}
115

116
func (fltr *DeviceFilter) UnmarshalJSON(b []byte) error {
1✔
117
        schema := struct {
1✔
118
                Status interface{} `json:"status"`
1✔
119
                IDs    interface{} `json:"id"`
1✔
120
        }{}
1✔
121

1✔
122
        err := json.Unmarshal(b, &schema)
1✔
123
        if err != nil {
2✔
124
                return err
1✔
125
        }
1✔
126
        switch t := schema.Status.(type) {
1✔
127
        case string:
1✔
128
                fltr.Status = []string{t}
1✔
129
        case []interface{}:
1✔
130
                fltr.Status = make([]string, 0, len(t))
1✔
131
                for _, elem := range t {
2✔
132
                        if str, ok := elem.(string); ok {
2✔
133
                                fltr.Status = append(fltr.Status, str)
1✔
134
                        } else {
2✔
135
                                return errors.New(
1✔
136
                                        "invalid JSON type for 'status': " +
1✔
137
                                                "must be string or []string",
1✔
138
                                )
1✔
139
                        }
1✔
140
                }
141
        case nil:
1✔
142
                break
1✔
143
        default:
1✔
144
                return errors.New(
1✔
145
                        "invalid JSON type for 'status': " +
1✔
146
                                "must be string or []string",
1✔
147
                )
1✔
148
        }
149
        switch t := schema.IDs.(type) {
1✔
150
        case string:
1✔
151
                fltr.IDs = []string{t}
1✔
152
        case []interface{}:
1✔
153
                fltr.IDs = make([]string, 0, len(t))
1✔
154
                for _, elem := range t {
2✔
155
                        if str, ok := elem.(string); ok {
2✔
156
                                fltr.IDs = append(fltr.IDs, str)
1✔
157
                        } else {
2✔
158
                                return errors.New(
1✔
159
                                        "invalid JSON type for 'id': " +
1✔
160
                                                "must be string or []string",
1✔
161
                                )
1✔
162
                        }
1✔
163
                }
164
        case nil:
1✔
165
                break
1✔
166
        default:
1✔
167
                return errors.New(
1✔
168
                        "invalid JSON type for 'id': " +
1✔
169
                                "must be string or []string",
1✔
170
                )
1✔
171
        }
172
        return nil
1✔
173
}
174

175
func (fltr *DeviceFilter) ParseForm(form url.Values) error {
1✔
176
        if stat, ok := form["status"]; ok {
2✔
177
                fltr.Status = stat
1✔
178
        }
1✔
179
        if IDs, ok := form["id"]; ok {
2✔
180
                fltr.IDs = IDs
1✔
181
        }
1✔
182
        return fltr.Validate()
1✔
183
}
184

185
type DeviceAttribute struct {
186
        Name        string      `json:"name" bson:",omitempty"`
187
        Description *string     `json:"description,omitempty" bson:",omitempty"`
188
        Value       interface{} `json:"value" bson:",omitempty"`
189
        Scope       string      `json:"scope" bson:",omitempty"`
190
}
191

192
type DeviceInventoryUpdate struct {
193
        Id       string `json:"id"`
194
        Revision uint   `json:"revision"`
195
}
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