github.com/akazakov/terraform@v0.5.2-0.20160205142716-097441beafdf/state/local.go (about)

     1  package state
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  
     7  	"github.com/hashicorp/terraform/terraform"
     8  )
     9  
    10  // LocalState manages a state storage that is local to the filesystem.
    11  type LocalState struct {
    12  	// Path is the path to read the state from. PathOut is the path to
    13  	// write the state to. If PathOut is not specified, Path will be used.
    14  	// If PathOut already exists, it will be overwritten.
    15  	Path    string
    16  	PathOut string
    17  
    18  	state     *terraform.State
    19  	readState *terraform.State
    20  	written   bool
    21  }
    22  
    23  // SetState will force a specific state in-memory for this local state.
    24  func (s *LocalState) SetState(state *terraform.State) {
    25  	s.state = state
    26  	s.readState = state
    27  }
    28  
    29  // StateReader impl.
    30  func (s *LocalState) State() *terraform.State {
    31  	return s.state.DeepCopy()
    32  }
    33  
    34  // WriteState for LocalState always persists the state as well.
    35  //
    36  // StateWriter impl.
    37  func (s *LocalState) WriteState(state *terraform.State) error {
    38  	s.state = state
    39  
    40  	path := s.PathOut
    41  	if path == "" {
    42  		path = s.Path
    43  	}
    44  
    45  	// If we don't have any state, we actually delete the file if it exists
    46  	if state == nil {
    47  		err := os.Remove(path)
    48  		if err != nil && os.IsNotExist(err) {
    49  			return nil
    50  		}
    51  
    52  		return err
    53  	}
    54  
    55  	// Create all the directories
    56  	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
    57  		return err
    58  	}
    59  
    60  	f, err := os.Create(path)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	defer f.Close()
    65  
    66  	s.state.IncrementSerialMaybe(s.readState)
    67  	s.readState = s.state
    68  
    69  	if err := terraform.WriteState(s.state, f); err != nil {
    70  		return err
    71  	}
    72  
    73  	s.written = true
    74  	return nil
    75  }
    76  
    77  // PersistState for LocalState is a no-op since WriteState always persists.
    78  //
    79  // StatePersister impl.
    80  func (s *LocalState) PersistState() error {
    81  	return nil
    82  }
    83  
    84  // StateRefresher impl.
    85  func (s *LocalState) RefreshState() error {
    86  	// If we've never loaded before, read from Path, otherwise we
    87  	// read from PathOut.
    88  	path := s.Path
    89  	if s.written && s.PathOut != "" {
    90  		path = s.PathOut
    91  	}
    92  
    93  	f, err := os.Open(path)
    94  	if err != nil {
    95  		// It is okay if the file doesn't exist, we treat that as a nil state
    96  		if !os.IsNotExist(err) {
    97  			return err
    98  		}
    99  
   100  		f = nil
   101  	}
   102  
   103  	var state *terraform.State
   104  	if f != nil {
   105  		defer f.Close()
   106  		state, err = terraform.ReadState(f)
   107  		if err != nil {
   108  			return err
   109  		}
   110  	}
   111  
   112  	s.state = state
   113  	s.readState = state
   114  	return nil
   115  }