github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/state/events.go (about)

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