launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/container/lxc/mock/mock-lxc.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package mock
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"launchpad.net/golxc"
    10  )
    11  
    12  // This file provides a mock implementation of the golxc interfaces
    13  // ContainerFactory and Container.
    14  
    15  type Action int
    16  
    17  const (
    18  	// A container has been started.
    19  	Started Action = iota
    20  	// A container has been stopped.
    21  	Stopped
    22  )
    23  
    24  func (action Action) String() string {
    25  	switch action {
    26  	case Started:
    27  		return "Started"
    28  	case Stopped:
    29  		return "Stopped"
    30  	}
    31  	return "unknown"
    32  }
    33  
    34  type Event struct {
    35  	Action     Action
    36  	InstanceId string
    37  }
    38  
    39  type ContainerFactory interface {
    40  	golxc.ContainerFactory
    41  
    42  	AddListener(chan<- Event)
    43  	RemoveListener(chan<- Event)
    44  }
    45  
    46  type mockFactory struct {
    47  	instances map[string]golxc.Container
    48  	listeners []chan<- Event
    49  }
    50  
    51  func MockFactory() ContainerFactory {
    52  	return &mockFactory{
    53  		instances: make(map[string]golxc.Container),
    54  	}
    55  }
    56  
    57  type mockContainer struct {
    58  	factory  *mockFactory
    59  	name     string
    60  	state    golxc.State
    61  	logFile  string
    62  	logLevel golxc.LogLevel
    63  }
    64  
    65  // Name returns the name of the container.
    66  func (mock *mockContainer) Name() string {
    67  	return mock.name
    68  }
    69  
    70  // Create creates a new container based on the given template.
    71  func (mock *mockContainer) Create(configFile, template string, templateArgs ...string) error {
    72  	if mock.state != golxc.StateUnknown {
    73  		return fmt.Errorf("container is already created")
    74  	}
    75  	mock.state = golxc.StateStopped
    76  	mock.factory.instances[mock.name] = mock
    77  	return nil
    78  }
    79  
    80  // Start runs the container as a daemon.
    81  func (mock *mockContainer) Start(configFile, consoleFile string) error {
    82  	if mock.state == golxc.StateUnknown {
    83  		return fmt.Errorf("container has not been created")
    84  	} else if mock.state == golxc.StateRunning {
    85  		return fmt.Errorf("container is already running")
    86  	}
    87  	mock.state = golxc.StateRunning
    88  	mock.factory.notify(Started, mock.name)
    89  	return nil
    90  }
    91  
    92  // Stop terminates the running container.
    93  func (mock *mockContainer) Stop() error {
    94  	if mock.state == golxc.StateUnknown {
    95  		return fmt.Errorf("container has not been created")
    96  	} else if mock.state == golxc.StateStopped {
    97  		return fmt.Errorf("container is already stopped")
    98  	}
    99  	mock.state = golxc.StateStopped
   100  	mock.factory.notify(Stopped, mock.name)
   101  	return nil
   102  }
   103  
   104  // Clone creates a copy of the container, giving the copy the specified name.
   105  func (mock *mockContainer) Clone(name string) (golxc.Container, error) {
   106  	container := &mockContainer{
   107  		factory:  mock.factory,
   108  		name:     name,
   109  		state:    golxc.StateStopped,
   110  		logLevel: golxc.LogWarning,
   111  	}
   112  	mock.factory.instances[name] = container
   113  	return container, nil
   114  }
   115  
   116  // Freeze freezes all the container's processes.
   117  func (mock *mockContainer) Freeze() error {
   118  	return nil
   119  }
   120  
   121  // Unfreeze thaws all frozen container's processes.
   122  func (mock *mockContainer) Unfreeze() error {
   123  	return nil
   124  }
   125  
   126  // Destroy stops and removes the container.
   127  func (mock *mockContainer) Destroy() error {
   128  	// golxc destroy will stop the machine if it is running.
   129  	if mock.state == golxc.StateRunning {
   130  		mock.Stop()
   131  	}
   132  	if mock.state == golxc.StateUnknown {
   133  		return fmt.Errorf("container has not been created")
   134  	}
   135  	mock.state = golxc.StateUnknown
   136  	delete(mock.factory.instances, mock.name)
   137  	return nil
   138  }
   139  
   140  // Wait waits for one of the specified container states.
   141  func (mock *mockContainer) Wait(states ...golxc.State) error {
   142  	return nil
   143  }
   144  
   145  // Info returns the status and the process id of the container.
   146  func (mock *mockContainer) Info() (golxc.State, int, error) {
   147  	pid := -1
   148  	if mock.state == golxc.StateRunning {
   149  		pid = 42
   150  	}
   151  	return mock.state, pid, nil
   152  }
   153  
   154  // IsConstructed checks if the container image exists.
   155  func (mock *mockContainer) IsConstructed() bool {
   156  	return mock.state != golxc.StateUnknown
   157  }
   158  
   159  // IsRunning checks if the state of the container is 'RUNNING'.
   160  func (mock *mockContainer) IsRunning() bool {
   161  	return mock.state == golxc.StateRunning
   162  }
   163  
   164  // String returns information about the container, like the name, state,
   165  // and process id.
   166  func (mock *mockContainer) String() string {
   167  	_, pid, _ := mock.Info()
   168  	return fmt.Sprintf("<MockContainer %q, state: %s, pid %d>", mock.name, string(mock.state), pid)
   169  }
   170  
   171  // LogFile returns the current filename used for the LogFile.
   172  func (mock *mockContainer) LogFile() string {
   173  	return mock.logFile
   174  }
   175  
   176  // LogLevel returns the current logging level (only used if the
   177  // LogFile is not "").
   178  func (mock *mockContainer) LogLevel() golxc.LogLevel {
   179  	return mock.logLevel
   180  }
   181  
   182  // SetLogFile sets both the LogFile and LogLevel.
   183  func (mock *mockContainer) SetLogFile(filename string, level golxc.LogLevel) {
   184  	mock.logFile = filename
   185  	mock.logLevel = level
   186  }
   187  
   188  func (mock *mockFactory) String() string {
   189  	return fmt.Sprintf("mock lxc factory")
   190  }
   191  
   192  func (mock *mockFactory) New(name string) golxc.Container {
   193  	container, ok := mock.instances[name]
   194  	if ok {
   195  		return container
   196  	}
   197  	container = &mockContainer{
   198  		factory:  mock,
   199  		name:     name,
   200  		state:    golxc.StateUnknown,
   201  		logLevel: golxc.LogWarning,
   202  	}
   203  	return container
   204  }
   205  
   206  func (mock *mockFactory) List() (result []golxc.Container, err error) {
   207  	for _, container := range mock.instances {
   208  		result = append(result, container)
   209  	}
   210  	return
   211  }
   212  
   213  func (mock *mockFactory) notify(action Action, instanceId string) {
   214  	event := Event{action, instanceId}
   215  	for _, c := range mock.listeners {
   216  		c <- event
   217  	}
   218  }
   219  
   220  func (mock *mockFactory) AddListener(listener chan<- Event) {
   221  	mock.listeners = append(mock.listeners, listener)
   222  }
   223  
   224  func (mock *mockFactory) RemoveListener(listener chan<- Event) {
   225  	pos := 0
   226  	for i, c := range mock.listeners {
   227  		if c == listener {
   228  			pos = i
   229  		}
   230  	}
   231  	mock.listeners = append(mock.listeners[:pos], mock.listeners[pos+1:]...)
   232  }