github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/util.go (about)

     1  package client
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/rand"
     8  
     9  	"github.com/hashicorp/nomad/nomad/structs"
    10  )
    11  
    12  type allocTuple struct {
    13  	exist, updated *structs.Allocation
    14  }
    15  
    16  // diffResult is used to return the sets that result from a diff
    17  type diffResult struct {
    18  	added   []*structs.Allocation
    19  	removed []*structs.Allocation
    20  	updated []allocTuple
    21  	ignore  []*structs.Allocation
    22  }
    23  
    24  func (d *diffResult) GoString() string {
    25  	return fmt.Sprintf("allocs: (added %d) (removed %d) (updated %d) (ignore %d)",
    26  		len(d.added), len(d.removed), len(d.updated), len(d.ignore))
    27  }
    28  
    29  // diffAllocs is used to diff the existing and updated allocations
    30  // to see what has happened.
    31  func diffAllocs(existing []*structs.Allocation, allocs *allocUpdates) *diffResult {
    32  	// Scan the existing allocations
    33  	result := &diffResult{}
    34  	existIdx := make(map[string]struct{})
    35  	for _, exist := range existing {
    36  		// Mark this as existing
    37  		existIdx[exist.ID] = struct{}{}
    38  
    39  		// Check if the alloc was updated or filtered because an update wasn't
    40  		// needed.
    41  		alloc, pulled := allocs.pulled[exist.ID]
    42  		_, filtered := allocs.filtered[exist.ID]
    43  
    44  		// If not updated or filtered, removed
    45  		if !pulled && !filtered {
    46  			result.removed = append(result.removed, exist)
    47  			continue
    48  		}
    49  
    50  		// Check for an update
    51  		if pulled && alloc.AllocModifyIndex > exist.AllocModifyIndex {
    52  			result.updated = append(result.updated, allocTuple{exist, alloc})
    53  			continue
    54  		}
    55  
    56  		// Ignore this
    57  		result.ignore = append(result.ignore, exist)
    58  	}
    59  
    60  	// Scan the updated allocations for any that are new
    61  	for id, pulled := range allocs.pulled {
    62  		if _, ok := existIdx[id]; !ok {
    63  			result.added = append(result.added, pulled)
    64  		}
    65  	}
    66  	return result
    67  }
    68  
    69  // shuffleStrings randomly shuffles the list of strings
    70  func shuffleStrings(list []string) {
    71  	for i := range list {
    72  		j := rand.Intn(i + 1)
    73  		list[i], list[j] = list[j], list[i]
    74  	}
    75  }
    76  
    77  // pre060RestoreState is used to read back in the persisted state for pre v0.6.0
    78  // state
    79  func pre060RestoreState(path string, data interface{}) error {
    80  	buf, err := ioutil.ReadFile(path)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	if err := json.Unmarshal(buf, data); err != nil {
    85  		return fmt.Errorf("failed to decode state: %v", err)
    86  	}
    87  	return nil
    88  }