Skip to content

Commit

Permalink
Merge branch 'v3' into chore/support-mulitple-config-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
dhurley committed Dec 13, 2024
2 parents 46ef267 + 8d7c4de commit 696d850
Show file tree
Hide file tree
Showing 25 changed files with 369 additions and 85 deletions.
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ require (
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e
golang.org/x/mod v0.21.0
golang.org/x/sync v0.9.0
golang.org/x/sync v0.10.0
google.golang.org/protobuf v1.35.2
)

Expand Down Expand Up @@ -307,9 +307,9 @@ require (
github.com/vardius/message-bus v1.1.5
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.32.0
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/grpc v1.68.0
)
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
Expand Down Expand Up @@ -842,8 +842,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -862,19 +862,19 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
13 changes: 1 addition & 12 deletions internal/collector/otel_collector_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"context"
"errors"
"fmt"
"strings"
"testing"

"github.com/nginx/agent/v3/test/protos"
Expand Down Expand Up @@ -119,23 +118,13 @@ func TestCollector_Init(t *testing.T) {
initError := collector.Init(context.Background(), nil)
require.NoError(t, initError)

validateLog(t, tt.expectedLog, logBuf)
helpers.ValidateLog(t, tt.expectedLog, logBuf)

require.NoError(t, collector.Close(context.TODO()))
})
}
}

func validateLog(t *testing.T, expectedLog string, logBuf *bytes.Buffer) {
t.Helper()

if expectedLog != "" {
if !strings.Contains(logBuf.String(), expectedLog) {
t.Errorf("Expected log to contain %q, but got %q", expectedLog, logBuf.String())
}
}
}

func TestCollector_InitAndClose(t *testing.T) {
conf := types.OTelConfig(t)
conf.Collector.Log.Path = ""
Expand Down
5 changes: 2 additions & 3 deletions internal/command/command_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ import (

"google.golang.org/protobuf/types/known/timestamppb"

"github.com/google/uuid"

mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1"
"github.com/nginx/agent/v3/internal/bus"
"github.com/nginx/agent/v3/internal/config"
"github.com/nginx/agent/v3/internal/datasource/proto"
"github.com/nginx/agent/v3/internal/grpc"
"github.com/nginx/agent/v3/internal/logger"
pkgConfig "github.com/nginx/agent/v3/pkg/config"
Expand Down Expand Up @@ -249,7 +248,7 @@ func (cp *CommandPlugin) createDataPlaneResponse(correlationID string, status mp
) *mpi.DataPlaneResponse {
return &mpi.DataPlaneResponse{
MessageMeta: &mpi.MessageMeta{
MessageId: uuid.NewString(),
MessageId: proto.GenerateMessageID(),
CorrelationId: correlationID,
Timestamp: timestamppb.Now(),
},
Expand Down
7 changes: 2 additions & 5 deletions internal/command/command_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package command
import (
"bytes"
"context"
"strings"
"testing"
"time"

Expand All @@ -18,6 +17,7 @@ import (
"github.com/nginx/agent/v3/internal/bus"
"github.com/nginx/agent/v3/internal/command/commandfakes"
"github.com/nginx/agent/v3/internal/grpc/grpcfakes"
"github.com/nginx/agent/v3/test/helpers"
"github.com/nginx/agent/v3/test/protos"
"github.com/nginx/agent/v3/test/stub"
"github.com/nginx/agent/v3/test/types"
Expand Down Expand Up @@ -211,10 +211,7 @@ func TestMonitorSubscribeChannel(t *testing.T) {

time.Sleep(100 * time.Millisecond)

// Verify the logger was called
if s := logBuf.String(); !strings.Contains(s, "Received management plane request") {
t.Errorf("Unexpected log %s", s)
}
helpers.ValidateLog(t, "Received management plane request", logBuf)

// Clear the log buffer
logBuf.Reset()
Expand Down
19 changes: 8 additions & 11 deletions internal/command/command_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import (
"time"

"github.com/cenkalti/backoff/v4"
"github.com/google/uuid"

mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1"
"github.com/nginx/agent/v3/internal/config"
"github.com/nginx/agent/v3/internal/datasource/proto"
"github.com/nginx/agent/v3/internal/grpc"
"github.com/nginx/agent/v3/internal/logger"

"google.golang.org/protobuf/types/known/timestamppb"

backoffHelpers "github.com/nginx/agent/v3/internal/backoff"
Expand Down Expand Up @@ -89,7 +91,7 @@ func (cs *CommandService) UpdateDataPlaneStatus(

request := &mpi.UpdateDataPlaneStatusRequest{
MessageMeta: &mpi.MessageMeta{
MessageId: uuid.NewString(),
MessageId: proto.GenerateMessageID(),
CorrelationId: correlationID,
Timestamp: timestamppb.Now(),
},
Expand Down Expand Up @@ -139,7 +141,7 @@ func (cs *CommandService) UpdateDataPlaneHealth(ctx context.Context, instanceHea

request := &mpi.UpdateDataPlaneHealthRequest{
MessageMeta: &mpi.MessageMeta{
MessageId: uuid.NewString(),
MessageId: proto.GenerateMessageID(),
CorrelationId: correlationID,
Timestamp: timestamppb.Now(),
},
Expand Down Expand Up @@ -222,7 +224,7 @@ func (cs *CommandService) CreateConnection(

request := &mpi.CreateConnectionRequest{
MessageMeta: &mpi.MessageMeta{
MessageId: uuid.NewString(),
MessageId: proto.GenerateMessageID(),
CorrelationId: correlationID,
Timestamp: timestamppb.Now(),
},
Expand Down Expand Up @@ -318,12 +320,7 @@ func (cs *CommandService) sendResponseForQueuedConfigApplyRequests(
for i := 0; i < indexOfConfigApplyRequest; i++ {
newResponse := response

newMessageID, err := uuid.NewV7()
if err != nil {
slog.DebugContext(ctx, "Failed to create new message ID", "error", err)
} else {
newResponse.GetMessageMeta().MessageId = newMessageID.String()
}
newResponse.GetMessageMeta().MessageId = proto.GenerateMessageID()

request := cs.configApplyRequestQueue[instanceID][i]
newResponse.GetMessageMeta().CorrelationId = request.GetMessageMeta().GetCorrelationId()
Expand All @@ -336,7 +333,7 @@ func (cs *CommandService) sendResponseForQueuedConfigApplyRequests(

backOffCtx, backoffCancel := context.WithTimeout(ctx, cs.agentConfig.Common.MaxElapsedTime)

err = backoff.Retry(
err := backoff.Retry(
cs.sendDataPlaneResponseCallback(ctx, newResponse),
backoffHelpers.Context(backOffCtx, cs.agentConfig.Common),
)
Expand Down
7 changes: 3 additions & 4 deletions internal/command/command_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"context"
"errors"
"log/slog"
"strings"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -184,9 +183,9 @@ func TestCommandService_UpdateDataPlaneStatusSubscribeError(t *testing.T) {
err := commandService.UpdateDataPlaneStatus(ctx, protos.GetHostResource())
require.Error(t, err)

if s := logBuf.String(); !strings.Contains(s, "Failed to send update data plane status") {
t.Errorf("Unexpected log %s", s)
}
helpers.ValidateLog(t, "Failed to send update data plane status", logBuf)

logBuf.Reset()
}

func TestCommandService_CreateConnection(t *testing.T) {
Expand Down
31 changes: 31 additions & 0 deletions internal/datasource/proto/message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) F5, Inc.
//
// This source code is licensed under the Apache License, Version 2.0 license found in the
// LICENSE file in the root directory of this source tree.

package proto

import (
"log/slog"
"time"

"github.com/google/uuid"
agentUuid "github.com/nginx/agent/v3/pkg/uuid"
)

// UUIDGenerator defines a function type for generating UUIDs.
type UUIDGenerator func() (uuid.UUID, error)

// DefaultUUIDGenerator is the production implementation for generating UUIDv7.
var defaultUUIDGenerator UUIDGenerator = uuid.NewUUID

// GenerateMessageID generates a unique message ID, falling back to sha256 and timestamp if UUID generation fails.
func GenerateMessageID() string {
uuidv7, err := defaultUUIDGenerator()
if err != nil {
slog.Debug("Issue generating uuidv7, using sha256 and timestamp instead", "error", err)
return agentUuid.Generate("%s", time.Now().String())
}

return uuidv7.String()
}
128 changes: 128 additions & 0 deletions internal/datasource/proto/message_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright (c) F5, Inc.
//
// This source code is licensed under the Apache License, Version 2.0 license found in the
// LICENSE file in the root directory of this source tree.

package proto

import (
"bytes"
"errors"
"regexp"
"testing"

"github.com/nginx/agent/v3/test/helpers"
"github.com/nginx/agent/v3/test/stub"
"github.com/stretchr/testify/assert"

"github.com/google/uuid"
)

func TestUUIDv7Regex(t *testing.T) {
// Define the UUIDv7 regex
uuidv7Regex := regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)

// Define test cases
tests := []struct {
name string
input string
expectMatch bool
}{
{
name: "Valid UUIDv7 with variant 8",
input: "01876395-3f9d-7c91-89a3-4f57e53a1a4b",
expectMatch: true,
},
{
name: "Valid UUIDv7 with variant a",
input: "01876395-3f9d-7c91-9f00-4f57e53a1a4b",
expectMatch: true,
},
{
name: "Invalid UUIDv7 - wrong version",
input: "01876395-3f9d-6c91-89a3-4f57e53a1a4b",
expectMatch: false,
},
{
name: "Invalid UUIDv7 - wrong variant",
input: "01876395-3f9d-7c91-7a00-4f57e53a1a4b",
expectMatch: false,
},
{
name: "Invalid UUIDv7 - extra characters",
input: "01876395-3f9d-7c91-89a3-4f57e53a1a4b123",
expectMatch: false,
},
{
name: "Invalid UUIDv7 - missing characters",
input: "01876395-3f9d-7c91-89a3-4f57e53a",
expectMatch: false,
},
}

// Iterate over test cases
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
match := uuidv7Regex.MatchString(tt.input)
assert.Equal(t, tt.expectMatch, match, "Regex match result did not match expectation")
})
}
}

func TestGenerateMessageID(t *testing.T) {
tests := []struct {
name string
mockFunc func() (uuid.UUID, error)
expected string
expectError bool
}{
{
name: "Valid UUID generation",
mockFunc: func() (uuid.UUID, error) {
return uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, nil
},
expected: "01020304-0506-0708-090a-0b0c0d0e0f10",
expectError: false,
},
{
name: "Fallback UUID generation due to error",
mockFunc: func() (uuid.UUID, error) {
return uuid.Nil, errors.New("mock error")
},
expected: "", // Fallback UUIDs don't follow a fixed prefix but should not be empty
expectError: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defaultUUIDGenerator = tt.mockFunc

if tt.expectError {
logBuf := &bytes.Buffer{}
stub.StubLoggerWith(logBuf)

got := GenerateMessageID()
assert.NotEmpty(t, got)

// Inspect logs
helpers.ValidateLog(t, "Issue generating uuidv7, using sha256 and timestamp instead", logBuf)

logBuf.Reset()
} else {
got := GenerateMessageID()

assert.Equal(t, tt.expected, got, "Expected UUID string to match")
}

// reset
defaultUUIDGenerator = uuid.NewUUID
})
}
defaultUUIDGenerator = func() (uuid.UUID, error) {
return uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, nil
}

got := GenerateMessageID()
assert.Equal(t, "01020304-0506-0708-090a-0b0c0d0e0f10", got, "Expected correct UUID string")
}
Loading

0 comments on commit 696d850

Please sign in to comment.