github.com/hernad/nomad@v1.6.112/nomad/state/events.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package state
     5  
     6  import (
     7  	memdb "github.com/hashicorp/go-memdb"
     8  	"github.com/hernad/nomad/nomad/structs"
     9  )
    10  
    11  var MsgTypeEvents = map[structs.MessageType]string{
    12  	structs.NodeRegisterRequestType:                      structs.TypeNodeRegistration,
    13  	structs.NodeDeregisterRequestType:                    structs.TypeNodeDeregistration,
    14  	structs.UpsertNodeEventsType:                         structs.TypeNodeEvent,
    15  	structs.NodePoolUpsertRequestType:                    structs.TypeNodePoolUpserted,
    16  	structs.NodePoolDeleteRequestType:                    structs.TypeNodePoolDeleted,
    17  	structs.EvalUpdateRequestType:                        structs.TypeEvalUpdated,
    18  	structs.AllocClientUpdateRequestType:                 structs.TypeAllocationUpdated,
    19  	structs.JobRegisterRequestType:                       structs.TypeJobRegistered,
    20  	structs.NodeUpdateStatusRequestType:                  structs.TypeNodeEvent,
    21  	structs.JobDeregisterRequestType:                     structs.TypeJobDeregistered,
    22  	structs.JobBatchDeregisterRequestType:                structs.TypeJobBatchDeregistered,
    23  	structs.AllocUpdateDesiredTransitionRequestType:      structs.TypeAllocationUpdateDesiredStatus,
    24  	structs.NodeUpdateEligibilityRequestType:             structs.TypeNodeDrain,
    25  	structs.NodeUpdateDrainRequestType:                   structs.TypeNodeDrain,
    26  	structs.BatchNodeUpdateDrainRequestType:              structs.TypeNodeDrain,
    27  	structs.DeploymentStatusUpdateRequestType:            structs.TypeDeploymentUpdate,
    28  	structs.DeploymentPromoteRequestType:                 structs.TypeDeploymentPromotion,
    29  	structs.DeploymentAllocHealthRequestType:             structs.TypeDeploymentAllocHealth,
    30  	structs.ApplyPlanResultsRequestType:                  structs.TypePlanResult,
    31  	structs.ACLTokenDeleteRequestType:                    structs.TypeACLTokenDeleted,
    32  	structs.ACLTokenUpsertRequestType:                    structs.TypeACLTokenUpserted,
    33  	structs.ACLPolicyDeleteRequestType:                   structs.TypeACLPolicyDeleted,
    34  	structs.ACLPolicyUpsertRequestType:                   structs.TypeACLPolicyUpserted,
    35  	structs.ACLRolesDeleteByIDRequestType:                structs.TypeACLRoleDeleted,
    36  	structs.ACLRolesUpsertRequestType:                    structs.TypeACLRoleUpserted,
    37  	structs.ACLAuthMethodsUpsertRequestType:              structs.TypeACLAuthMethodUpserted,
    38  	structs.ACLAuthMethodsDeleteRequestType:              structs.TypeACLAuthMethodDeleted,
    39  	structs.ACLBindingRulesUpsertRequestType:             structs.TypeACLBindingRuleUpserted,
    40  	structs.ACLBindingRulesDeleteRequestType:             structs.TypeACLBindingRuleDeleted,
    41  	structs.ServiceRegistrationUpsertRequestType:         structs.TypeServiceRegistration,
    42  	structs.ServiceRegistrationDeleteByIDRequestType:     structs.TypeServiceDeregistration,
    43  	structs.ServiceRegistrationDeleteByNodeIDRequestType: structs.TypeServiceDeregistration,
    44  }
    45  
    46  func eventsFromChanges(tx ReadTxn, changes Changes) *structs.Events {
    47  	eventType, ok := MsgTypeEvents[changes.MsgType]
    48  	if !ok {
    49  		return nil
    50  	}
    51  
    52  	var events []structs.Event
    53  	for _, change := range changes.Changes {
    54  		if event, ok := eventFromChange(change); ok {
    55  			event.Type = eventType
    56  			event.Index = changes.Index
    57  			events = append(events, event)
    58  		}
    59  	}
    60  
    61  	return &structs.Events{Index: changes.Index, Events: events}
    62  }
    63  
    64  func eventFromChange(change memdb.Change) (structs.Event, bool) {
    65  	if change.Deleted() {
    66  		switch change.Table {
    67  		case "acl_token":
    68  			before, ok := change.Before.(*structs.ACLToken)
    69  			if !ok {
    70  				return structs.Event{}, false
    71  			}
    72  
    73  			return structs.Event{
    74  				Topic:   structs.TopicACLToken,
    75  				Key:     before.AccessorID,
    76  				Payload: structs.NewACLTokenEvent(before),
    77  			}, true
    78  		case "acl_policy":
    79  			before, ok := change.Before.(*structs.ACLPolicy)
    80  			if !ok {
    81  				return structs.Event{}, false
    82  			}
    83  			return structs.Event{
    84  				Topic: structs.TopicACLPolicy,
    85  				Key:   before.Name,
    86  				Payload: &structs.ACLPolicyEvent{
    87  					ACLPolicy: before,
    88  				},
    89  			}, true
    90  		case TableACLRoles:
    91  			before, ok := change.Before.(*structs.ACLRole)
    92  			if !ok {
    93  				return structs.Event{}, false
    94  			}
    95  			return structs.Event{
    96  				Topic:      structs.TopicACLRole,
    97  				Key:        before.ID,
    98  				FilterKeys: []string{before.Name},
    99  				Payload: &structs.ACLRoleStreamEvent{
   100  					ACLRole: before,
   101  				},
   102  			}, true
   103  		case TableACLAuthMethods:
   104  			before, ok := change.Before.(*structs.ACLAuthMethod)
   105  			if !ok {
   106  				return structs.Event{}, false
   107  			}
   108  			return structs.Event{
   109  				Topic: structs.TopicACLAuthMethod,
   110  				Key:   before.Name,
   111  				Payload: &structs.ACLAuthMethodEvent{
   112  					AuthMethod: before,
   113  				},
   114  			}, true
   115  		case TableACLBindingRules:
   116  			before, ok := change.Before.(*structs.ACLBindingRule)
   117  			if !ok {
   118  				return structs.Event{}, false
   119  			}
   120  			return structs.Event{
   121  				Topic:      structs.TopicACLBindingRule,
   122  				Key:        before.ID,
   123  				FilterKeys: []string{before.AuthMethod},
   124  				Payload: &structs.ACLBindingRuleEvent{
   125  					ACLBindingRule: before,
   126  				},
   127  			}, true
   128  		case "nodes":
   129  			before, ok := change.Before.(*structs.Node)
   130  			if !ok {
   131  				return structs.Event{}, false
   132  			}
   133  
   134  			before = before.Sanitize()
   135  			return structs.Event{
   136  				Topic: structs.TopicNode,
   137  				Key:   before.ID,
   138  				Payload: &structs.NodeStreamEvent{
   139  					Node: before,
   140  				},
   141  			}, true
   142  		case TableNodePools:
   143  			before, ok := change.Before.(*structs.NodePool)
   144  			if !ok {
   145  				return structs.Event{}, false
   146  			}
   147  			return structs.Event{
   148  				Topic: structs.TopicNodePool,
   149  				Key:   before.Name,
   150  				Payload: &structs.NodePoolEvent{
   151  					NodePool: before,
   152  				},
   153  			}, true
   154  		case TableServiceRegistrations:
   155  			before, ok := change.Before.(*structs.ServiceRegistration)
   156  			if !ok {
   157  				return structs.Event{}, false
   158  			}
   159  			return structs.Event{
   160  				Topic: structs.TopicService,
   161  				Key:   before.ID,
   162  				FilterKeys: []string{
   163  					before.JobID,
   164  					before.ServiceName,
   165  				},
   166  				Namespace: before.Namespace,
   167  				Payload: &structs.ServiceRegistrationStreamEvent{
   168  					Service: before,
   169  				},
   170  			}, true
   171  		}
   172  		return structs.Event{}, false
   173  	}
   174  
   175  	switch change.Table {
   176  	case "acl_token":
   177  		after, ok := change.After.(*structs.ACLToken)
   178  		if !ok {
   179  			return structs.Event{}, false
   180  		}
   181  
   182  		return structs.Event{
   183  			Topic:   structs.TopicACLToken,
   184  			Key:     after.AccessorID,
   185  			Payload: structs.NewACLTokenEvent(after),
   186  		}, true
   187  	case "acl_policy":
   188  		after, ok := change.After.(*structs.ACLPolicy)
   189  		if !ok {
   190  			return structs.Event{}, false
   191  		}
   192  		return structs.Event{
   193  			Topic: structs.TopicACLPolicy,
   194  			Key:   after.Name,
   195  			Payload: &structs.ACLPolicyEvent{
   196  				ACLPolicy: after,
   197  			},
   198  		}, true
   199  	case TableACLRoles:
   200  		after, ok := change.After.(*structs.ACLRole)
   201  		if !ok {
   202  			return structs.Event{}, false
   203  		}
   204  		return structs.Event{
   205  			Topic:      structs.TopicACLRole,
   206  			Key:        after.ID,
   207  			FilterKeys: []string{after.Name},
   208  			Payload: &structs.ACLRoleStreamEvent{
   209  				ACLRole: after,
   210  			},
   211  		}, true
   212  	case TableACLAuthMethods:
   213  		after, ok := change.After.(*structs.ACLAuthMethod)
   214  		if !ok {
   215  			return structs.Event{}, false
   216  		}
   217  		return structs.Event{
   218  			Topic: structs.TopicACLAuthMethod,
   219  			Key:   after.Name,
   220  			Payload: &structs.ACLAuthMethodEvent{
   221  				AuthMethod: after,
   222  			},
   223  		}, true
   224  	case TableACLBindingRules:
   225  		after, ok := change.After.(*structs.ACLBindingRule)
   226  		if !ok {
   227  			return structs.Event{}, false
   228  		}
   229  		return structs.Event{
   230  			Topic:      structs.TopicACLBindingRule,
   231  			Key:        after.ID,
   232  			FilterKeys: []string{after.AuthMethod},
   233  			Payload: &structs.ACLBindingRuleEvent{
   234  				ACLBindingRule: after,
   235  			},
   236  		}, true
   237  	case "evals":
   238  		after, ok := change.After.(*structs.Evaluation)
   239  		if !ok {
   240  			return structs.Event{}, false
   241  		}
   242  		return structs.Event{
   243  			Topic: structs.TopicEvaluation,
   244  			Key:   after.ID,
   245  			FilterKeys: []string{
   246  				after.JobID,
   247  				after.DeploymentID,
   248  			},
   249  			Namespace: after.Namespace,
   250  			Payload: &structs.EvaluationEvent{
   251  				Evaluation: after,
   252  			},
   253  		}, true
   254  	case "allocs":
   255  		after, ok := change.After.(*structs.Allocation)
   256  		if !ok {
   257  			return structs.Event{}, false
   258  		}
   259  		alloc := after.Copy()
   260  
   261  		filterKeys := []string{
   262  			alloc.JobID,
   263  			alloc.DeploymentID,
   264  		}
   265  
   266  		// remove job info to help keep size of alloc event down
   267  		alloc.Job = nil
   268  
   269  		return structs.Event{
   270  			Topic:      structs.TopicAllocation,
   271  			Key:        after.ID,
   272  			FilterKeys: filterKeys,
   273  			Namespace:  after.Namespace,
   274  			Payload: &structs.AllocationEvent{
   275  				Allocation: alloc,
   276  			},
   277  		}, true
   278  	case "jobs":
   279  		after, ok := change.After.(*structs.Job)
   280  		if !ok {
   281  			return structs.Event{}, false
   282  		}
   283  		return structs.Event{
   284  			Topic:     structs.TopicJob,
   285  			Key:       after.ID,
   286  			Namespace: after.Namespace,
   287  			Payload: &structs.JobEvent{
   288  				Job: after,
   289  			},
   290  		}, true
   291  	case "nodes":
   292  		after, ok := change.After.(*structs.Node)
   293  		if !ok {
   294  			return structs.Event{}, false
   295  		}
   296  
   297  		after = after.Sanitize()
   298  		return structs.Event{
   299  			Topic: structs.TopicNode,
   300  			Key:   after.ID,
   301  			Payload: &structs.NodeStreamEvent{
   302  				Node: after,
   303  			},
   304  		}, true
   305  	case TableNodePools:
   306  		after, ok := change.After.(*structs.NodePool)
   307  		if !ok {
   308  			return structs.Event{}, false
   309  		}
   310  		return structs.Event{
   311  			Topic: structs.TopicNodePool,
   312  			Key:   after.Name,
   313  			Payload: &structs.NodePoolEvent{
   314  				NodePool: after,
   315  			},
   316  		}, true
   317  	case "deployment":
   318  		after, ok := change.After.(*structs.Deployment)
   319  		if !ok {
   320  			return structs.Event{}, false
   321  		}
   322  		return structs.Event{
   323  			Topic:      structs.TopicDeployment,
   324  			Key:        after.ID,
   325  			Namespace:  after.Namespace,
   326  			FilterKeys: []string{after.JobID},
   327  			Payload: &structs.DeploymentEvent{
   328  				Deployment: after,
   329  			},
   330  		}, true
   331  	case TableServiceRegistrations:
   332  		after, ok := change.After.(*structs.ServiceRegistration)
   333  		if !ok {
   334  			return structs.Event{}, false
   335  		}
   336  		return structs.Event{
   337  			Topic: structs.TopicService,
   338  			Key:   after.ID,
   339  			FilterKeys: []string{
   340  				after.JobID,
   341  				after.ServiceName,
   342  			},
   343  			Namespace: after.Namespace,
   344  			Payload: &structs.ServiceRegistrationStreamEvent{
   345  				Service: after,
   346  			},
   347  		}, true
   348  	}
   349  
   350  	return structs.Event{}, false
   351  }