github.com/outbrain/consul@v1.4.5/agent/user_event_test.go (about)

     1  package agent
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/consul/acl"
     8  	"github.com/hashicorp/consul/agent/structs"
     9  	"github.com/hashicorp/consul/testutil/retry"
    10  )
    11  
    12  func TestValidateUserEventParams(t *testing.T) {
    13  	t.Parallel()
    14  	p := &UserEvent{}
    15  	err := validateUserEventParams(p)
    16  	if err == nil || err.Error() != "User event missing name" {
    17  		t.Fatalf("err: %v", err)
    18  	}
    19  	p.Name = "foo"
    20  
    21  	p.NodeFilter = "("
    22  	err = validateUserEventParams(p)
    23  	if err == nil || !strings.Contains(err.Error(), "Invalid node filter") {
    24  		t.Fatalf("err: %v", err)
    25  	}
    26  
    27  	p.NodeFilter = ""
    28  	p.ServiceFilter = "("
    29  	err = validateUserEventParams(p)
    30  	if err == nil || !strings.Contains(err.Error(), "Invalid service filter") {
    31  		t.Fatalf("err: %v", err)
    32  	}
    33  
    34  	p.ServiceFilter = "foo"
    35  	p.TagFilter = "("
    36  	err = validateUserEventParams(p)
    37  	if err == nil || !strings.Contains(err.Error(), "Invalid tag filter") {
    38  		t.Fatalf("err: %v", err)
    39  	}
    40  
    41  	p.ServiceFilter = ""
    42  	p.TagFilter = "foo"
    43  	err = validateUserEventParams(p)
    44  	if err == nil || !strings.Contains(err.Error(), "tag filter without service") {
    45  		t.Fatalf("err: %v", err)
    46  	}
    47  }
    48  
    49  func TestShouldProcessUserEvent(t *testing.T) {
    50  	t.Parallel()
    51  	a := NewTestAgent(t, t.Name(), "")
    52  	defer a.Shutdown()
    53  
    54  	srv1 := &structs.NodeService{
    55  		ID:      "mysql",
    56  		Service: "mysql",
    57  		Tags:    []string{"test", "foo", "bar", "master"},
    58  		Port:    5000,
    59  	}
    60  	a.State.AddService(srv1, "")
    61  
    62  	p := &UserEvent{}
    63  	if !a.shouldProcessUserEvent(p) {
    64  		t.Fatalf("bad")
    65  	}
    66  
    67  	// Bad node name
    68  	p = &UserEvent{
    69  		NodeFilter: "foobar",
    70  	}
    71  	if a.shouldProcessUserEvent(p) {
    72  		t.Fatalf("bad")
    73  	}
    74  
    75  	// Good node name
    76  	p = &UserEvent{
    77  		NodeFilter: "^Node",
    78  	}
    79  	if !a.shouldProcessUserEvent(p) {
    80  		t.Fatalf("bad")
    81  	}
    82  
    83  	// Bad service name
    84  	p = &UserEvent{
    85  		ServiceFilter: "foobar",
    86  	}
    87  	if a.shouldProcessUserEvent(p) {
    88  		t.Fatalf("bad")
    89  	}
    90  
    91  	// Good service name
    92  	p = &UserEvent{
    93  		ServiceFilter: ".*sql",
    94  	}
    95  	if !a.shouldProcessUserEvent(p) {
    96  		t.Fatalf("bad")
    97  	}
    98  
    99  	// Bad tag name
   100  	p = &UserEvent{
   101  		ServiceFilter: ".*sql",
   102  		TagFilter:     "slave",
   103  	}
   104  	if a.shouldProcessUserEvent(p) {
   105  		t.Fatalf("bad")
   106  	}
   107  
   108  	// Good service name
   109  	p = &UserEvent{
   110  		ServiceFilter: ".*sql",
   111  		TagFilter:     "master",
   112  	}
   113  	if !a.shouldProcessUserEvent(p) {
   114  		t.Fatalf("bad")
   115  	}
   116  }
   117  
   118  func TestIngestUserEvent(t *testing.T) {
   119  	t.Parallel()
   120  	a := NewTestAgent(t, t.Name(), "")
   121  	defer a.Shutdown()
   122  
   123  	for i := 0; i < 512; i++ {
   124  		msg := &UserEvent{LTime: uint64(i), Name: "test"}
   125  		a.ingestUserEvent(msg)
   126  		if a.LastUserEvent() != msg {
   127  			t.Fatalf("bad: %#v", msg)
   128  		}
   129  		events := a.UserEvents()
   130  
   131  		expectLen := 256
   132  		if i < 256 {
   133  			expectLen = i + 1
   134  		}
   135  		if len(events) != expectLen {
   136  			t.Fatalf("bad: %d %d %d", i, expectLen, len(events))
   137  		}
   138  
   139  		counter := i
   140  		for j := len(events) - 1; j >= 0; j-- {
   141  			if events[j].LTime != uint64(counter) {
   142  				t.Fatalf("bad: %#v", events)
   143  			}
   144  			counter--
   145  		}
   146  	}
   147  }
   148  
   149  func TestFireReceiveEvent(t *testing.T) {
   150  	t.Parallel()
   151  	a := NewTestAgent(t, t.Name(), "")
   152  	defer a.Shutdown()
   153  
   154  	srv1 := &structs.NodeService{
   155  		ID:      "mysql",
   156  		Service: "mysql",
   157  		Tags:    []string{"test", "foo", "bar", "master"},
   158  		Port:    5000,
   159  	}
   160  	a.State.AddService(srv1, "")
   161  
   162  	p1 := &UserEvent{Name: "deploy", ServiceFilter: "web"}
   163  	err := a.UserEvent("dc1", "root", p1)
   164  	if err != nil {
   165  		t.Fatalf("err: %v", err)
   166  	}
   167  
   168  	p2 := &UserEvent{Name: "deploy"}
   169  	err = a.UserEvent("dc1", "root", p2)
   170  	if err != nil {
   171  		t.Fatalf("err: %v", err)
   172  	}
   173  	retry.Run(t, func(r *retry.R) {
   174  		if got, want := len(a.UserEvents()), 1; got != want {
   175  			r.Fatalf("got %d events want %d", got, want)
   176  		}
   177  	})
   178  
   179  	last := a.LastUserEvent()
   180  	if last.ID != p2.ID {
   181  		t.Fatalf("bad: %#v", last)
   182  	}
   183  }
   184  
   185  func TestUserEventToken(t *testing.T) {
   186  	t.Parallel()
   187  	a := NewTestAgent(t, t.Name(), TestACLConfig()+`
   188  		acl_default_policy = "deny"
   189  	`)
   190  	defer a.Shutdown()
   191  
   192  	// Create an ACL token
   193  	args := structs.ACLRequest{
   194  		Datacenter: "dc1",
   195  		Op:         structs.ACLSet,
   196  		ACL: structs.ACL{
   197  			Name:  "User token",
   198  			Type:  structs.ACLTokenTypeClient,
   199  			Rules: testEventPolicy,
   200  		},
   201  		WriteRequest: structs.WriteRequest{Token: "root"},
   202  	}
   203  	var token string
   204  	if err := a.RPC("ACL.Apply", &args, &token); err != nil {
   205  		t.Fatalf("err: %v", err)
   206  	}
   207  
   208  	type tcase struct {
   209  		name   string
   210  		expect bool
   211  	}
   212  	cases := []tcase{
   213  		{"foo", false},
   214  		{"bar", false},
   215  		{"baz", true},
   216  		{"zip", false},
   217  	}
   218  	for _, c := range cases {
   219  		event := &UserEvent{Name: c.name}
   220  		err := a.UserEvent("dc1", token, event)
   221  		allowed := !acl.IsErrPermissionDenied(err)
   222  		if allowed != c.expect {
   223  			t.Fatalf("bad: %#v result: %v", c, allowed)
   224  		}
   225  	}
   226  }
   227  
   228  const testEventPolicy = `
   229  event "foo" {
   230  	policy = "deny"
   231  }
   232  event "bar" {
   233  	policy = "read"
   234  }
   235  event "baz" {
   236  	policy = "write"
   237  }
   238  `