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