github.com/opentofu/opentofu@v1.7.1/internal/legacy/tofu/state_upgrade_v1_to_v2.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package tofu
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"github.com/mitchellh/copystructure"
    12  )
    13  
    14  // upgradeStateV1ToV2 is used to upgrade a V1 state representation
    15  // into a V2 state representation
    16  func upgradeStateV1ToV2(old *stateV1) (*State, error) {
    17  	if old == nil {
    18  		return nil, nil
    19  	}
    20  
    21  	remote, err := old.Remote.upgradeToV2()
    22  	if err != nil {
    23  		return nil, fmt.Errorf("Error upgrading State V1: %w", err)
    24  	}
    25  
    26  	modules := make([]*ModuleState, len(old.Modules))
    27  	for i, module := range old.Modules {
    28  		upgraded, err := module.upgradeToV2()
    29  		if err != nil {
    30  			return nil, fmt.Errorf("Error upgrading State V1: %w", err)
    31  		}
    32  		modules[i] = upgraded
    33  	}
    34  	if len(modules) == 0 {
    35  		modules = nil
    36  	}
    37  
    38  	newState := &State{
    39  		Version: 2,
    40  		Serial:  old.Serial,
    41  		Remote:  remote,
    42  		Modules: modules,
    43  	}
    44  
    45  	newState.sort()
    46  	newState.init()
    47  
    48  	return newState, nil
    49  }
    50  
    51  func (old *remoteStateV1) upgradeToV2() (*RemoteState, error) {
    52  	if old == nil {
    53  		return nil, nil
    54  	}
    55  
    56  	config, err := copystructure.Copy(old.Config)
    57  	if err != nil {
    58  		return nil, fmt.Errorf("Error upgrading RemoteState V1: %w", err)
    59  	}
    60  
    61  	return &RemoteState{
    62  		Type:   old.Type,
    63  		Config: config.(map[string]string),
    64  	}, nil
    65  }
    66  
    67  func (old *moduleStateV1) upgradeToV2() (*ModuleState, error) {
    68  	if old == nil {
    69  		return nil, nil
    70  	}
    71  
    72  	pathRaw, err := copystructure.Copy(old.Path)
    73  	if err != nil {
    74  		return nil, fmt.Errorf("Error upgrading ModuleState V1: %w", err)
    75  	}
    76  	path, ok := pathRaw.([]string)
    77  	if !ok {
    78  		return nil, fmt.Errorf("Error upgrading ModuleState V1: path is not a list of strings")
    79  	}
    80  	if len(path) == 0 {
    81  		// We found some V1 states with a nil path. Assume root and catch
    82  		// duplicate path errors later (as part of Validate).
    83  		path = rootModulePath
    84  	}
    85  
    86  	// Outputs needs upgrading to use the new structure
    87  	outputs := make(map[string]*OutputState)
    88  	for key, output := range old.Outputs {
    89  		outputs[key] = &OutputState{
    90  			Type:      "string",
    91  			Value:     output,
    92  			Sensitive: false,
    93  		}
    94  	}
    95  
    96  	resources := make(map[string]*ResourceState)
    97  	for key, oldResource := range old.Resources {
    98  		upgraded, err := oldResource.upgradeToV2()
    99  		if err != nil {
   100  			return nil, fmt.Errorf("Error upgrading ModuleState V1: %w", err)
   101  		}
   102  		resources[key] = upgraded
   103  	}
   104  
   105  	dependencies, err := copystructure.Copy(old.Dependencies)
   106  	if err != nil {
   107  		return nil, fmt.Errorf("Error upgrading ModuleState V1: %w", err)
   108  	}
   109  
   110  	return &ModuleState{
   111  		Path:         path,
   112  		Outputs:      outputs,
   113  		Resources:    resources,
   114  		Dependencies: dependencies.([]string),
   115  	}, nil
   116  }
   117  
   118  func (old *resourceStateV1) upgradeToV2() (*ResourceState, error) {
   119  	if old == nil {
   120  		return nil, nil
   121  	}
   122  
   123  	dependencies, err := copystructure.Copy(old.Dependencies)
   124  	if err != nil {
   125  		return nil, fmt.Errorf("Error upgrading ResourceState V1: %w", err)
   126  	}
   127  
   128  	primary, err := old.Primary.upgradeToV2()
   129  	if err != nil {
   130  		return nil, fmt.Errorf("Error upgrading ResourceState V1: %w", err)
   131  	}
   132  
   133  	deposed := make([]*InstanceState, len(old.Deposed))
   134  	for i, v := range old.Deposed {
   135  		upgraded, err := v.upgradeToV2()
   136  		if err != nil {
   137  			return nil, fmt.Errorf("Error upgrading ResourceState V1: %w", err)
   138  		}
   139  		deposed[i] = upgraded
   140  	}
   141  	if len(deposed) == 0 {
   142  		deposed = nil
   143  	}
   144  
   145  	return &ResourceState{
   146  		Type:         old.Type,
   147  		Dependencies: dependencies.([]string),
   148  		Primary:      primary,
   149  		Deposed:      deposed,
   150  		Provider:     old.Provider,
   151  	}, nil
   152  }
   153  
   154  func (old *instanceStateV1) upgradeToV2() (*InstanceState, error) {
   155  	if old == nil {
   156  		return nil, nil
   157  	}
   158  
   159  	attributes, err := copystructure.Copy(old.Attributes)
   160  	if err != nil {
   161  		return nil, fmt.Errorf("Error upgrading InstanceState V1: %w", err)
   162  	}
   163  	ephemeral, err := old.Ephemeral.upgradeToV2()
   164  	if err != nil {
   165  		return nil, fmt.Errorf("Error upgrading InstanceState V1: %w", err)
   166  	}
   167  
   168  	meta, err := copystructure.Copy(old.Meta)
   169  	if err != nil {
   170  		return nil, fmt.Errorf("Error upgrading InstanceState V1: %w", err)
   171  	}
   172  
   173  	newMeta := make(map[string]interface{})
   174  	for k, v := range meta.(map[string]string) {
   175  		newMeta[k] = v
   176  	}
   177  
   178  	return &InstanceState{
   179  		ID:         old.ID,
   180  		Attributes: attributes.(map[string]string),
   181  		Ephemeral:  *ephemeral,
   182  		Meta:       newMeta,
   183  	}, nil
   184  }
   185  
   186  func (old *ephemeralStateV1) upgradeToV2() (*EphemeralState, error) {
   187  	connInfo, err := copystructure.Copy(old.ConnInfo)
   188  	if err != nil {
   189  		return nil, fmt.Errorf("Error upgrading EphemeralState V1: %w", err)
   190  	}
   191  	return &EphemeralState{
   192  		ConnInfo: connInfo.(map[string]string),
   193  	}, nil
   194  }