github.com/containerd/Containerd@v1.4.13/metadata/migrations.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package metadata
    18  
    19  import bolt "go.etcd.io/bbolt"
    20  
    21  type migration struct {
    22  	schema  string
    23  	version int
    24  	migrate func(*bolt.Tx) error
    25  }
    26  
    27  // migrations stores the list of database migrations
    28  // for each update to the database schema. The migrations
    29  // array MUST be ordered by version from least to greatest.
    30  // The last entry in the array should correspond to the
    31  // schemaVersion and dbVersion constants.
    32  // A migration test MUST be added for each migration in
    33  // the array.
    34  // The migrate function can safely assume the version
    35  // of the data it is migrating from is the previous version
    36  // of the database.
    37  var migrations = []migration{
    38  	{
    39  		schema:  "v1",
    40  		version: 1,
    41  		migrate: addChildLinks,
    42  	},
    43  	{
    44  		schema:  "v1",
    45  		version: 2,
    46  		migrate: migrateIngests,
    47  	},
    48  	{
    49  		schema:  "v1",
    50  		version: 3,
    51  		migrate: noOpMigration,
    52  	},
    53  }
    54  
    55  // addChildLinks Adds children key to the snapshotters to enforce snapshot
    56  // entries cannot be removed which have children
    57  func addChildLinks(tx *bolt.Tx) error {
    58  	v1bkt := tx.Bucket(bucketKeyVersion)
    59  	if v1bkt == nil {
    60  		return nil
    61  	}
    62  
    63  	// iterate through each namespace
    64  	v1c := v1bkt.Cursor()
    65  
    66  	for k, v := v1c.First(); k != nil; k, v = v1c.Next() {
    67  		if v != nil {
    68  			continue
    69  		}
    70  		nbkt := v1bkt.Bucket(k)
    71  
    72  		sbkt := nbkt.Bucket(bucketKeyObjectSnapshots)
    73  		if sbkt != nil {
    74  			// Iterate through each snapshotter
    75  			if err := sbkt.ForEach(func(sk, sv []byte) error {
    76  				if sv != nil {
    77  					return nil
    78  				}
    79  				snbkt := sbkt.Bucket(sk)
    80  
    81  				// Iterate through each snapshot
    82  				return snbkt.ForEach(func(k, v []byte) error {
    83  					if v != nil {
    84  						return nil
    85  					}
    86  					parent := snbkt.Bucket(k).Get(bucketKeyParent)
    87  					if len(parent) > 0 {
    88  						pbkt := snbkt.Bucket(parent)
    89  						if pbkt == nil {
    90  							// Not enforcing consistency during migration, skip
    91  							return nil
    92  						}
    93  						cbkt, err := pbkt.CreateBucketIfNotExists(bucketKeyChildren)
    94  						if err != nil {
    95  							return err
    96  						}
    97  						if err := cbkt.Put(k, nil); err != nil {
    98  							return err
    99  						}
   100  					}
   101  
   102  					return nil
   103  				})
   104  			}); err != nil {
   105  				return err
   106  			}
   107  		}
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  // migrateIngests moves ingests from the key/value ingest bucket
   114  // to a structured ingest bucket for storing additional state about
   115  // an ingest.
   116  func migrateIngests(tx *bolt.Tx) error {
   117  	v1bkt := tx.Bucket(bucketKeyVersion)
   118  	if v1bkt == nil {
   119  		return nil
   120  	}
   121  
   122  	// iterate through each namespace
   123  	v1c := v1bkt.Cursor()
   124  
   125  	for k, v := v1c.First(); k != nil; k, v = v1c.Next() {
   126  		if v != nil {
   127  			continue
   128  		}
   129  		bkt := v1bkt.Bucket(k).Bucket(bucketKeyObjectContent)
   130  		if bkt == nil {
   131  			continue
   132  		}
   133  
   134  		dbkt := bkt.Bucket(deprecatedBucketKeyObjectIngest)
   135  		if dbkt == nil {
   136  			continue
   137  		}
   138  
   139  		// Create new ingests bucket
   140  		nbkt, err := bkt.CreateBucketIfNotExists(bucketKeyObjectIngests)
   141  		if err != nil {
   142  			return err
   143  		}
   144  
   145  		if err := dbkt.ForEach(func(ref, bref []byte) error {
   146  			ibkt, err := nbkt.CreateBucketIfNotExists(ref)
   147  			if err != nil {
   148  				return err
   149  			}
   150  			return ibkt.Put(bucketKeyRef, bref)
   151  		}); err != nil {
   152  			return err
   153  		}
   154  
   155  		if err := bkt.DeleteBucket(deprecatedBucketKeyObjectIngest); err != nil {
   156  			return err
   157  		}
   158  	}
   159  
   160  	return nil
   161  }
   162  
   163  // noOpMigration was for a database change from boltdb/bolt which is no
   164  // longer being supported, to go.etcd.io/bbolt which is the currently
   165  // maintained repo for boltdb.
   166  func noOpMigration(tx *bolt.Tx) error {
   167  	return nil
   168  }