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

mendersoftware / deployments / 972678690

18 Aug 2023 07:14PM UTC coverage: 79.678% (+0.07%) from 79.613%
972678690

Pull #901

gitlab-ci

merlin-northern
test: docs and acc test

Ticket: MEN-6623
Signed-off-by: Peter Grzybowski <peter@northern.tech>
Pull Request #901: feat: save and get the update types

74 of 85 new or added lines in 4 files covered. (87.06%)

391 existing lines in 3 files now uncovered.

7810 of 9802 relevant lines covered (79.68%)

34.01 hits per line

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

85.85
/store/mongo/datastore_mongo_releases.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
        "time"
19

20
        "github.com/pkg/errors"
21
        "go.mongodb.org/mongo-driver/bson"
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/log"
26
        mstore "github.com/mendersoftware/go-lib-micro/store"
27

28
        "github.com/mendersoftware/deployments/model"
29
        "github.com/mendersoftware/deployments/store"
30
)
31

32
func (db *DataStoreMongo) UpdateReleaseArtifactDescription(
33
        ctx context.Context,
34
        artifactToEdit *model.Image,
35
        releaseName string,
36
) error {
×
37
        database := db.client.Database(mstore.DbFromContext(ctx, DatabaseName))
×
38
        collReleases := database.Collection(CollectionReleases)
×
39

×
40
        update := bson.M{
×
41
                "$set": bson.M{
×
42
                        StorageKeyReleaseArtifactsIndexDescription: artifactToEdit.ImageMeta.Description,
×
43
                        StorageKeyReleaseArtifactsIndexModified:    artifactToEdit.Modified,
×
44
                        StorageKeyReleaseModified:                  time.Now(),
×
45
                },
×
46
        }
×
47
        _, err := collReleases.UpdateOne(
×
48
                ctx,
×
49
                bson.M{
×
50
                        StorageKeyReleaseName:        releaseName,
×
51
                        StorageKeyReleaseArtifactsId: artifactToEdit.Id,
×
52
                },
×
53
                update,
×
54
        )
×
55
        if err != nil {
×
56
                return err
×
57
        }
×
58
        return nil
×
59
}
60

61
func (db *DataStoreMongo) UpdateReleaseArtifacts(
62
        ctx context.Context,
63
        artifactToAdd *model.Image,
64
        artifactToRemove *model.Image,
65
        releaseName string,
66
) error {
127✔
67
        database := db.client.Database(mstore.DbFromContext(ctx, DatabaseName))
127✔
68
        collReleases := database.Collection(CollectionReleases)
127✔
69

127✔
70
        opt := &mopts.UpdateOptions{}
127✔
71
        update := bson.M{
127✔
72
                "$set": bson.M{
127✔
73
                        StorageKeyReleaseName:     releaseName,
127✔
74
                        StorageKeyReleaseModified: time.Now(),
127✔
75
                },
127✔
76
        }
127✔
77
        if artifactToRemove != nil {
188✔
78
                update["$pull"] = bson.M{
61✔
79
                        StorageKeyReleaseArtifacts: bson.M{StorageKeyId: artifactToRemove.Id},
61✔
80
                }
61✔
81
        }
61✔
82
        if artifactToAdd != nil {
194✔
83
                upsert := true
67✔
84
                opt.Upsert = &upsert
67✔
85
                update["$push"] = bson.M{StorageKeyReleaseArtifacts: artifactToAdd}
67✔
86
        }
67✔
87
        _, err := collReleases.UpdateOne(
127✔
88
                ctx,
127✔
89
                bson.M{StorageKeyReleaseName: releaseName},
127✔
90
                update,
127✔
91
                opt,
127✔
92
        )
127✔
93
        if err != nil {
127✔
94
                return err
×
95
        }
×
96
        if artifactToRemove != nil {
188✔
97
                r := collReleases.FindOneAndDelete(
61✔
98
                        ctx,
61✔
99
                        bson.M{
61✔
100
                                StorageKeyReleaseName:      releaseName,
61✔
101
                                StorageKeyReleaseArtifacts: bson.M{"$size": 0},
61✔
102
                        },
61✔
103
                )
61✔
104
                if r.Err() != nil {
92✔
105
                        return err
31✔
106
                }
31✔
107
        }
108
        return nil
97✔
109
}
110

111
func (db *DataStoreMongo) ListReleaseTags(ctx context.Context) (model.Tags, error) {
4✔
112
        l := log.FromContext(ctx)
4✔
113
        tagKeys, err := db.client.
4✔
114
                Database(mstore.DbFromContext(ctx, DatabaseName)).
4✔
115
                Collection(CollectionReleases).
4✔
116
                Distinct(ctx, StorageKeyReleaseTags, bson.D{})
4✔
117
        if err != nil {
5✔
118
                return nil, errors.WithMessage(err,
1✔
119
                        "mongo: failed to retrieve distinct tags")
1✔
120
        }
1✔
121
        ret := make([]model.Tag, 0, len(tagKeys))
3✔
122
        for _, elem := range tagKeys {
110✔
123
                if key, ok := elem.(string); ok {
212✔
124
                        ret = append(ret, model.Tag(key))
105✔
125
                } else {
107✔
126
                        l.Warnf("unexpected data type (%T) received from distinct call: "+
2✔
127
                                "ignoring result", elem)
2✔
128
                }
2✔
129
        }
130

131
        return ret, err
3✔
132
}
133

134
func (db *DataStoreMongo) ReplaceReleaseTags(
135
        ctx context.Context,
136
        releaseName string,
137
        tags model.Tags,
138
) error {
8✔
139
        // Check preconditions
8✔
140
        if len(tags) > model.TagsMaxUnique {
9✔
141
                return model.ErrTooManyUniqueTags
1✔
142
        }
1✔
143

144
        collReleases := db.client.
7✔
145
                Database(mstore.DbFromContext(ctx, DatabaseName)).
7✔
146
                Collection(CollectionReleases)
7✔
147

7✔
148
        // Check if added tags will exceed limits
7✔
149
        if len(tags) > 0 {
11✔
150
                inUseTags, err := db.ListReleaseTags(ctx)
4✔
151
                if err != nil {
5✔
152
                        return errors.WithMessage(err, "mongo: failed to count in-use tags")
1✔
153
                }
1✔
154
                tagSet := make(map[model.Tag]struct{}, len(inUseTags))
3✔
155
                for _, tagKey := range inUseTags {
108✔
156
                        tagSet[tagKey] = struct{}{}
105✔
157
                }
105✔
158
                for _, tag := range tags {
56✔
159
                        delete(tagSet, tag)
53✔
160
                }
53✔
161
                if len(tags)+len(tagSet) > model.TagsMaxUnique {
4✔
162
                        return model.ErrTooManyUniqueTags
1✔
163
                }
1✔
164
        }
165

166
        // Update release tags
167
        res, err := collReleases.UpdateOne(ctx, bson.D{{
5✔
168
                Key: StorageKeyReleaseName, Value: releaseName,
5✔
169
        }}, bson.D{{
5✔
170
                Key:   mongoOpSet,
5✔
171
                Value: bson.D{{Key: StorageKeyReleaseTags, Value: tags}},
5✔
172
        }})
5✔
173
        if err != nil {
6✔
174
                return errors.WithMessage(err, "mongo: failed to update release tags")
1✔
175
        } else if res.MatchedCount <= 0 {
6✔
176
                return store.ErrNotFound
1✔
177
        }
1✔
178
        return nil
3✔
179
}
180

181
func (db *DataStoreMongo) UpdateRelease(
182
        ctx context.Context,
183
        releaseName string,
184
        release model.ReleasePatch,
185
) error {
6✔
186
        collReleases := db.client.
6✔
187
                Database(mstore.DbFromContext(ctx, DatabaseName)).
6✔
188
                Collection(CollectionReleases)
6✔
189

6✔
190
        err := release.Validate()
6✔
191
        if err != nil {
7✔
192
                return errors.Wrap(err, "cant update release due to validation errors")
1✔
193
        }
1✔
194

195
        // Update release, at the moment we update only the notes,
196
        // it is on purpose that we take only this field explicitly,
197
        // once there is a need we can extend
198
        res, err := collReleases.UpdateOne(
5✔
199
                ctx,
5✔
200
                bson.D{
5✔
201
                        {
5✔
202
                                Key: StorageKeyReleaseName, Value: releaseName,
5✔
203
                        },
5✔
204
                },
5✔
205
                bson.D{
5✔
206
                        {
5✔
207
                                Key: mongoOpSet,
5✔
208
                                Value: bson.D{
5✔
209
                                        {
5✔
210
                                                Key: StorageKeyReleaseNotes, Value: release.Notes,
5✔
211
                                        },
5✔
212
                                },
5✔
213
                        },
5✔
214
                },
5✔
215
        )
5✔
216
        if err != nil {
5✔
217
                return errors.WithMessage(err, "mongo: failed to update release")
×
218
        } else if res.MatchedCount <= 0 {
5✔
219
                return store.ErrNotFound
×
220
        }
×
221
        return nil
5✔
222
}
223

224
// Save the possibly new update types
225
func (db *DataStoreMongo) SaveUpdateTypes(ctx context.Context, updateTypes []string) error {
7✔
226
        database := db.client.Database(DatabaseName)
7✔
227
        c := database.Collection(CollectionUpdateTypes)
7✔
228

7✔
229
        tenantId := ""
7✔
230
        if id := identity.FromContext(ctx); id != nil {
11✔
231
                tenantId = id.Tenant
4✔
232
        }
4✔
233
        options := mopts.UpdateOptions{}
7✔
234
        options.SetUpsert(true)
7✔
235
        _, err := c.UpdateOne(
7✔
236
                ctx,
7✔
237
                bson.M{
7✔
238
                        StorageKeyId:       StorageKeyStorageReleaseUpdateTypes,
7✔
239
                        StorageKeyTenantId: tenantId,
7✔
240
                },
7✔
241
                bson.M{
7✔
242
                        "$addToSet": bson.M{
7✔
243
                                StorageKeyStorageReleaseUpdateTypes: bson.M{
7✔
244
                                        "$each": updateTypes,
7✔
245
                                },
7✔
246
                        },
7✔
247
                },
7✔
248
                &options,
7✔
249
        )
7✔
250
        return err
7✔
251
}
252

253
// Get the update types
254
func (db *DataStoreMongo) GetUpdateTypes(ctx context.Context) ([]string, error) {
7✔
255
        database := db.client.Database(DatabaseName)
7✔
256
        c := database.Collection(CollectionUpdateTypes)
7✔
257

7✔
258
        tenantId := ""
7✔
259
        if id := identity.FromContext(ctx); id != nil {
10✔
260
                tenantId = id.Tenant
3✔
261
        }
3✔
262
        result := c.FindOne(
7✔
263
                ctx,
7✔
264
                bson.M{
7✔
265
                        StorageKeyId:       StorageKeyStorageReleaseUpdateTypes,
7✔
266
                        StorageKeyTenantId: tenantId,
7✔
267
                },
7✔
268
        )
7✔
269
        type updateType struct {
7✔
270
                UpdateTypes []string `bson:"update_types"`
7✔
271
        }
7✔
272
        var updateTypes updateType
7✔
273
        err := result.Decode(&updateTypes)
7✔
274
        if err != nil {
7✔
NEW
275
                return []string{}, err
×
276
        } else {
7✔
277
                return updateTypes.UpdateTypes, nil
7✔
278
        }
7✔
279
}
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