github.com/codeherentuk/terraform@v0.11.12-beta1/backend/remote-state/etcdv3/backend_state.go (about) 1 package etcd 2 3 import ( 4 "context" 5 "fmt" 6 "sort" 7 "strings" 8 9 etcdv3 "github.com/coreos/etcd/clientv3" 10 "github.com/hashicorp/terraform/backend" 11 "github.com/hashicorp/terraform/state" 12 "github.com/hashicorp/terraform/state/remote" 13 "github.com/hashicorp/terraform/terraform" 14 ) 15 16 func (b *Backend) States() ([]string, error) { 17 res, err := b.client.Get(context.TODO(), b.prefix, etcdv3.WithPrefix(), etcdv3.WithKeysOnly()) 18 if err != nil { 19 return nil, err 20 } 21 22 result := make([]string, 1, len(res.Kvs)+1) 23 result[0] = backend.DefaultStateName 24 for _, kv := range res.Kvs { 25 result = append(result, strings.TrimPrefix(string(kv.Key), b.prefix)) 26 } 27 sort.Strings(result[1:]) 28 29 return result, nil 30 } 31 32 func (b *Backend) DeleteState(name string) error { 33 if name == backend.DefaultStateName || name == "" { 34 return fmt.Errorf("Can't delete default state.") 35 } 36 37 key := b.determineKey(name) 38 39 _, err := b.client.Delete(context.TODO(), key) 40 return err 41 } 42 43 func (b *Backend) State(name string) (state.State, error) { 44 var stateMgr state.State = &remote.State{ 45 Client: &RemoteClient{ 46 Client: b.client, 47 DoLock: b.lock, 48 Key: b.determineKey(name), 49 }, 50 } 51 52 if !b.lock { 53 stateMgr = &state.LockDisabled{Inner: stateMgr} 54 } 55 56 lockInfo := state.NewLockInfo() 57 lockInfo.Operation = "init" 58 lockId, err := stateMgr.Lock(lockInfo) 59 if err != nil { 60 return nil, fmt.Errorf("Failed to lock state in etcd: %s.", err) 61 } 62 63 lockUnlock := func(parent error) error { 64 if err := stateMgr.Unlock(lockId); err != nil { 65 return fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err) 66 } 67 return parent 68 } 69 70 if err := stateMgr.RefreshState(); err != nil { 71 err = lockUnlock(err) 72 return nil, err 73 } 74 75 if v := stateMgr.State(); v == nil { 76 if err := stateMgr.WriteState(terraform.NewState()); err != nil { 77 err = lockUnlock(err) 78 return nil, err 79 } 80 if err := stateMgr.PersistState(); err != nil { 81 err = lockUnlock(err) 82 return nil, err 83 } 84 } 85 86 if err := lockUnlock(nil); err != nil { 87 return nil, err 88 } 89 90 return stateMgr, nil 91 } 92 93 func (b *Backend) determineKey(name string) string { 94 return b.prefix + name 95 } 96 97 const errStateUnlock = ` 98 Error unlocking etcd state. Lock ID: %s 99 100 Error: %s 101 102 You may have to force-unlock this state in order to use it again. 103 `