github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/environs/configstore/mem.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package configstore
     5  
     6  import (
     7  	"fmt"
     8  	"sync"
     9  
    10  	"github.com/juju/errors"
    11  )
    12  
    13  type memStore struct {
    14  	mu   sync.Mutex
    15  	envs map[string]*memInfo
    16  }
    17  
    18  type memInfo struct {
    19  	store *memStore
    20  	name  string
    21  	environInfo
    22  }
    23  
    24  // clone returns a copy of the given environment info, isolated
    25  // from the store itself.
    26  func (info *memInfo) clone() *memInfo {
    27  	// Note that none of the Set* methods ever set fields inside
    28  	// references, which makes this OK to do.
    29  	info1 := *info
    30  	newAttrs := make(map[string]interface{})
    31  	for name, attr := range info.bootstrapConfig {
    32  		newAttrs[name] = attr
    33  	}
    34  	info1.bootstrapConfig = newAttrs
    35  	info1.source = sourceMem
    36  	return &info1
    37  }
    38  
    39  // NewMem returns a ConfigStorage implementation that
    40  // stores configuration in memory.
    41  func NewMem() Storage {
    42  	return &memStore{
    43  		envs: make(map[string]*memInfo),
    44  	}
    45  }
    46  
    47  // CreateInfo implements Storage.CreateInfo.
    48  func (m *memStore) CreateInfo(envName string) EnvironInfo {
    49  	m.mu.Lock()
    50  	defer m.mu.Unlock()
    51  	info := &memInfo{
    52  		store: m,
    53  		name:  envName,
    54  	}
    55  	info.source = sourceCreated
    56  	return info
    57  }
    58  
    59  // List implements Storage.List
    60  func (m *memStore) List() ([]string, error) {
    61  	var envs []string
    62  	m.mu.Lock()
    63  	defer m.mu.Unlock()
    64  	for name, env := range m.envs {
    65  		api := env.APIEndpoint()
    66  		if api.ServerUUID == "" || api.EnvironUUID != "" {
    67  			envs = append(envs, name)
    68  		}
    69  	}
    70  	return envs, nil
    71  }
    72  
    73  // ListSystems implements Storage.ListSystems
    74  func (m *memStore) ListSystems() ([]string, error) {
    75  	var servers []string
    76  	m.mu.Lock()
    77  	defer m.mu.Unlock()
    78  	for name, env := range m.envs {
    79  		api := env.APIEndpoint()
    80  		if api.ServerUUID == "" ||
    81  			api.ServerUUID == api.EnvironUUID ||
    82  			api.EnvironUUID == "" {
    83  			servers = append(servers, name)
    84  		}
    85  	}
    86  	return servers, nil
    87  }
    88  
    89  // ReadInfo implements Storage.ReadInfo.
    90  func (m *memStore) ReadInfo(envName string) (EnvironInfo, error) {
    91  	m.mu.Lock()
    92  	defer m.mu.Unlock()
    93  	info := m.envs[envName]
    94  	if info != nil {
    95  		return info.clone(), nil
    96  	}
    97  	return nil, errors.NotFoundf("environment %q", envName)
    98  }
    99  
   100  // Location implements EnvironInfo.Location.
   101  func (info *memInfo) Location() string {
   102  	return "memory"
   103  }
   104  
   105  // Write implements EnvironInfo.Write.
   106  func (info *memInfo) Write() error {
   107  	m := info.store
   108  	m.mu.Lock()
   109  	defer m.mu.Unlock()
   110  
   111  	if !info.initialized() && m.envs[info.name] != nil {
   112  		return ErrEnvironInfoAlreadyExists
   113  	}
   114  
   115  	info.source = sourceMem
   116  	m.envs[info.name] = info.clone()
   117  	return nil
   118  }
   119  
   120  // Destroy implements EnvironInfo.Destroy.
   121  func (info *memInfo) Destroy() error {
   122  	m := info.store
   123  	m.mu.Lock()
   124  	defer m.mu.Unlock()
   125  	if info.initialized() {
   126  		if m.envs[info.name] == nil {
   127  			return fmt.Errorf("environment info has already been removed")
   128  		}
   129  		delete(m.envs, info.name)
   130  	}
   131  	return nil
   132  }