github.com/hugorut/terraform@v1.1.3/src/backend/remote-state/manta/backend_state.go (about)

     1  package manta
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"path"
     8  	"sort"
     9  	"strings"
    10  
    11  	tritonErrors "github.com/joyent/triton-go/errors"
    12  	"github.com/joyent/triton-go/storage"
    13  
    14  	"github.com/hugorut/terraform/src/backend"
    15  	"github.com/hugorut/terraform/src/states"
    16  	"github.com/hugorut/terraform/src/states/remote"
    17  	"github.com/hugorut/terraform/src/states/statemgr"
    18  )
    19  
    20  func (b *Backend) Workspaces() ([]string, error) {
    21  	result := []string{backend.DefaultStateName}
    22  
    23  	objs, err := b.storageClient.Dir().List(context.Background(), &storage.ListDirectoryInput{
    24  		DirectoryName: path.Join(mantaDefaultRootStore, b.path),
    25  	})
    26  	if err != nil {
    27  		if tritonErrors.IsResourceNotFound(err) {
    28  			return result, nil
    29  		}
    30  		return nil, err
    31  	}
    32  
    33  	for _, obj := range objs.Entries {
    34  		if obj.Type == "directory" && obj.Name != "" {
    35  			result = append(result, obj.Name)
    36  		}
    37  	}
    38  
    39  	sort.Strings(result[1:])
    40  	return result, nil
    41  }
    42  
    43  func (b *Backend) DeleteWorkspace(name string) error {
    44  	if name == backend.DefaultStateName || name == "" {
    45  		return fmt.Errorf("can't delete default state")
    46  	}
    47  
    48  	//firstly we need to delete the state file
    49  	err := b.storageClient.Objects().Delete(context.Background(), &storage.DeleteObjectInput{
    50  		ObjectPath: path.Join(mantaDefaultRootStore, b.statePath(name), b.objectName),
    51  	})
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	//then we need to delete the state folder
    57  	err = b.storageClient.Objects().Delete(context.Background(), &storage.DeleteObjectInput{
    58  		ObjectPath: path.Join(mantaDefaultRootStore, b.statePath(name)),
    59  	})
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	return nil
    65  }
    66  
    67  func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
    68  	if name == "" {
    69  		return nil, errors.New("missing state name")
    70  	}
    71  
    72  	client := &RemoteClient{
    73  		storageClient: b.storageClient,
    74  		directoryName: b.statePath(name),
    75  		keyName:       b.objectName,
    76  	}
    77  
    78  	stateMgr := &remote.State{Client: client}
    79  
    80  	//if this isn't the default state name, we need to create the object so
    81  	//it's listed by States.
    82  	if name != backend.DefaultStateName {
    83  		// take a lock on this state while we write it
    84  		lockInfo := statemgr.NewLockInfo()
    85  		lockInfo.Operation = "init"
    86  		lockId, err := client.Lock(lockInfo)
    87  		if err != nil {
    88  			return nil, fmt.Errorf("failed to lock manta state: %s", err)
    89  		}
    90  
    91  		// Local helper function so we can call it multiple places
    92  		lockUnlock := func(parent error) error {
    93  			if err := stateMgr.Unlock(lockId); err != nil {
    94  				return fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err)
    95  			}
    96  			return parent
    97  		}
    98  
    99  		// Grab the value
   100  		if err := stateMgr.RefreshState(); err != nil {
   101  			err = lockUnlock(err)
   102  			return nil, err
   103  		}
   104  
   105  		// If we have no state, we have to create an empty state
   106  		if v := stateMgr.State(); v == nil {
   107  			if err := stateMgr.WriteState(states.NewState()); err != nil {
   108  				err = lockUnlock(err)
   109  				return nil, err
   110  			}
   111  			if err := stateMgr.PersistState(); err != nil {
   112  				err = lockUnlock(err)
   113  				return nil, err
   114  			}
   115  		}
   116  
   117  		// Unlock, the state should now be initialized
   118  		if err := lockUnlock(nil); err != nil {
   119  			return nil, err
   120  		}
   121  
   122  	}
   123  
   124  	return stateMgr, nil
   125  }
   126  
   127  func (b *Backend) client() *RemoteClient {
   128  	return &RemoteClient{}
   129  }
   130  
   131  func (b *Backend) statePath(name string) string {
   132  	if name == backend.DefaultStateName {
   133  		return b.path
   134  	}
   135  
   136  	return path.Join(b.path, name)
   137  }
   138  
   139  const errStateUnlock = `
   140  Error unlocking Manta state. Lock ID: %s
   141  
   142  Error: %s
   143  
   144  You may have to force-unlock this state in order to use it again.
   145  `