diff --git a/sdk/messaging/azeventgrid/CHANGELOG.md b/sdk/messaging/azeventgrid/CHANGELOG.md index bd474b266681..fa3c5822fecf 100644 --- a/sdk/messaging/azeventgrid/CHANGELOG.md +++ b/sdk/messaging/azeventgrid/CHANGELOG.md @@ -1,5 +1,7 @@ # Release History -## 0.1.0 (TBD) +## 0.1.0 (2023-07-11) -* Event Grid package for Event Grid Namespaces +### Features Added + +- Initial preview for the Event Grid package for Event Grid Namespaces diff --git a/sdk/messaging/azeventgrid/README.md b/sdk/messaging/azeventgrid/README.md index ba7eaea401b5..cc633144c593 100644 --- a/sdk/messaging/azeventgrid/README.md +++ b/sdk/messaging/azeventgrid/README.md @@ -1,24 +1,65 @@ -# Azure Template Package client library for Go +# Azure Event Grid Client Module for Go -Azure Template Package client library for Go (`aztemplate`) matches necessary patterns that the development team has established to create a unified SDK written in the Go programming language. These libraries follow the Azure SDK Design Guidelines for Go. +[Azure Event Grid](https://learn.microsoft.com/azure/event-grid/overview) is a highly scalable, fully managed Pub Sub message distribution service that offers flexible message consumption patterns. For more information about Event Grid see: [link](https://learn.microsoft.com/azure/event-grid/overview). -The library allows client libraries to expose common functionality in a consistent fashion. Once you learn how to use these APIs in one client library, you will know how to use them in other client libraries. +This client module allows you to publish events and receive events using the [Pull delivery](https://learn.microsoft.com/azure/event-grid/pull-delivery-overview) API. + +Key links: +- [Source code][source] +- [API Reference Documentation][godoc] +- [Product documentation](https://azure.microsoft.com/services/event-grid/) +- [Samples][godoc_examples] ## Getting started -For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) +### Install the package + +Install the Azure Event Grid client module for Go with `go get`: + +```bash +go get github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid +``` + +### Prerequisites + +- Go, version 1.18 or higher +- An [Azure subscription](https://azure.microsoft.com/free/) +- An [Event Grid namespace](https://learn.microsoft.com/azure/event-grid/). +- An Event Grid namespace. You can create an Event Grid Namespace using the [Azure Portal](https://learn.microsoft.com/azure/event-grid/create-view-manage-namespaces). + +### Authenticate the client + +Event Grid clients authenticate using a shared key credential. An example of that can be viewed here: [ExampleNewClientWithSharedKeyCredential][godoc_example_newclient]. # Key concepts -Bullet point list of your library's main concepts. +An Azure Event Grid [**namespace**](https://learn.microsoft.com/azure/event-grid/mqtt-event-grid-namespace-terminology#namespace) can contain multiple **namespace topics**. Publishers publish events to namespace topics. More on creating namespace topics can be found here: [link](https://learn.microsoft.com/azure/event-grid/create-view-manage-namespace-topics). + +To receive events, you must create an **event subscription**, which is associated with a topic. More on creating topic subscriptions can be found here: [link](https://learn.microsoft.com/azure/event-grid/create-view-manage-event-subscriptions). # Examples -Examples of some of the key concepts for your library. +Examples for various scenarios can be found on [pkg.go.dev](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid#pkg-examples) or in the example*_test.go files in our GitHub repo for [azeventgrid](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventgrid). # Troubleshooting -Running into issues? This section should contain details as to what to do there. +### Logging + +This module uses the classification-based logging implementation in `azcore`. To enable console logging for all SDK modules, set the environment variable `AZURE_SDK_GO_LOGGING` to `all`. + +Use the `azcore/log` package to control log event output. + +```go +import ( + "fmt" + azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" +) + +// print log output to stdout +azlog.SetListener(func(event azlog.Event, s string) { + fmt.Printf("[%s] %s\n", event, s) +}) +``` # Next steps @@ -67,3 +108,7 @@ Azure SDK for Go is licensed under the [MIT](https://github.com/Azure/azure-sdk- [azure_sub]: https://azure.microsoft.com/free/ [cloud_shell]: https://docs.microsoft.com/azure/cloud-shell/overview [cloud_shell_bash]: https://shell.azure.com/bash +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/messaging/azeventgrid +[godoc]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid +[godoc_examples]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid#pkg-examples +[godoc_example_newclient]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid#example-NewClientWithSharedKeyCredential diff --git a/sdk/messaging/azeventgrid/autorest.md b/sdk/messaging/azeventgrid/autorest.md index a1a8da9c6050..f2444a5287b0 100644 --- a/sdk/messaging/azeventgrid/autorest.md +++ b/sdk/messaging/azeventgrid/autorest.md @@ -8,15 +8,18 @@ clear-output-folder: false go: true input-file: # This was the commit that everyone used to generate their first official betas. - - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/947c9ce9b20900c6cbc8e95bc083e723d09a9c2c/specification/eventgrid/data-plane/Microsoft.EventGrid/preview/2023-06-01-preview/EventGrid.json + - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/c07d9898ed901330e5ac4996b1bc641adac2e6fd/specification/eventgrid/data-plane/Microsoft.EventGrid/preview/2023-06-01-preview/EventGrid.json + # - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/947c9ce9b20900c6cbc8e95bc083e723d09a9c2c/specification/eventgrid/data-plane/Microsoft.EventGrid/preview/2023-06-01-preview/EventGrid.json license-header: MICROSOFT_MIT_NO_VERSION module: github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid openapi-type: "data-plane" output-folder: ../azeventgrid override-client-name: Client security: "AADToken" -use: "@autorest/go@4.0.0-preview.49" +use: "@autorest/go@4.0.0-preview.52" version: "^3.0.0" +slice-elements-byval: true +remove-non-reference-schema: true directive: # we have to write a little wrapper code for this so we'll hide the public function # for now. @@ -54,6 +57,7 @@ directive: - client.go - models.go - response_types.go + - options.go where: $ transform: return $.replace(/Client(\w+)((?:Options|Response))/g, "$1$2"); # replace references to the "generated" CloudEvent to the actual version in azcore/messaging @@ -61,8 +65,11 @@ directive: - client.go - models.go - response_types.go + - options.go where: $ - transform: return $.replace(/\*CloudEvent/g, "messaging.CloudEvent"); + transform: | + return $.replace(/\[\]CloudEvent/g, "[]messaging.CloudEvent") + .replace(/\*CloudEvent/g, "messaging.CloudEvent"); # remove the 'Interface any' that's generated for an empty response object. - from: diff --git a/sdk/messaging/azeventgrid/client.go b/sdk/messaging/azeventgrid/client.go index 6656aff2cd50..77bdc3b0be5a 100644 --- a/sdk/messaging/azeventgrid/client.go +++ b/sdk/messaging/azeventgrid/client.go @@ -3,9 +3,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. // Changes may cause incorrect behavior and will be lost if the code is regenerated. -// DO NOT EDIT. package azeventgrid @@ -42,18 +41,21 @@ type Client struct { // - lockTokens - AcknowledgeOptions. // - options - AcknowledgeCloudEventsOptions contains the optional parameters for the Client.AcknowledgeCloudEvents method. func (client *Client) AcknowledgeCloudEvents(ctx context.Context, topicName string, eventSubscriptionName string, lockTokens AcknowledgeOptions, options *AcknowledgeCloudEventsOptions) (AcknowledgeCloudEventsResponse, error) { + var err error req, err := client.acknowledgeCloudEventsCreateRequest(ctx, topicName, eventSubscriptionName, lockTokens, options) if err != nil { return AcknowledgeCloudEventsResponse{}, err } - resp, err := client.internal.Pipeline().Do(req) + httpResp, err := client.internal.Pipeline().Do(req) if err != nil { return AcknowledgeCloudEventsResponse{}, err } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return AcknowledgeCloudEventsResponse{}, runtime.NewResponseError(resp) + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return AcknowledgeCloudEventsResponse{}, err } - return client.acknowledgeCloudEventsHandleResponse(resp) + resp, err := client.acknowledgeCloudEventsHandleResponse(httpResp) + return resp, err } // acknowledgeCloudEventsCreateRequest creates the AcknowledgeCloudEvents request. @@ -102,16 +104,18 @@ func (client *Client) acknowledgeCloudEventsHandleResponse(resp *http.Response) // - events - Array of Cloud Events being published. // - options - PublishCloudEventsOptions contains the optional parameters for the Client.PublishCloudEvents method. func (client *Client) internalPublishCloudEvents(ctx context.Context, topicName string, events []messaging.CloudEvent, options *PublishCloudEventsOptions) (PublishCloudEventsResponse, error) { + var err error req, err := client.publishCloudEventsCreateRequest(ctx, topicName, events, options) if err != nil { return PublishCloudEventsResponse{}, err } - resp, err := client.internal.Pipeline().Do(req) + httpResp, err := client.internal.Pipeline().Do(req) if err != nil { return PublishCloudEventsResponse{}, err } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return PublishCloudEventsResponse{}, runtime.NewResponseError(resp) + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return PublishCloudEventsResponse{}, err } return PublishCloudEventsResponse{}, nil } @@ -145,18 +149,21 @@ func (client *Client) publishCloudEventsCreateRequest(ctx context.Context, topic // - eventSubscriptionName - Event Subscription Name. // - options - ReceiveCloudEventsOptions contains the optional parameters for the Client.ReceiveCloudEvents method. func (client *Client) ReceiveCloudEvents(ctx context.Context, topicName string, eventSubscriptionName string, options *ReceiveCloudEventsOptions) (ReceiveCloudEventsResponse, error) { + var err error req, err := client.receiveCloudEventsCreateRequest(ctx, topicName, eventSubscriptionName, options) if err != nil { return ReceiveCloudEventsResponse{}, err } - resp, err := client.internal.Pipeline().Do(req) + httpResp, err := client.internal.Pipeline().Do(req) if err != nil { return ReceiveCloudEventsResponse{}, err } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return ReceiveCloudEventsResponse{}, runtime.NewResponseError(resp) + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ReceiveCloudEventsResponse{}, err } - return client.receiveCloudEventsHandleResponse(resp) + resp, err := client.receiveCloudEventsHandleResponse(httpResp) + return resp, err } // receiveCloudEventsCreateRequest creates the ReceiveCloudEvents request. @@ -205,18 +212,21 @@ func (client *Client) receiveCloudEventsHandleResponse(resp *http.Response) (Rec // - lockTokens - RejectOptions // - options - RejectCloudEventsOptions contains the optional parameters for the Client.RejectCloudEvents method. func (client *Client) RejectCloudEvents(ctx context.Context, topicName string, eventSubscriptionName string, lockTokens RejectOptions, options *RejectCloudEventsOptions) (RejectCloudEventsResponse, error) { + var err error req, err := client.rejectCloudEventsCreateRequest(ctx, topicName, eventSubscriptionName, lockTokens, options) if err != nil { return RejectCloudEventsResponse{}, err } - resp, err := client.internal.Pipeline().Do(req) + httpResp, err := client.internal.Pipeline().Do(req) if err != nil { return RejectCloudEventsResponse{}, err } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return RejectCloudEventsResponse{}, runtime.NewResponseError(resp) + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return RejectCloudEventsResponse{}, err } - return client.rejectCloudEventsHandleResponse(resp) + resp, err := client.rejectCloudEventsHandleResponse(httpResp) + return resp, err } // rejectCloudEventsCreateRequest creates the RejectCloudEvents request. @@ -264,18 +274,21 @@ func (client *Client) rejectCloudEventsHandleResponse(resp *http.Response) (Reje // - lockTokens - ReleaseOptions // - options - ReleaseCloudEventsOptions contains the optional parameters for the Client.ReleaseCloudEvents method. func (client *Client) ReleaseCloudEvents(ctx context.Context, topicName string, eventSubscriptionName string, lockTokens ReleaseOptions, options *ReleaseCloudEventsOptions) (ReleaseCloudEventsResponse, error) { + var err error req, err := client.releaseCloudEventsCreateRequest(ctx, topicName, eventSubscriptionName, lockTokens, options) if err != nil { return ReleaseCloudEventsResponse{}, err } - resp, err := client.internal.Pipeline().Do(req) + httpResp, err := client.internal.Pipeline().Do(req) if err != nil { return ReleaseCloudEventsResponse{}, err } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return ReleaseCloudEventsResponse{}, runtime.NewResponseError(resp) + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ReleaseCloudEventsResponse{}, err } - return client.releaseCloudEventsHandleResponse(resp) + resp, err := client.releaseCloudEventsHandleResponse(httpResp) + return resp, err } // releaseCloudEventsCreateRequest creates the ReleaseCloudEvents request. diff --git a/sdk/messaging/azeventgrid/client_test.go b/sdk/messaging/azeventgrid/client_test.go index e74f235f3a4f..0d1441b5972d 100644 --- a/sdk/messaging/azeventgrid/client_test.go +++ b/sdk/messaging/azeventgrid/client_test.go @@ -35,21 +35,21 @@ func TestFailedAck(t *testing.T) { require.NoError(t, err) ackResp, err := c.AcknowledgeCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.AcknowledgeOptions{ - LockTokens: []*string{recvResp.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*recvResp.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, ackResp.FailedLockTokens) - require.Equal(t, []*string{recvResp.Value[0].BrokerProperties.LockToken}, ackResp.SucceededLockTokens) + require.Equal(t, []string{*recvResp.Value[0].BrokerProperties.LockToken}, ackResp.SucceededLockTokens) // now let's try to do stuff with an "out of date" token t.Run("AcknowledgeCloudEvents", func(t *testing.T) { resp, err := c.AcknowledgeCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.AcknowledgeOptions{ - LockTokens: []*string{recvResp.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*recvResp.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, resp.SucceededLockTokens) // TODO: these two fields are not symmetrical - FailedLockTokens carries a reason. - require.Equal(t, []*azeventgrid.FailedLockToken{ + require.Equal(t, []azeventgrid.FailedLockToken{ { LockToken: recvResp.Value[0].BrokerProperties.LockToken, ErrorCode: to.Ptr("TokenLost"), @@ -60,12 +60,12 @@ func TestFailedAck(t *testing.T) { t.Run("RejectCloudEvents", func(t *testing.T) { resp, err := c.RejectCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.RejectOptions{ - LockTokens: []*string{recvResp.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*recvResp.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, resp.SucceededLockTokens) // TODO: these two fields are not symmetrical - FailedLockTokens carries a reason. - require.Equal(t, []*azeventgrid.FailedLockToken{ + require.Equal(t, []azeventgrid.FailedLockToken{ { LockToken: recvResp.Value[0].BrokerProperties.LockToken, ErrorCode: to.Ptr("TokenLost"), @@ -74,14 +74,14 @@ func TestFailedAck(t *testing.T) { }, resp.FailedLockTokens) }) - t.Run("AcknowledgeCloudEvents", func(t *testing.T) { + t.Run("ReleaseCloudEvents", func(t *testing.T) { resp, err := c.ReleaseCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.ReleaseOptions{ - LockTokens: []*string{recvResp.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*recvResp.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, resp.SucceededLockTokens) // TODO: these two fields are not symmetrical - FailedLockTokens carries a reason. - require.Equal(t, []*azeventgrid.FailedLockToken{ + require.Equal(t, []azeventgrid.FailedLockToken{ { LockToken: recvResp.Value[0].BrokerProperties.LockToken, ErrorCode: to.Ptr("TokenLost"), @@ -110,27 +110,27 @@ func TestPartialAckFailure(t *testing.T) { // we'll ack one now so we can force a failure to happen. ackResp, err := c.AcknowledgeCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.AcknowledgeOptions{ - LockTokens: []*string{events.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*events.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, ackResp.FailedLockTokens) // this will result in a partial failure. ackResp, err = c.AcknowledgeCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.AcknowledgeOptions{ - LockTokens: []*string{ - events.Value[0].BrokerProperties.LockToken, - events.Value[1].BrokerProperties.LockToken, + LockTokens: []string{ + *events.Value[0].BrokerProperties.LockToken, + *events.Value[1].BrokerProperties.LockToken, }, }, nil) require.NoError(t, err) - require.Equal(t, []*azeventgrid.FailedLockToken{ + require.Equal(t, []azeventgrid.FailedLockToken{ { LockToken: events.Value[0].BrokerProperties.LockToken, ErrorCode: to.Ptr("TokenLost"), ErrorDescription: to.Ptr("Token has expired."), }, }, ackResp.FailedLockTokens) - require.Equal(t, []*string{events.Value[1].BrokerProperties.LockToken}, ackResp.SucceededLockTokens) + require.Equal(t, []string{*events.Value[1].BrokerProperties.LockToken}, ackResp.SucceededLockTokens) } func TestReject(t *testing.T) { @@ -155,7 +155,7 @@ func TestReject(t *testing.T) { require.Equal(t, int32(1), *events.Value[0].BrokerProperties.DeliveryCount, "DeliveryCount starts at 1") rejectResp, err := c.RejectCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.RejectOptions{ - LockTokens: []*string{events.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*events.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, rejectResp.FailedLockTokens) @@ -185,7 +185,7 @@ func TestRelease(t *testing.T) { require.Equal(t, int32(1), *events.Value[0].BrokerProperties.DeliveryCount, "DeliveryCount starts at 1") rejectResp, err := c.ReleaseCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.ReleaseOptions{ - LockTokens: []*string{events.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*events.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, rejectResp.FailedLockTokens) @@ -195,7 +195,7 @@ func TestRelease(t *testing.T) { require.Equal(t, int32(2), *events.Value[0].BrokerProperties.DeliveryCount, "DeliveryCount is incremented") ackResp, err := c.AcknowledgeCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, azeventgrid.AcknowledgeOptions{ - LockTokens: []*string{events.Value[0].BrokerProperties.LockToken}, + LockTokens: []string{*events.Value[0].BrokerProperties.LockToken}, }, nil) require.NoError(t, err) require.Empty(t, ackResp.FailedLockTokens) @@ -267,7 +267,7 @@ func TestPublishingAndReceivingCloudEvents(t *testing.T) { for _, e := range resp.Value { require.NotNil(t, e.BrokerProperties.LockToken) - ackArgs.LockTokens = append(ackArgs.LockTokens, e.BrokerProperties.LockToken) + ackArgs.LockTokens = append(ackArgs.LockTokens, *e.BrokerProperties.LockToken) } ackResp, err := c.AcknowledgeCloudEvents(context.Background(), c.TestVars.Topic, c.TestVars.Subscription, ackArgs, nil) diff --git a/sdk/messaging/azeventgrid/example_publish_and_receive_test.go b/sdk/messaging/azeventgrid/example_publish_and_receive_test.go new file mode 100644 index 000000000000..5060af75b631 --- /dev/null +++ b/sdk/messaging/azeventgrid/example_publish_and_receive_test.go @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azeventgrid_test + +import ( + "context" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/messaging" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid" +) + +func Example_publishAndReceiveCloudEvents() { + endpoint := os.Getenv("EVENTGRID_ENDPOINT") + key := os.Getenv("EVENTGRID_KEY") + topicName := os.Getenv("EVENTGRID_TOPIC") + subscriptionName := os.Getenv("EVENTGRID_SUBSCRIPTION") + + client, err := azeventgrid.NewClientWithSharedKeyCredential(endpoint, key, nil) + + if err != nil { + panic(err) + } + + eventWithString, err := publishAndReceiveEvent(client, topicName, subscriptionName, "hello world") + + if err != nil { + panic(err) + } + + fmt.Printf("ID: %s\n", eventWithString.Event.ID) + fmt.Printf(" Body: %s\n", eventWithString.Event.Data.(string)) + fmt.Printf(" Delivery count: %d\n", eventWithString.BrokerProperties.DeliveryCount) + + eventWithBytes, err := publishAndReceiveEvent(client, topicName, subscriptionName, []byte{0, 1, 2}) + + if err != nil { + panic(err) + } + + fmt.Printf("ID: %s\n", eventWithBytes.Event.ID) + fmt.Printf(" Body: %s\n", hex.EncodeToString(eventWithBytes.Event.Data.([]byte))) + fmt.Printf(" Delivery count: %d\n", eventWithBytes.BrokerProperties.DeliveryCount) + + type SampleData struct { + Name string `json:"name"` + } + + eventWithStruct, err := publishAndReceiveEvent(client, topicName, subscriptionName, SampleData{Name: "hello"}) + + if err != nil { + panic(err) + } + + var sampleData *SampleData + if err := json.Unmarshal(eventWithStruct.Event.Data.(json.RawMessage), &sampleData); err != nil { + panic(err) + } + + fmt.Printf("ID: %s\n", eventWithStruct.Event.ID) + fmt.Printf(" Body: %#v\n", sampleData) + fmt.Printf(" Delivery count: %d\n", eventWithStruct.BrokerProperties.DeliveryCount) +} + +func publishAndReceiveEvent(client *azeventgrid.Client, topicName string, subscriptionName string, payload any) (azeventgrid.ReceiveDetails, error) { + event, err := messaging.NewCloudEvent("source", "eventType", payload, nil) + + if err != nil { + return azeventgrid.ReceiveDetails{}, err + } + + eventsToSend := []messaging.CloudEvent{ + event, + } + + // NOTE: we're sending a single event as an example. For better efficiency it's best if you send + // multiple events at a time. + _, err = client.PublishCloudEvents(context.TODO(), topicName, eventsToSend, nil) + + if err != nil { + return azeventgrid.ReceiveDetails{}, err + } + + events, err := client.ReceiveCloudEvents(context.TODO(), topicName, subscriptionName, &azeventgrid.ReceiveCloudEventsOptions{ + MaxEvents: to.Ptr(int32(1)), + + // Wait for 60 seconds for events. + MaxWaitTime: to.Ptr[int32](60), + }) + + if err != nil { + return azeventgrid.ReceiveDetails{}, err + } + + if len(events.Value) == 0 { + return azeventgrid.ReceiveDetails{}, errors.New("no events received") + } + + // This acknowledges the event and causes it to be deleted from the subscription. + // Other options are: + // - client.ReleaseCloudEvents, which invalidates our event lock and allows another subscriber to receive the event. + // - client.RejectCloudEvents, which rejects the event. + // If dead-lettering is configured, the event will be moved into the dead letter queue. + // Otherwise the event is deleted. + ackResp, err := client.AcknowledgeCloudEvents(context.TODO(), topicName, subscriptionName, azeventgrid.AcknowledgeOptions{ + LockTokens: []string{ + *events.Value[0].BrokerProperties.LockToken, + }, + }, nil) + + if err != nil { + return azeventgrid.ReceiveDetails{}, err + } + + if len(ackResp.FailedLockTokens) > 0 { + // some events failed when we tried to acknowledge them. + for _, failed := range ackResp.FailedLockTokens { + fmt.Printf("Failed to acknowledge event with lock token %s: %s\n", *failed.LockToken, *failed.ErrorDescription) + } + + return azeventgrid.ReceiveDetails{}, errors.New("failed to acknowledge event") + } + + return events.Value[0], nil +} diff --git a/sdk/messaging/azeventgrid/example_test.go b/sdk/messaging/azeventgrid/example_test.go new file mode 100644 index 000000000000..cffb5045ffaa --- /dev/null +++ b/sdk/messaging/azeventgrid/example_test.go @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azeventgrid_test + +import ( + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventgrid" +) + +func ExampleNewClientWithSharedKeyCredential() { + endpoint := os.Getenv("EVENTGRID_ENDPOINT") + sharedKey := os.Getenv("EVENTGRID_KEY") + + client, err := azeventgrid.NewClientWithSharedKeyCredential(endpoint, sharedKey, nil) + + if err != nil { + panic(err) + } + + _ = client // ignore +} diff --git a/sdk/messaging/azeventgrid/models.go b/sdk/messaging/azeventgrid/models.go index 2784b50973a8..1571ba04979c 100644 --- a/sdk/messaging/azeventgrid/models.go +++ b/sdk/messaging/azeventgrid/models.go @@ -3,9 +3,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. // Changes may cause incorrect behavior and will be lost if the code is regenerated. -// DO NOT EDIT. package azeventgrid @@ -14,17 +13,17 @@ import "github.com/Azure/azure-sdk-for-go/sdk/azcore/messaging" // AcknowledgeOptions - Array of lock token strings for the corresponding received Cloud Events to be acknowledged. type AcknowledgeOptions struct { // REQUIRED; String array of lock tokens. - LockTokens []*string + LockTokens []string } // AcknowledgeResult - The result of the Acknowledge operation. type AcknowledgeResult struct { // REQUIRED; Array of LockToken values for failed cloud events. Each LockToken includes the lock token value along with the // related error information (namely, the error code and description). - FailedLockTokens []*FailedLockToken + FailedLockTokens []FailedLockToken // REQUIRED; Array of lock tokens values for the successfully acknowledged cloud events. - SucceededLockTokens []*string + SucceededLockTokens []string } // BrokerProperties - Properties of the Event Broker operation. @@ -36,38 +35,6 @@ type BrokerProperties struct { LockToken *string } -// AcknowledgeCloudEventsOptions contains the optional parameters for the Client.AcknowledgeCloudEvents method. -type AcknowledgeCloudEventsOptions struct { - // placeholder for future optional parameters -} - -// PublishCloudEventsOptions contains the optional parameters for the Client.PublishCloudEvents method. -type PublishCloudEventsOptions struct { - // placeholder for future optional parameters -} - -// ReceiveCloudEventsOptions contains the optional parameters for the Client.ReceiveCloudEvents method. -type ReceiveCloudEventsOptions struct { - // Max Events count to be received. Minimum value is 1, while maximum value is 100 events. If not specified, the default value - // is 1. - MaxEvents *int32 - // Max wait time value for receive operation in Seconds. It is the time in seconds that the server approximately waits for - // the availability of an event and responds to the request. If an event is - // available, the broker responds immediately to the client. Minimum value is 10 seconds, while maximum value is 120 seconds. - // If not specified, the default value is 60 seconds. - MaxWaitTime *int32 -} - -// RejectCloudEventsOptions contains the optional parameters for the Client.RejectCloudEvents method. -type RejectCloudEventsOptions struct { - // placeholder for future optional parameters -} - -// ReleaseCloudEventsOptions contains the optional parameters for the Client.ReleaseCloudEvents method. -type ReleaseCloudEventsOptions struct { - // placeholder for future optional parameters -} - // FailedLockToken - Failed LockToken information. type FailedLockToken struct { // REQUIRED; Error code related to the token. Example of such error codes are BadToken: which indicates the Token is not formatted @@ -94,37 +61,37 @@ type ReceiveDetails struct { // ReceiveResult - Details of the Receive operation response. type ReceiveResult struct { // REQUIRED; Array of receive responses, one per cloud event. - Value []*ReceiveDetails + Value []ReceiveDetails } // RejectOptions - Array of lock token strings for the corresponding received Cloud Events to be rejected. type RejectOptions struct { // REQUIRED; String array of lock tokens. - LockTokens []*string + LockTokens []string } // RejectResult - The result of the Reject operation. type RejectResult struct { // REQUIRED; Array of LockToken values for failed cloud events. Each LockToken includes the lock token value along with the // related error information (namely, the error code and description). - FailedLockTokens []*FailedLockToken + FailedLockTokens []FailedLockToken // REQUIRED; Array of lock tokens values for the successfully rejected cloud events. - SucceededLockTokens []*string + SucceededLockTokens []string } // ReleaseOptions - Array of lock token strings for the corresponding received Cloud Events to be released. type ReleaseOptions struct { // REQUIRED; String array of lock tokens. - LockTokens []*string + LockTokens []string } // ReleaseResult - The result of the Release operation. type ReleaseResult struct { // REQUIRED; Array of LockToken values for failed cloud events. Each LockToken includes the lock token value along with the // related error information (namely, the error code and description). - FailedLockTokens []*FailedLockToken + FailedLockTokens []FailedLockToken // REQUIRED; Array of lock tokens values for the successfully released cloud events. - SucceededLockTokens []*string + SucceededLockTokens []string } diff --git a/sdk/messaging/azeventgrid/models_serde.go b/sdk/messaging/azeventgrid/models_serde.go index 736f0a5b1835..645ce48d687b 100644 --- a/sdk/messaging/azeventgrid/models_serde.go +++ b/sdk/messaging/azeventgrid/models_serde.go @@ -3,9 +3,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. // Changes may cause incorrect behavior and will be lost if the code is regenerated. -// DO NOT EDIT. package azeventgrid diff --git a/sdk/messaging/azeventgrid/options.go b/sdk/messaging/azeventgrid/options.go new file mode 100644 index 000000000000..865aea4ff575 --- /dev/null +++ b/sdk/messaging/azeventgrid/options.go @@ -0,0 +1,42 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azeventgrid + +// AcknowledgeCloudEventsOptions contains the optional parameters for the Client.AcknowledgeCloudEvents method. +type AcknowledgeCloudEventsOptions struct { + // placeholder for future optional parameters +} + +// PublishCloudEventsOptions contains the optional parameters for the Client.PublishCloudEvents method. +type PublishCloudEventsOptions struct { + // placeholder for future optional parameters +} + +// ReceiveCloudEventsOptions contains the optional parameters for the Client.ReceiveCloudEvents method. +type ReceiveCloudEventsOptions struct { + // Max Events count to be received. Minimum value is 1, while maximum value is 100 events. If not specified, the default value + // is 1. + MaxEvents *int32 + + // Max wait time value for receive operation in Seconds. It is the time in seconds that the server approximately waits for + // the availability of an event and responds to the request. If an event is + // available, the broker responds immediately to the client. Minimum value is 10 seconds, while maximum value is 120 seconds. + // If not specified, the default value is 60 seconds. + MaxWaitTime *int32 +} + +// RejectCloudEventsOptions contains the optional parameters for the Client.RejectCloudEvents method. +type RejectCloudEventsOptions struct { + // placeholder for future optional parameters +} + +// ReleaseCloudEventsOptions contains the optional parameters for the Client.ReleaseCloudEvents method. +type ReleaseCloudEventsOptions struct { + // placeholder for future optional parameters +} diff --git a/sdk/messaging/azeventgrid/response_types.go b/sdk/messaging/azeventgrid/response_types.go index 9c7bc32d5030..246767dad25b 100644 --- a/sdk/messaging/azeventgrid/response_types.go +++ b/sdk/messaging/azeventgrid/response_types.go @@ -3,14 +3,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. // Changes may cause incorrect behavior and will be lost if the code is regenerated. -// DO NOT EDIT. package azeventgrid // AcknowledgeCloudEventsResponse contains the response from method Client.AcknowledgeCloudEvents. type AcknowledgeCloudEventsResponse struct { + // The result of the Acknowledge operation. AcknowledgeResult } @@ -21,15 +21,18 @@ type PublishCloudEventsResponse struct { // ReceiveCloudEventsResponse contains the response from method Client.ReceiveCloudEvents. type ReceiveCloudEventsResponse struct { + // Details of the Receive operation response. ReceiveResult } // RejectCloudEventsResponse contains the response from method Client.RejectCloudEvents. type RejectCloudEventsResponse struct { + // The result of the Reject operation. RejectResult } // ReleaseCloudEventsResponse contains the response from method Client.ReleaseCloudEvents. type ReleaseCloudEventsResponse struct { + // The result of the Release operation. ReleaseResult } diff --git a/sdk/messaging/azeventgrid/sample.env b/sdk/messaging/azeventgrid/sample.env new file mode 100644 index 000000000000..7d71c0289419 --- /dev/null +++ b/sdk/messaging/azeventgrid/sample.env @@ -0,0 +1,4 @@ +EVENTGRID_KEY= +EVENTGRID_ENDPOINT= +EVENTGRID_TOPIC= +EVENTGRID_SUBSCRIPTION= diff --git a/sdk/messaging/azeventgrid/shared_test.go b/sdk/messaging/azeventgrid/shared_test.go index d41053270431..3fe74eccfc90 100644 --- a/sdk/messaging/azeventgrid/shared_test.go +++ b/sdk/messaging/azeventgrid/shared_test.go @@ -241,10 +241,10 @@ func purgePreviousEvents(t *testing.T, c *azeventgrid.Client, testVars testVars) }) require.NoError(t, err) - var lockTokens []*string + var lockTokens []string for _, e := range events.Value { - lockTokens = append(lockTokens, e.BrokerProperties.LockToken) + lockTokens = append(lockTokens, *e.BrokerProperties.LockToken) } if len(lockTokens) > 0 { diff --git a/sdk/messaging/azeventgrid/time_rfc3339.go b/sdk/messaging/azeventgrid/time_rfc3339.go index f8fbc9ae9dfc..541e52ffb7c8 100644 --- a/sdk/messaging/azeventgrid/time_rfc3339.go +++ b/sdk/messaging/azeventgrid/time_rfc3339.go @@ -3,9 +3,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. // Changes may cause incorrect behavior and will be lost if the code is regenerated. -// DO NOT EDIT. package azeventgrid diff --git a/sdk/messaging/azeventhubs/README.md b/sdk/messaging/azeventhubs/README.md index bc92a4cc0fc2..bd724a1810be 100644 --- a/sdk/messaging/azeventhubs/README.md +++ b/sdk/messaging/azeventhubs/README.md @@ -32,7 +32,7 @@ go get github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs ### Authenticate the client -Event Hub clients are created using an Event Hub a credential from the [Azure Identity package][azure_identity_pkg], like [DefaultAzureCredential][default_azure_credential]. +Event Hub clients are created using a TokenCredential from the [Azure Identity package][azure_identity_pkg], like [DefaultAzureCredential][default_azure_credential]. You can also create a client using a connection string. #### Using a service principal