func TestClient_HasNodeChanged(t *testing.T) { c := testClient(t, nil) defer c.Shutdown() node := c.Node() attrHash, err := hashstructure.Hash(node.Attributes, nil) if err != nil { c.logger.Printf("[DEBUG] client: unable to calculate node attributes hash: %v", err) } // Calculate node meta map hash metaHash, err := hashstructure.Hash(node.Meta, nil) if err != nil { c.logger.Printf("[DEBUG] client: unable to calculate node meta hash: %v", err) } if changed, _, _ := c.hasNodeChanged(attrHash, metaHash); changed { t.Fatalf("Unexpected hash change.") } // Change node attribute node.Attributes["arch"] = "xyz_86" if changed, newAttrHash, _ := c.hasNodeChanged(attrHash, metaHash); !changed { t.Fatalf("Expected hash change in attributes: %d vs %d", attrHash, newAttrHash) } // Change node meta map node.Meta["foo"] = "bar" if changed, _, newMetaHash := c.hasNodeChanged(attrHash, metaHash); !changed { t.Fatalf("Expected hash change in meta map: %d vs %d", metaHash, newMetaHash) } }
// hasNodeChanged calculates a hash for the node attributes- and meta map. // The new hash values are compared against the old (passed-in) hash values to // determine if the node properties have changed. It returns the new hash values // in case they are different from the old hash values. func (c *Client) hasNodeChanged(oldAttrHash uint64, oldMetaHash uint64) (bool, uint64, uint64) { newAttrHash, err := hashstructure.Hash(c.config.Node.Attributes, nil) if err != nil { c.logger.Printf("[DEBUG] client: unable to calculate node attributes hash: %v", err) } // Calculate node meta map hash newMetaHash, err := hashstructure.Hash(c.config.Node.Meta, nil) if err != nil { c.logger.Printf("[DEBUG] client: unable to calculate node meta hash: %v", err) } if newAttrHash != oldAttrHash || newMetaHash != oldMetaHash { return true, newAttrHash, newMetaHash } return false, oldAttrHash, oldMetaHash }
// hashInlineQueryResult calculates the 64-bit FNV-1 hash of an // inline query result. func hashInlineQueryResult(result InlineQueryResult) (string, error) { hash, err := hashstructure.Hash(result, inlineQueryHashOptions) if err != nil { return "", err } return strconv.FormatUint(hash, 16), nil }
// primitiveObjectSetDiff does a set difference of the old and new sets. The // filter parameter can be used to filter a set of primitive fields in the // passed structs. The name corresponds to the name of the passed objects. If // contextual diff is enabled, objects' primtive fields will be returned even if // no diff exists. func primitiveObjectSetDiff(old, new []interface{}, filter []string, name string, contextual bool) []*ObjectDiff { makeSet := func(objects []interface{}) map[string]interface{} { objMap := make(map[string]interface{}, len(objects)) for _, obj := range objects { hash, err := hashstructure.Hash(obj, nil) if err != nil { panic(err) } objMap[fmt.Sprintf("%d", hash)] = obj } return objMap } oldSet := makeSet(old) newSet := makeSet(new) var diffs []*ObjectDiff for k, v := range oldSet { // Deleted if _, ok := newSet[k]; !ok { diffs = append(diffs, primitiveObjectDiff(v, nil, filter, name, contextual)) } } for k, v := range newSet { // Added if _, ok := oldSet[k]; !ok { diffs = append(diffs, primitiveObjectDiff(nil, v, filter, name, contextual)) } } sort.Sort(ObjectDiffs(diffs)) return diffs }
func (j *jsonReader) Parse(changes ...*ChangeSet) (*ChangeSet, error) { var merged map[string]interface{} for _, m := range changes { if len(m.Data) == 0 { m.Data = []byte(`{}`) } var data map[string]interface{} if err := json.Unmarshal(m.Data, &data); err != nil { return nil, err } if err := mergo.MapWithOverwrite(&merged, data); err != nil { return nil, err } } b, err := json.Marshal(merged) if err != nil { return nil, err } h, err := hash.Hash(merged, nil) if err != nil { return nil, err } return &ChangeSet{ Timestamp: time.Now(), Data: b, Checksum: fmt.Sprintf("%x", h), Source: "json", }, nil }
func TestReadWriteStateV1(t *testing.T) { state := &StateV1{ Resources: map[string]*ResourceStateV1{ "foo": &ResourceStateV1{ ID: "bar", ConnInfo: map[string]string{ "type": "ssh", "user": "******", "password": "******", }, }, }, } // Checksum before the write chksum, err := hashstructure.Hash(state, nil) if err != nil { t.Fatalf("hash: %s", err) } buf := new(bytes.Buffer) if err := testWriteStateV1(state, buf); err != nil { t.Fatalf("err: %s", err) } // Checksum after the write chksumAfter, err := hashstructure.Hash(state, nil) if err != nil { t.Fatalf("hash: %s", err) } if chksumAfter != chksum { t.Fatalf("structure changed during serialization!") } actual, err := ReadStateV1(buf) if err != nil { t.Fatalf("err: %s", err) } // ReadState should not restore sensitive information! state.Resources["foo"].ConnInfo = nil if !reflect.DeepEqual(actual, state) { t.Fatalf("bad: %#v", actual) } }
// handleUpdate takes an updated allocation and updates internal state to // reflect the new config for the task. func (r *TaskRunner) handleUpdate(update *structs.Allocation) error { // Extract the task group from the alloc. tg := update.Job.LookupTaskGroup(update.TaskGroup) if tg == nil { return fmt.Errorf("alloc '%s' missing task group '%s'", update.ID, update.TaskGroup) } // Extract the task. var updatedTask *structs.Task for _, t := range tg.Tasks { if t.Name == r.task.Name { updatedTask = t } } if updatedTask == nil { return fmt.Errorf("task group %q doesn't contain task %q", tg.Name, r.task.Name) } // Merge in the task resources updatedTask.Resources = update.TaskResources[updatedTask.Name] // Update will update resources and store the new kill timeout. var mErr multierror.Error r.handleLock.Lock() if r.handle != nil { if err := r.handle.Update(updatedTask); err != nil { mErr.Errors = append(mErr.Errors, fmt.Errorf("updating task resources failed: %v", err)) } } r.handleLock.Unlock() // Update the restart policy. if r.restartTracker != nil { r.restartTracker.SetPolicy(tg.RestartPolicy) } // Hash services returns the hash of the task's services hashServices := func(task *structs.Task) uint64 { h, err := hashstructure.Hash(task.Services, nil) if err != nil { mErr.Errors = append(mErr.Errors, fmt.Errorf("hashing services failed %#v: %v", task.Services, err)) } return h } // Re-register the task to consul if any of the services have changed. if hashServices(updatedTask) != hashServices(r.task) { if err := r.consulService.Register(updatedTask, update); err != nil { mErr.Errors = append(mErr.Errors, fmt.Errorf("updating services with consul failed: %v", err)) } } // Store the updated alloc. r.alloc = update r.task = updatedTask return mErr.ErrorOrNil() }
// ComputeClass computes a derived class for the node based on its attributes. // ComputedClass is a unique id that identifies nodes with a common set of // attributes and capabilities. Thus, when calculating a node's computed class // we avoid including any uniquely identifing fields. func (n *Node) ComputeClass() error { hash, err := hashstructure.Hash(n, nil) if err != nil { return err } n.ComputedClass = fmt.Sprintf("v1:%d", hash) return nil }
// ComputeClass computes a derived class for the node based on its attributes. // ComputedClass is a unique id that identifies nodes with a common set of // attributes and capabilities. Thus, when calculating a node's computed class // we avoid including any uniquely identifing fields. func (n *Node) ComputeClass() error { hash, err := hashstructure.Hash(n, nil) if err != nil { return err } n.ComputedClass = hash return nil }
// private function without terminal prompts func updateSecurityGroups(secGrpList *SecurityGroups, dryRun bool) error { for _, secGrp := range *secGrpList { // Verify the security group class input cfg, err := config.LoadSecurityGroupClass(secGrp.Class) if err != nil { terminal.Information("Skipping Security Group [" + secGrp.Name + "]") terminal.ErrorLine(err.Error()) continue } else { terminal.Information("Found Security Group class configuration for [" + secGrp.Class + "]") } // TODO fmt.Println("\n\n") fmt.Println("aws\n") fmt.Println(secGrp.SecurityGroupGrants) fmt.Println("awsm\n") fmt.Println(cfg.SecurityGroupGrants) fmt.Println("\n\n") hash1, err := hashstructure.Hash(secGrp.SecurityGroupGrants, nil) if err != nil { panic(err) } fmt.Printf("\n\n%d\n\n", hash1) hash2, err := hashstructure.Hash(cfg.SecurityGroupGrants, nil) if err != nil { panic(err) } fmt.Printf("\n\n%d\n\n", hash2) } return nil }
// networkResourceDiffs diffs a set of NetworkResources. If contextual diff is enabled, // non-changed fields will still be returned. func networkResourceDiffs(old, new []*NetworkResource, contextual bool) []*ObjectDiff { makeSet := func(objects []*NetworkResource) map[string]*NetworkResource { objMap := make(map[string]*NetworkResource, len(objects)) for _, obj := range objects { hash, err := hashstructure.Hash(obj, nil) if err != nil { panic(err) } objMap[fmt.Sprintf("%d", hash)] = obj } return objMap } oldSet := makeSet(old) newSet := makeSet(new) var diffs []*ObjectDiff for k, oldV := range oldSet { if newV, ok := newSet[k]; !ok { if diff := oldV.Diff(newV, contextual); diff != nil { diffs = append(diffs, diff) } } } for k, newV := range newSet { if oldV, ok := oldSet[k]; !ok { if diff := oldV.Diff(newV, contextual); diff != nil { diffs = append(diffs, diff) } } } sort.Sort(ObjectDiffs(diffs)) return diffs }
func (m *mdnsRegistry) Register(service *registry.Service, opts ...registry.RegisterOption) error { m.Lock() defer m.Unlock() entries, ok := m.services[service.Name] // first entry, create wildcard used for list queries if !ok { s, err := mdns.NewMDNSService( service.Name, "_services", "", "", 9999, []net.IP{net.ParseIP("0.0.0.0")}, nil, ) if err != nil { return err } srv, err := mdns.NewServer(&mdns.Config{Zone: &mdns.DNSSDService{s}}) if err != nil { return err } // append the wildcard entry entries = append(entries, &mdnsEntry{id: "*", node: srv}) } var gerr error for _, node := range service.Nodes { // create hash of service; uint64 h, err := hash.Hash(node, nil) if err != nil { gerr = err continue } var seen bool var e *mdnsEntry for _, entry := range entries { if node.Id == entry.id { seen = true e = entry break } } // already registered, continue if seen && e.hash == h { continue // hash doesn't match, shutdown } else if seen { e.node.Shutdown() // doesn't exist } else { e = &mdnsEntry{hash: h} } txt, err := encode(&mdnsTxt{ Service: service.Name, Version: service.Version, Endpoints: service.Endpoints, Metadata: node.Metadata, }) if err != nil { gerr = err continue } // we got here, new node s, err := mdns.NewMDNSService( node.Id, service.Name, "", "", node.Port, []net.IP{net.ParseIP(node.Address)}, txt, ) if err != nil { gerr = err continue } srv, err := mdns.NewServer(&mdns.Config{Zone: s}) if err != nil { gerr = err continue } e.id = node.Id e.node = srv entries = append(entries, e) } // save m.services[service.Name] = entries return gerr }
func (p *ECSEnvironmentProperties) ReplacementHash() (uint64, error) { return hashstructure.Hash(p, nil) }
func (p *ECSTaskDefinitionProperties) ReplacementHash() (uint64, error) { return hashstructure.Hash(p, nil) }
func (e *etcdv3Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error { if len(s.Nodes) == 0 { return errors.New("Require at least one node") } //refreshing lease if existing leaseID, ok := e.leases[s.Name] if ok { _, err := e.client.KeepAliveOnce(context.TODO(), leaseID) if err != nil { return err } } var options registry.RegisterOptions for _, o := range opts { o(&options) } // create hash of service; uint64 h, err := hash.Hash(s, nil) if err != nil { return err } // get existing hash e.Lock() v, ok := e.register[s.Name] e.Unlock() // the service is unchanged, skip registering if ok && v == h { return nil } service := ®istry.Service{ Name: s.Name, Version: s.Version, Metadata: s.Metadata, Endpoints: s.Endpoints, } ctx, cancel := context.WithTimeout(context.Background(), e.options.Timeout) defer cancel() var lgr *clientv3.LeaseGrantResponse if options.TTL.Seconds() > 0 { lgr, err = e.client.Grant(ctx, int64(options.TTL.Seconds())) if err != nil { return err } } for _, node := range s.Nodes { service.Nodes = []*registry.Node{node} if lgr != nil { _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service), clientv3.WithLease(lgr.ID)) } else { _, err = e.client.Put(ctx, nodePath(service.Name, node.Id), encode(service)) } if err != nil { return err } } e.Lock() // save our hash of the service e.register[s.Name] = h // save our leaseID of the service if lgr != nil { e.leases[s.Name] = lgr.ID } e.Unlock() return nil }
func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { if len(s.Nodes) == 0 { return errors.New("Require at least one node") } var options RegisterOptions for _, o := range opts { o(&options) } // create hash of service; uint64 h, err := hash.Hash(s, nil) if err != nil { return err } // use first node node := s.Nodes[0] // get existing hash c.Lock() v, ok := c.register[s.Name] c.Unlock() // if it's already registered and matches then just pass the check if ok && v == h { // if the err is nil we're all good, bail out // if not, we don't know what the state is, so full re-register if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { return nil } } // encode the tags tags := encodeMetadata(node.Metadata) tags = append(tags, encodeEndpoints(s.Endpoints)...) tags = append(tags, encodeVersion(s.Version)...) var check *consul.AgentServiceCheck // if the TTL is greater than 0 create an associated check if options.TTL > time.Duration(0) { check = &consul.AgentServiceCheck{ TTL: fmt.Sprintf("%v", options.TTL), } } // register the service if err := c.Client.Agent().ServiceRegister(&consul.AgentServiceRegistration{ ID: node.Id, Name: s.Name, Tags: tags, Port: node.Port, Address: node.Address, Check: check, }); err != nil { return err } // save our hash of the service c.Lock() c.register[s.Name] = h c.Unlock() // if the TTL is 0 we don't mess with the checks if options.TTL == time.Duration(0) { return nil } // pass the healthcheck return c.Client.Agent().PassTTL("service:"+node.Id, "") }
func (m *gossipRegistry) run() { var mtx sync.Mutex updates := map[uint64]*update{} // expiry loop go func() { t := time.NewTicker(ExpiryTick) defer t.Stop() for _ = range t.C { now := time.Now().Unix() mtx.Lock() for k, v := range updates { // check if expiry time has passed if d := (v.Timestamp + v.Expires) - now; d < 0 { // delete from records delete(updates, k) // set to delete v.Action = delAction // fire a new update m.updates <- v } } mtx.Unlock() } }() for u := range m.updates { switch u.Action { case addAction: m.Lock() if service, ok := m.services[u.Service.Name]; !ok { m.services[u.Service.Name] = []*registry.Service{u.Service} } else { m.services[u.Service.Name] = addServices(service, []*registry.Service{u.Service}) } m.Unlock() go m.publish("add", []*registry.Service{u.Service}) // we need to expire the node at some point in the future if u.Expires > 0 { // create a hash of this service if hash, err := hashstructure.Hash(u.Service, nil); err == nil { mtx.Lock() updates[hash] = u mtx.Unlock() } } case delAction: m.Lock() if service, ok := m.services[u.Service.Name]; ok { if services := delServices(service, []*registry.Service{u.Service}); len(services) == 0 { delete(m.services, u.Service.Name) } else { m.services[u.Service.Name] = services } } m.Unlock() go m.publish("delete", []*registry.Service{u.Service}) // delete from expiry checks if hash, err := hashstructure.Hash(u.Service, nil); err == nil { mtx.Lock() delete(updates, hash) mtx.Unlock() } case syncAction: if u.sync == nil { continue } m.RLock() for _, services := range m.services { for _, service := range services { u.sync <- service } go m.publish("add", services) } m.RUnlock() close(u.sync) } } }
func (z *zookeeperRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { if len(s.Nodes) == 0 { return errors.New("Require at least one node") } var options registry.RegisterOptions for _, o := range opts { o(&options) } // create hash of service; uint64 h, err := hash.Hash(s, nil) if err != nil { return err } // get existing hash z.Lock() v, ok := z.register[s.Name] z.Unlock() // the service is unchanged, skip registering if ok && v == h { return nil } service := ®istry.Service{ Name: s.Name, Version: s.Version, Metadata: s.Metadata, Endpoints: s.Endpoints, } for _, node := range s.Nodes { service.Nodes = []*registry.Node{node} exists, _, err := z.client.Exists(nodePath(service.Name, node.Id)) if err != nil { return err } srv, err := encode(service) if err != nil { return err } if exists { _, err := z.client.Set(nodePath(service.Name, node.Id), srv, -1) if err != nil { return err } } else { err := createPath(nodePath(service.Name, node.Id), srv, z.client) if err != nil { return err } } } // save our hash of the service z.Lock() z.register[s.Name] = h z.Unlock() return nil }