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

mendersoftware / mender-server / 1802588196

06 May 2025 10:48AM UTC coverage: 66.322% (+1.0%) from 65.288%
1802588196

Pull #631

gitlab-ci

lluiscampos
feat(create-artifact-worker): Update `mender-artifact` to latest v4.1.0

Modifying also the integration to build the tool from source instead or
repurposing the upstream Debian package. This has the main advantage
that we can compile it statically (by disabling a feature that we don't
use) and that we have control of the compatibility aspects of the
binary.

Ticket: MEN-8337

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>
Pull Request #631: MEN-8337: feat(create-artifact-worker): Update `mender-artifact` to latest v4.1.0

29522 of 44513 relevant lines covered (66.32%)

1.45 hits per line

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

56.76
/backend/pkg/mongo/migrate/migrator_simple.go
1
// Copyright 2024 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 migrate
15

16
import (
17
        "context"
18
        "fmt"
19
        "sort"
20
        "strings"
21

22
        "github.com/pkg/errors"
23
        "go.mongodb.org/mongo-driver/mongo"
24

25
        "github.com/mendersoftware/mender-server/pkg/log"
26
)
27

28
var (
29
        ErrNeedsMigration = "db needs migration"
30
)
31

32
func IsErrNeedsMigration(e error) bool {
×
33
        return strings.HasPrefix(e.Error(), ErrNeedsMigration)
×
34
}
×
35

36
// SimpleMigratior applies migrations by comparing `Version` of migrations
37
// passed to Apply() and already applied migrations. Only migrations that are of
38
// version higher than the last applied migration will be run. For example:
39
//
40
//        already applied migrations: 1.0.0, 1.0.1, 1.0.2
41
//        migrations in Apply(): 1.0.1, 1.0.3, 1.1.0
42
//        migrations that will be applied: 1.0.3, 1.1.0
43
type SimpleMigrator struct {
44
        Client      *mongo.Client
45
        Db          string
46
        Automigrate bool
47
}
48

49
// Apply will apply migrations, provided that Automigrate is on.
50
// After each successful migration a new migration
51
// record will be added to DB with the version of migration that was just
52
// applied. If a migration fails, Apply() returns an error and does not add a
53
// migration record (so last migration that is recorded is N-1).
54
//
55
// Apply() will log some messages when running. Logger will be extracted from
56
// context using go-lib-micro/log.LoggerContextKey as key.
57
// If Automigrate is off, the migrator will just check if the DB is up-to-date,
58
// and return with ErrNeedsMigration otherwise.
59
// Check for it with IsErrNeedsMigration.
60
func (m *SimpleMigrator) Apply(ctx context.Context, target Version, migrations []Migration) error {
9✔
61
        l := log.FromContext(ctx).F(log.Ctx{"db": m.Db})
9✔
62

9✔
63
        sort.Slice(migrations, func(i int, j int) bool {
16✔
64
                return VersionIsLess(migrations[i].Version(), migrations[j].Version())
7✔
65
        })
7✔
66

67
        applied, err := GetMigrationInfo(ctx, m.Client, m.Db)
9✔
68
        if err != nil {
9✔
69
                return errors.Wrap(err, "failed to list applied migrations")
×
70
        }
×
71

72
        // starts at 0.0.0
73
        last := Version{}
9✔
74

9✔
75
        if len(applied) != 0 {
16✔
76
                // sort applied migrations wrt. version
7✔
77
                sort.Slice(applied, func(i int, j int) bool {
11✔
78
                        return VersionIsLess(applied[i].Version, applied[j].Version)
4✔
79
                })
4✔
80
                // last version from already applied migrations
81
                last = applied[len(applied)-1].Version
7✔
82
        }
83

84
        // if Automigrate is disabled - just check
85
        // if the last applied migration is lower than the target one
86
        if !m.Automigrate {
12✔
87
                if VersionIsLess(last, target) {
3✔
88
                        return fmt.Errorf(
×
89
                                "%s: %s has version %s, needs version %s",
×
90
                                ErrNeedsMigration, m.Db, last.String(), target.String())
×
91
                } else {
3✔
92
                        return nil
3✔
93
                }
3✔
94
        }
95

96
        // try to apply migrations
97
        for _, migration := range migrations {
18✔
98
                mv := migration.Version()
9✔
99
                if VersionIsLess(target, mv) {
9✔
100
                        l.Warnf("migration to version %s skipped, target version %s is lower",
×
101
                                mv, target)
×
102
                } else if VersionIsLess(last, mv) {
18✔
103
                        // log, migration applied
9✔
104
                        l.Infof("applying migration from version %s to %s",
9✔
105
                                last, mv)
9✔
106

9✔
107
                        // apply migration
9✔
108
                        if err := migration.Up(last); err != nil {
9✔
109
                                l.Errorf("migration from %s to %s failed: %s",
×
110
                                        last, mv, err)
×
111

×
112
                                // migration from last to migration.Version() failed: err
×
113
                                return errors.Wrapf(err,
×
114
                                        "failed to apply migration from %s to %s",
×
115
                                        last, mv)
×
116
                        }
×
117

118
                        if err := UpdateMigrationInfo(ctx, mv, m.Client, m.Db); err != nil {
9✔
119

×
120
                                return errors.Wrapf(err,
×
121
                                        "failed to record migration from %s to %s",
×
122
                                        last, mv)
×
123

×
124
                        }
×
125
                        last = mv
9✔
126
                } else {
4✔
127
                        // log migration already applied
4✔
128
                        l.Infof("migration to version %s skipped", mv)
4✔
129
                }
4✔
130
        }
131

132
        // ideally, when all migrations have completed, DB should be in `target` version
133
        if VersionIsLess(last, target) {
9✔
134
                l.Warnf("last migration to version %s did not produce target version %s",
×
135
                        last, target)
×
136
                // record DB version anyways
×
137
                if err := UpdateMigrationInfo(ctx, target, m.Client, m.Db); err != nil {
×
138
                        return errors.Wrapf(err,
×
139
                                "failed to record migration from %s to %s",
×
140
                                last, target)
×
141
                }
×
142
        } else {
9✔
143
                l.Infof("DB migrated to version %s", target)
9✔
144
        }
9✔
145

146
        return nil
9✔
147
}
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