Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nginx plus api actions #955

Merged
merged 53 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
0d3ba77
agent parsing stub status, metrics not working yet
aphralG Nov 18, 2024
daaddb9
remove TODO
aphralG Nov 19, 2024
5abe057
Merge branch 'v3' into add-ability-to-use-unix-socket
aphralG Nov 19, 2024
a152d35
revert config changes
aphralG Nov 19, 2024
d7feb70
lint
aphralG Nov 19, 2024
5bd18b7
working unix plus and oss
aphralG Nov 22, 2024
2e7c55f
WIP
aphralG Nov 26, 2024
5b3a821
WIP
aphralG Nov 26, 2024
9c96943
WIP
aphralG Nov 26, 2024
c5d963a
WIP
aphralG Nov 26, 2024
b948bd0
WIP
aphralG Nov 26, 2024
b37dbc6
working oss metrics with unix
aphralG Nov 28, 2024
1b577d8
working plus
aphralG Nov 28, 2024
41b37c2
working plus
aphralG Nov 28, 2024
fbbd6d0
clean up
aphralG Nov 28, 2024
b9c4794
clean up:
aphralG Nov 28, 2024
f6ea17c
clean up:
aphralG Nov 28, 2024
23358c9
clean up
aphralG Nov 28, 2024
8e53d34
add unit tests
aphralG Nov 29, 2024
1b25e59
add unit tests
aphralG Nov 29, 2024
6b8965b
merge v3
aphralG Nov 29, 2024
a28f55b
fix integration tests
aphralG Nov 29, 2024
b431c1f
merge v3
aphralG Nov 29, 2024
5dafe48
update runtime info
aphralG Dec 3, 2024
e92113d
update README
aphralG Dec 5, 2024
f54ee62
Merge branch 'v3' into add-ability-to-use-unix-socket
aphralG Dec 5, 2024
b4ea46e
merge v3
aphralG Dec 5, 2024
06bbe29
add api action request
aphralG Dec 16, 2024
ce81487
merge v3
aphralG Dec 16, 2024
e95edb6
tests WIP
aphralG Dec 17, 2024
a54b119
added tests
aphralG Dec 18, 2024
47e7b5e
merge v3
aphralG Dec 18, 2024
de29b7a
PR feedback
aphralG Dec 19, 2024
34d7f77
feedback
aphralG Dec 19, 2024
6e22018
PR feedback
aphralG Dec 19, 2024
767441c
add tests
aphralG Dec 19, 2024
611e168
feedback
aphralG Dec 19, 2024
1ecfcad
WIP plus api actions
aphralG Dec 19, 2024
b1d0a6c
merge v3
aphralG Dec 19, 2024
aa857a0
add unit tests
aphralG Jan 6, 2025
aaf2526
PR Feedback
aphralG Jan 9, 2025
1d4a50b
PR Feedback
aphralG Jan 9, 2025
dd3e301
PR feedback
aphralG Jan 10, 2025
85115e3
fix empty response from get requests
aphralG Jan 13, 2025
aadb015
PR feedback
aphralG Jan 15, 2025
32c6f74
Merge branch 'v3' into add-nginx-plus-api-actions
aphralG Jan 15, 2025
757be8c
add warning log
aphralG Jan 16, 2025
927414d
increase test coverage, fix spelling
aphralG Jan 17, 2025
8341e37
PR feedback
aphralG Jan 17, 2025
e3f2084
PR feedback
aphralG Jan 17, 2025
0e03b60
PR feedback
aphralG Jan 17, 2025
5b594b5
Merge branch 'v3' into add-nginx-plus-api-actions
aphralG Jan 17, 2025
145571a
Merge branch 'v3' into add-nginx-plus-api-actions
aphralG Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
745 changes: 478 additions & 267 deletions api/grpc/mpi/v1/command.pb.go

Large diffs are not rendered by default.

462 changes: 462 additions & 0 deletions api/grpc/mpi/v1/command.pb.validate.go

Large diffs are not rendered by default.

23 changes: 21 additions & 2 deletions api/grpc/mpi/v1/command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,11 @@ message APIActionRequest {
message NGINXPlusAction {
// types of actions possible with NGINX Plus API
oneof action {
UpdateHTTPUpstreamServers update_http_upstream_servers = 2;
GetHTTPUpstreamServers get_http_upstream_servers = 3;
UpdateHTTPUpstreamServers update_http_upstream_servers = 1;
GetHTTPUpstreamServers get_http_upstream_servers = 2;
UpdateStreamServers update_stream_servers = 3;
GetUpstreams get_upstreams = 4;
GetStreamUpstreams get_stream_upstreams = 5;
}
}

Expand All @@ -223,6 +226,22 @@ message GetHTTPUpstreamServers {
string http_upstream_name = 1;
}

// Update Upstream Stream Servers for an instance
message UpdateStreamServers {
// the name of the upstream stream
string upstream_stream_name = 1;
// a list of upstream stream servers
repeated google.protobuf.Struct servers = 2;
}

// Get Upstreams for an instance
message GetUpstreams {
}

// Get Stream Upstream Servers for an instance
message GetStreamUpstreams {
}

// Request an update on a particular command
message CommandStatusRequest {}

Expand Down
2 changes: 1 addition & 1 deletion api/grpc/mpi/v1/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/grpc/mpi/v1/files.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions docs/proto/protos.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
- [DataPlaneResponse](#mpi-v1-DataPlaneResponse)
- [FileServer](#mpi-v1-FileServer)
- [GetHTTPUpstreamServers](#mpi-v1-GetHTTPUpstreamServers)
- [GetStreamUpstreams](#mpi-v1-GetStreamUpstreams)
- [GetUpstreams](#mpi-v1-GetUpstreams)
- [HealthRequest](#mpi-v1-HealthRequest)
- [HostInfo](#mpi-v1-HostInfo)
- [Instance](#mpi-v1-Instance)
Expand All @@ -74,6 +76,7 @@
- [UpdateDataPlaneStatusRequest](#mpi-v1-UpdateDataPlaneStatusRequest)
- [UpdateDataPlaneStatusResponse](#mpi-v1-UpdateDataPlaneStatusResponse)
- [UpdateHTTPUpstreamServers](#mpi-v1-UpdateHTTPUpstreamServers)
- [UpdateStreamServers](#mpi-v1-UpdateStreamServers)

- [InstanceHealth.InstanceHealthStatus](#mpi-v1-InstanceHealth-InstanceHealthStatus)
- [InstanceMeta.InstanceType](#mpi-v1-InstanceMeta-InstanceType)
Expand Down Expand Up @@ -797,6 +800,26 @@ Get HTTP Upstream Servers for an instance



<a name="mpi-v1-GetStreamUpstreams"></a>

### GetStreamUpstreams
Get Stream Upstream Servers for an instance






<a name="mpi-v1-GetUpstreams"></a>

### GetUpstreams
Get Upstreams for an instance






<a name="mpi-v1-HealthRequest"></a>

### HealthRequest
Expand Down Expand Up @@ -977,6 +1000,9 @@ Perform an action using the NGINX Plus API on an instance
| ----- | ---- | ----- | ----------- |
| update_http_upstream_servers | [UpdateHTTPUpstreamServers](#mpi-v1-UpdateHTTPUpstreamServers) | | |
| get_http_upstream_servers | [GetHTTPUpstreamServers](#mpi-v1-GetHTTPUpstreamServers) | | |
| update_stream_servers | [UpdateStreamServers](#mpi-v1-UpdateStreamServers) | | |
| get_upstreams | [GetUpstreams](#mpi-v1-GetUpstreams) | | |
| get_stream_upstreams | [GetStreamUpstreams](#mpi-v1-GetStreamUpstreams) | | |



Expand Down Expand Up @@ -1136,6 +1162,22 @@ Update HTTP Upstream Servers for an instance




<a name="mpi-v1-UpdateStreamServers"></a>

### UpdateStreamServers
Update Upstream Stream Servers for an instance


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| upstream_stream_name | [string](#string) | | the name of the upstream stream |
| servers | [google.protobuf.Struct](#google-protobuf-Struct) | repeated | a list of upstream stream servers |








Expand Down
190 changes: 155 additions & 35 deletions internal/resource/resource_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type plusAPIErr struct {
Href string `json:"href"`
}

const emptyResponse = "{}"

var _ bus.Plugin = (*Resource)(nil)

func NewResource(agentConfig *config.Config) *Resource {
Expand Down Expand Up @@ -188,53 +190,171 @@ func (r *Resource) handleNginxPlusActionRequest(ctx context.Context, action *mpi

switch action.GetAction().(type) {
case *mpi.NGINXPlusAction_UpdateHttpUpstreamServers:
slog.DebugContext(ctx, "Updating http upstream servers",
"request", action.GetUpdateHttpUpstreamServers())
add, update, del, err := r.resourceService.UpdateHTTPUpstreams(ctx, instance,
action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(),
action.GetUpdateHttpUpstreamServers().GetServers())
if err != nil {
slog.ErrorContext(ctx, "Unable to update HTTP servers of upstream", "request",
action.GetUpdateHttpUpstreamServers(), "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
slog.DebugContext(ctx, "Updating http upstream servers", "request", action.GetUpdateHttpUpstreamServers())
r.handleUpdateHTTPUpstreamServers(ctx, action, instance)
case *mpi.NGINXPlusAction_GetHttpUpstreamServers:
slog.DebugContext(ctx, "Getting http upstream servers", "request", action.GetGetHttpUpstreamServers())
r.handleGetHTTPUpstreamServers(ctx, action, instance)
case *mpi.NGINXPlusAction_UpdateStreamServers:
slog.DebugContext(ctx, "Updating stream servers", "request", action.GetUpdateStreamServers())
r.handleUpdateStreamServers(ctx, action, instance)
case *mpi.NGINXPlusAction_GetStreamUpstreams:
slog.DebugContext(ctx, "Getting stream upstreams", "request", action.GetGetStreamUpstreams())
r.handleGetStreamUpstreams(ctx, instance)
case *mpi.NGINXPlusAction_GetUpstreams:
slog.DebugContext(ctx, "Getting upstreams", "request", action.GetGetUpstreams())
r.handleGetUpstreams(ctx, instance)
default:
slog.DebugContext(ctx, "NGINX Plus action not implemented yet")
}
}

return
}
// nolint: dupl
func (r *Resource) handleUpdateStreamServers(ctx context.Context, action *mpi.NGINXPlusAction, instance *mpi.Instance) {
correlationID := logger.GetCorrelationID(ctx)
instanceID := instance.GetInstanceMeta().GetInstanceId()

slog.DebugContext(ctx, "Successfully updated http upstream servers", "http_upstream_name",
action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), "add", len(add), "update", len(update),
"delete", len(del))
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
"Successfully updated HTTP Upstreams", instanceID, "")
add, update, del, err := r.resourceService.UpdateStreamServers(ctx, instance,
action.GetUpdateStreamServers().GetUpstreamStreamName(), action.GetUpdateStreamServers().GetServers())
if err != nil {
slog.ErrorContext(ctx, "Unable to update stream servers of upstream", "request",
action.GetUpdateHttpUpstreamServers(), "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})

return
}

slog.DebugContext(ctx, "Successfully updated stream upstream servers", "http_upstream_name",
action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), "add", len(add), "update", len(update),
"delete", len(del))

resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
"Successfully updated stream upstream servers", instanceID, "")

r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
}

// nolint: dupl
func (r *Resource) handleGetStreamUpstreams(ctx context.Context, instance *mpi.Instance) {
correlationID := logger.GetCorrelationID(ctx)
instanceID := instance.GetInstanceMeta().GetInstanceId()
streamUpstreamsResponse := emptyResponse

streamUpstreams, err := r.resourceService.GetStreamUpstreams(ctx, instance)
if err != nil {
slog.ErrorContext(ctx, "Unable to get stream upstreams", "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})

case *mpi.NGINXPlusAction_GetHttpUpstreamServers:
slog.DebugContext(ctx, "Getting http upstream servers", "request", action.GetGetHttpUpstreamServers())
upstreams, err := r.resourceService.GetUpstreams(ctx, instance,
action.GetGetHttpUpstreamServers().GetHttpUpstreamName())
if err != nil {
slog.ErrorContext(ctx, "Unable to get HTTP servers of upstream", "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
return
}

return
if streamUpstreams != nil {
streamUpstreamsJSON, jsonErr := json.Marshal(streamUpstreams)
if jsonErr != nil {
slog.ErrorContext(ctx, "Unable to marshal stream upstreams", "err", err)
}
streamUpstreamsResponse = string(streamUpstreamsJSON)
}

upstreamsJSON, err := json.Marshal(upstreams)
if err != nil {
slog.ErrorContext(ctx, "Unable to marshal http upstreams", "err", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
streamUpstreamsResponse, instanceID, "")

r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
}

// nolint: dupl
func (r *Resource) handleGetUpstreams(ctx context.Context, instance *mpi.Instance) {
correlationID := logger.GetCorrelationID(ctx)
instanceID := instance.GetInstanceMeta().GetInstanceId()
upstreamsResponse := emptyResponse

upstreams, err := r.resourceService.GetUpstreams(ctx, instance)
if err != nil {
slog.InfoContext(ctx, "Unable to get upstreams", "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})

return
}

if upstreams != nil {
upstreamsJSON, jsonErr := json.Marshal(upstreams)
if jsonErr != nil {
slog.ErrorContext(ctx, "Unable to marshal upstreams", "err", err)
}
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
string(upstreamsJSON), instanceID, "")
upstreamsResponse = string(upstreamsJSON)
}

resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
upstreamsResponse, instanceID, "")

r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
}

// nolint: dupl
func (r *Resource) handleUpdateHTTPUpstreamServers(ctx context.Context, action *mpi.NGINXPlusAction,
instance *mpi.Instance,
) {
correlationID := logger.GetCorrelationID(ctx)
instanceID := instance.GetInstanceMeta().GetInstanceId()

add, update, del, err := r.resourceService.UpdateHTTPUpstreamServers(ctx, instance,
action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(),
action.GetUpdateHttpUpstreamServers().GetServers())
if err != nil {
slog.ErrorContext(ctx, "Unable to update HTTP servers of upstream", "request",
action.GetUpdateHttpUpstreamServers(), "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
default:
slog.DebugContext(ctx, "NGINX Plus action not implemented yet")

return
}

slog.DebugContext(ctx, "Successfully updated http upstream servers", "http_upstream_name",
action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), "add", len(add), "update", len(update),
"delete", len(del))

resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
"Successfully updated HTTP Upstreams", instanceID, "")

r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
}

func (r *Resource) handleGetHTTPUpstreamServers(ctx context.Context, action *mpi.NGINXPlusAction,
instance *mpi.Instance,
) {
correlationID := logger.GetCorrelationID(ctx)
instanceID := instance.GetInstanceMeta().GetInstanceId()
upstreamsResponse := emptyResponse

upstreams, err := r.resourceService.GetHTTPUpstreamServers(ctx, instance,
action.GetGetHttpUpstreamServers().GetHttpUpstreamName())
if err != nil {
slog.ErrorContext(ctx, "Unable to get HTTP servers of upstream", "error", err)
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE,
"", instanceID, err.Error())
r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})

return
}

if upstreams != nil {
upstreamsJSON, jsonErr := json.Marshal(upstreams)
if jsonErr != nil {
slog.ErrorContext(ctx, "Unable to marshal http upstreams", "err", err)
}
upstreamsResponse = string(upstreamsJSON)
}
resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK,
upstreamsResponse, instanceID, "")

r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp})
}

func (r *Resource) handleWriteConfigSuccessful(ctx context.Context, msg *bus.Message) {
Expand Down
Loading