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