github.com/mendersoftware/go-lib-micro@v0.0.0-20240304135804-e8e39c59b148/mongo/migrate/db.go (about)

     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 migrate
    15  
    16  import (
    17  	"context"
    18  	"time"
    19  
    20  	"github.com/mendersoftware/go-lib-micro/store"
    21  	"github.com/pkg/errors"
    22  	"go.mongodb.org/mongo-driver/bson"
    23  	"go.mongodb.org/mongo-driver/mongo"
    24  	mopts "go.mongodb.org/mongo-driver/mongo/options"
    25  )
    26  
    27  // this is a small internal data layer for the migration utils, may be shared by diff migrators
    28  const (
    29  	DbMigrationsColl = "migration_info"
    30  )
    31  
    32  type MigrationEntry struct {
    33  	Version   Version   `bson:"version"`
    34  	Timestamp time.Time `bson:"timestamp"`
    35  }
    36  
    37  // GetMigrationInfo retrieves a list of migrations applied to the db.
    38  // On success the function returns the MigrationEntries present in the db
    39  // sorted by the version in decending order.
    40  func GetMigrationInfo(ctx context.Context, sess *mongo.Client, db string) ([]MigrationEntry, error) {
    41  	c := sess.Database(db).Collection(DbMigrationsColl)
    42  	findOpts := mopts.Find()
    43  	findOpts.SetSort(bson.D{{
    44  		Key: "version.major", Value: -1,
    45  	}, {
    46  		Key: "version.minor", Value: -1,
    47  	}, {
    48  		Key: "version.patch", Value: -1,
    49  	}})
    50  
    51  	cursor, err := c.Find(ctx, bson.M{
    52  		"version": bson.M{"$exists": true},
    53  	}, findOpts)
    54  	if cursor == nil || err != nil {
    55  		return nil, errors.Wrap(err, "db: failed to get migration info")
    56  	}
    57  
    58  	var infoArray []MigrationEntry
    59  	err = cursor.All(ctx, &infoArray)
    60  	return infoArray, err
    61  }
    62  
    63  // UpdateMigrationInfo inserts a migration entry in the migration info collection.
    64  func UpdateMigrationInfo(ctx context.Context, version Version, sess *mongo.Client, db string) error {
    65  	c := sess.Database(db).Collection(DbMigrationsColl)
    66  
    67  	entry := MigrationEntry{
    68  		Version:   version,
    69  		Timestamp: time.Now(),
    70  	}
    71  	_, err := c.InsertOne(ctx, entry)
    72  	if err != nil {
    73  		return errors.Wrap(err, "db: failed to insert migration info")
    74  	}
    75  	// result.InsertedID (InsertOneResult)
    76  
    77  	return nil
    78  }
    79  
    80  func GetTenantDbs(ctx context.Context, client *mongo.Client, matcher store.TenantDbMatchFunc) ([]string, error) {
    81  	result, err := client.ListDatabaseNames(ctx, bson.M{})
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	tenantDbs := make([]string, len(result))
    87  	j := 0
    88  	for _, db := range result {
    89  		if matcher(db) {
    90  			tenantDbs[j] = db
    91  			j++
    92  		}
    93  	}
    94  	tenantDbs = tenantDbs[:j]
    95  
    96  	return tenantDbs, nil
    97  }