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

mendersoftware / deviceauth / 948596009

pending completion
948596009

push

gitlab-ci

web-flow
Merge pull request #655 from merlin-northern/men_6529_merge_single_db_to_master

Merge single db to master

332 of 405 new or added lines in 5 files covered. (81.98%)

16 existing lines in 2 files now uncovered.

4809 of 5767 relevant lines covered (83.39%)

48.84 hits per line

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

62.6
/store/mongo/migration_2_0_0.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 mongo
15

16
import (
17
        "context"
18
        "strings"
19

20
        "github.com/pkg/errors"
21
        "go.mongodb.org/mongo-driver/mongo"
22
        mopts "go.mongodb.org/mongo-driver/mongo/options"
23

24
        "github.com/mendersoftware/go-lib-micro/identity"
25
        "github.com/mendersoftware/go-lib-micro/mongo/migrate"
26
        "github.com/mendersoftware/go-lib-micro/mongo/oid"
27
        mstorev1 "github.com/mendersoftware/go-lib-micro/store"
28
        mstore "github.com/mendersoftware/go-lib-micro/store/v2"
29
        "go.mongodb.org/mongo-driver/bson"
30
)
31

32
const (
33
        findBatchSize = 255
34
)
35

36
type migration_2_0_0 struct {
37
        ds  *DataStoreMongo
38
        ctx context.Context
39
}
40

41
var DbDevicesCollectionIndices = []mongo.IndexModel{
42
        {
43
                Keys: bson.D{
44
                        {Key: mstore.FieldTenantID, Value: 1},
45
                        {Key: dbFieldIDDataSha, Value: 1},
46
                },
47
                //nolint:staticcheck // SA1019
48
                Options: mopts.Index().
49
                        SetName(strings.Join([]string{
50
                                mstore.FieldTenantID,
51
                                dbFieldIDDataSha,
52
                        }, "_")).
53
                        SetUnique(true).
54
                        SetBackground(false),
55
        },
56
        {
57
                Keys: bson.D{
58
                        {Key: mstore.FieldTenantID, Value: 1},
59
                        {Key: dbFieldStatus, Value: 1},
60
                        {Key: dbFieldID, Value: 1},
61
                },
62
                //nolint:staticcheck // SA1019
63
                Options: mopts.Index().
64
                        SetName(strings.Join([]string{
65
                                mstore.FieldTenantID,
66
                                dbFieldStatus,
67
                                dbFieldID,
68
                        }, "_")).
69
                        SetBackground(false),
70
        },
71
}
72

73
var DbAuthSetsCollectionIndices = []mongo.IndexModel{
74
        {
75
                Keys: bson.D{
76
                        {Key: mstore.FieldTenantID, Value: 1},
77
                        {Key: dbFieldIDDataSha, Value: 1},
78
                        {Key: dbFieldPubKey, Value: 1},
79
                },
80
                Options: mopts.Index().
81
                        SetName(strings.Join([]string{
82
                                mstore.FieldTenantID,
83
                                dbFieldIDDataSha,
84
                                dbFieldPubKey,
85
                        }, "_")).
86
                        SetUnique(true),
87
        },
88
        {
89
                Keys: bson.D{
90
                        {Key: mstore.FieldTenantID, Value: 1},
91
                        {Key: dbFieldDeviceID, Value: 1},
92
                },
93
                Options: mopts.Index().
94
                        SetName(strings.Join([]string{
95
                                mstore.FieldTenantID,
96
                                dbFieldDeviceID,
97
                        }, "_")),
98
        },
99
}
100

101
var DbLimitsCollectionIndices = []mongo.IndexModel{
102
        {
103
                Keys: bson.D{
104
                        {Key: mstore.FieldTenantID, Value: 1},
105
                        {Key: dbFieldName, Value: 1},
106
                },
107
                Options: mopts.Index().
108
                        SetName(strings.Join([]string{
109
                                mstore.FieldTenantID,
110
                                dbFieldName,
111
                        },
112
                                "_",
113
                        ),
114
                        ).
115
                        SetUnique(true),
116
        },
117
}
118

119
var DbTokensCollectionIndices = []mongo.IndexModel{
120
        {
121
                Keys: bson.D{
122
                        {Key: dbFieldTenantClaim, Value: 1},
123
                        {Key: dbFieldID, Value: 1},
124
                },
125
                Options: mopts.Index().
126
                        SetName(
127
                                strings.Join(
128
                                        []string{
129
                                                strings.ReplaceAll(dbFieldTenantClaim, ".", "_"),
130
                                                dbFieldID,
131
                                        },
132
                                        "_",
133
                                ),
134
                        ),
135
        },
136
        {
137
                Keys: bson.D{
138
                        {Key: dbFieldTenantClaim, Value: 1},
139
                        {Key: dbFieldExpTime, Value: 1},
140
                },
141
                Options: mopts.Index().
142
                        SetName(
143
                                strings.Join(
144
                                        []string{
145
                                                strings.ReplaceAll(dbFieldTenantClaim, ".", "_"),
146
                                                strings.ReplaceAll(dbFieldExpTime, ".", "_"),
147
                                        },
148
                                        "_",
149
                                ),
150
                        ),
151
        },
152
}
153

154
// Up creates an index on status and id in the devices collection
155
// nolint: gocyclo
156
func (m *migration_2_0_0) Up(from migrate.Version) error {
138✔
157
        ctx := context.Background()
138✔
158
        client := m.ds.client
138✔
159

138✔
160
        collections := map[string]struct {
138✔
161
                Indexes []mongo.IndexModel
138✔
162
        }{
138✔
163
                DbAuthSetColl: {
138✔
164
                        Indexes: DbAuthSetsCollectionIndices,
138✔
165
                },
138✔
166
                DbDevicesColl: {
138✔
167
                        Indexes: DbDevicesCollectionIndices,
138✔
168
                },
138✔
169
                DbLimitsColl: {
138✔
170
                        Indexes: DbLimitsCollectionIndices,
138✔
171
                },
138✔
172
                DbTokensColl: {
138✔
173
                        Indexes: DbTokensCollectionIndices,
138✔
174
                },
138✔
175
        }
138✔
176

138✔
177
        databaseName := mstorev1.DbFromContext(m.ctx, DbName)
138✔
178
        tenantID := mstorev1.TenantFromDbName(databaseName, DbName)
138✔
179
        ctx = identity.WithContext(ctx, &identity.Identity{
138✔
180
                Tenant: tenantID,
138✔
181
        })
138✔
182
        writes := make([]mongo.WriteModel, 0, findBatchSize)
138✔
183

138✔
184
        for collection, idxes := range collections {
687✔
185
                writes = writes[:0]
549✔
186
                findOptions := mopts.Find().
549✔
187
                        SetBatchSize(findBatchSize).
549✔
188
                        SetSort(bson.D{{Key: dbFieldID, Value: 1}})
549✔
189
                collOut := client.Database(DbName).Collection(collection)
549✔
190
                if databaseName == DbName {
814✔
191
                        indices := collOut.Indexes()
265✔
192
                        _, _ = indices.DropAll(ctx)
265✔
193

265✔
194
                        if len(idxes.Indexes) > 0 {
530✔
195
                                _, err := collOut.Indexes().CreateMany(ctx, collections[collection].Indexes)
265✔
196
                                if err != nil {
265✔
NEW
197
                                        return err
×
NEW
198
                                }
×
199
                        }
200
                        if collection == DbTokensColl {
332✔
201
                                continue
67✔
202
                        }
203
                        _, err := collOut.UpdateMany(ctx, bson.D{
199✔
204
                                {Key: mstore.FieldTenantID, Value: bson.D{
199✔
205
                                        {Key: "$exists", Value: false},
199✔
206
                                }},
199✔
207
                        }, bson.D{{Key: "$set", Value: bson.D{
199✔
208
                                {Key: mstore.FieldTenantID, Value: ""},
199✔
209
                        }}},
199✔
210
                        )
199✔
211
                        if err != nil {
199✔
NEW
212
                                return err
×
NEW
213
                        }
×
214
                        continue
199✔
215
                }
216

217
                if collection == DbTokensColl {
357✔
218
                        continue
72✔
219
                }
220
                coll := client.Database(databaseName).Collection(collection)
214✔
221
                // get all the documents in the collection
214✔
222
                cur, err := coll.Find(ctx, bson.D{}, findOptions)
214✔
223
                if err != nil {
214✔
NEW
224
                        return err
×
NEW
225
                }
×
226
                defer cur.Close(ctx)
214✔
227

214✔
228
                // migrate the documents
214✔
229
                if collection == DbLimitsColl {
286✔
230
                        for cur.Next(ctx) {
72✔
NEW
231
                                id := cur.Current.Lookup(dbFieldID)
×
NEW
232
                                var currentId string
×
NEW
233
                                err = id.Unmarshal(&currentId)
×
NEW
234
                                if err != nil {
×
NEW
235
                                        return errors.Wrap(err, "the id found is un-parsable")
×
NEW
236
                                }
×
NEW
237
                                var item bson.D
×
NEW
238
                                if err = cur.Decode(&item); err != nil {
×
NEW
239
                                        return err
×
NEW
240
                                }
×
NEW
241
                                item = append(item, bson.E{
×
NEW
242
                                        Key:   dbFieldName,
×
NEW
243
                                        Value: currentId,
×
NEW
244
                                })
×
NEW
245
                                item = item[1:]
×
NEW
246
                                item = findAndReplace(item, dbFieldID, oid.NewUUIDv4().String())
×
NEW
247

×
NEW
248
                                writes = append(writes, mongo.
×
NEW
249
                                        NewReplaceOneModel().
×
NEW
250
                                        SetFilter(bson.D{{Key: dbFieldName, Value: id}}).
×
NEW
251
                                        SetUpsert(true).
×
NEW
252
                                        SetReplacement(mstore.WithTenantID(ctx, item)))
×
NEW
253
                                if len(writes) == findBatchSize {
×
NEW
254
                                        _, err = collOut.BulkWrite(ctx, writes)
×
NEW
255
                                        if err != nil {
×
NEW
256
                                                return err
×
NEW
257
                                        }
×
NEW
258
                                        writes = writes[:0]
×
259
                                }
260
                        }
261
                } else {
143✔
262
                        for cur.Next(ctx) {
10,786✔
263
                                id := cur.Current.Lookup(dbFieldID)
10,643✔
264
                                var item bson.D
10,643✔
265
                                if err = cur.Decode(&item); err != nil {
10,643✔
NEW
266
                                        return err
×
NEW
267
                                }
×
268
                                writes = append(writes, mongo.
10,643✔
269
                                        NewReplaceOneModel().
10,643✔
270
                                        SetFilter(bson.D{{Key: dbFieldID, Value: id}}).
10,643✔
271
                                        SetUpsert(true).
10,643✔
272
                                        SetReplacement(mstore.WithTenantID(ctx, item)))
10,643✔
273
                                if len(writes) == findBatchSize {
10,643✔
NEW
274
                                        _, err = collOut.BulkWrite(ctx, writes)
×
NEW
275
                                        if err != nil {
×
NEW
276
                                                return err
×
NEW
277
                                        }
×
NEW
278
                                        writes = writes[:0]
×
279
                                }
280
                        }
281
                }
282
                if len(writes) > 0 {
283✔
283
                        _, err := collOut.BulkWrite(ctx, writes)
69✔
284
                        if err != nil {
69✔
NEW
285
                                return err
×
NEW
286
                        }
×
287
                }
288
        }
289

290
        return nil
138✔
291
}
292

NEW
293
func findAndReplace(item bson.D, key string, value string) bson.D {
×
NEW
294
        for i, d := range item {
×
NEW
295
                if d.Key == key {
×
NEW
296
                        item[i].Value = value
×
NEW
297
                }
×
298
        }
NEW
299
        return item
×
300
}
301

302
func (m *migration_2_0_0) Version() migrate.Version {
141✔
303
        return migrate.MakeVersion(2, 0, 0)
141✔
304
}
141✔
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