github.com/argoproj/argo-events@v1.9.1/sensors/triggers/azure-service-bus/azure_service_bus.go (about)

     1  /*
     2  Copyright 2020 BlackRock, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  package azureservicebus
    17  
    18  import (
    19  	"context"
    20  	"encoding/json"
    21  	"fmt"
    22  
    23  	servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
    24  	"go.uber.org/zap"
    25  
    26  	"github.com/argoproj/argo-events/common"
    27  	"github.com/argoproj/argo-events/common/logging"
    28  	apicommon "github.com/argoproj/argo-events/pkg/apis/common"
    29  	"github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1"
    30  	"github.com/argoproj/argo-events/sensors/triggers"
    31  )
    32  
    33  // AzureServiceBusTrigger describes the trigger to send messages to a Service Bus
    34  type AzureServiceBusTrigger struct {
    35  	// Sensor object
    36  	Sensor *v1alpha1.Sensor
    37  	// Trigger reference
    38  	Trigger *v1alpha1.Trigger
    39  	// Sender refers to Azure Service Bus Sender struct
    40  	Sender *servicebus.Sender
    41  	// Logger to log stuff
    42  	Logger *zap.SugaredLogger
    43  }
    44  
    45  func NewAzureServiceBusTrigger(sensor *v1alpha1.Sensor, trigger *v1alpha1.Trigger, azureServiceBusClients common.StringKeyedMap[*servicebus.Sender], logger *zap.SugaredLogger) (*AzureServiceBusTrigger, error) {
    46  	triggerLogger := logger.With(logging.LabelTriggerType, apicommon.AzureServiceBusTrigger)
    47  	azureServiceBusTrigger := trigger.Template.AzureServiceBus
    48  
    49  	sender, ok := azureServiceBusClients.Load(trigger.Template.Name)
    50  
    51  	if !ok {
    52  		connStr, err := common.GetSecretFromVolume(azureServiceBusTrigger.ConnectionString)
    53  		if err != nil {
    54  			triggerLogger.With("connection-string", azureServiceBusTrigger.ConnectionString.Name).Errorw("failed to retrieve connection string from secret", zap.Error(err))
    55  			return nil, err
    56  		}
    57  
    58  		triggerLogger.Info("connecting to the service bus...")
    59  		clientOptions := servicebus.ClientOptions{}
    60  		if azureServiceBusTrigger.TLS != nil {
    61  			tlsConfig, err := common.GetTLSConfig(azureServiceBusTrigger.TLS)
    62  			if err != nil {
    63  				triggerLogger.Errorw("failed to get the tls configuration", zap.Error(err))
    64  				return nil, err
    65  			}
    66  			clientOptions.TLSConfig = tlsConfig
    67  		}
    68  
    69  		client, err := servicebus.NewClientFromConnectionString(connStr, &clientOptions)
    70  		if err != nil {
    71  			triggerLogger.Errorw("failed to create a service bus client", zap.Error(err))
    72  			return nil, err
    73  		}
    74  
    75  		// Set queueOrTopicName to be azureServiceBusTrigger.QueueName or azureServiceBusTrigger.TopicName
    76  		var queueOrTopicName string
    77  		switch {
    78  		case azureServiceBusTrigger.QueueName != "":
    79  			queueOrTopicName = azureServiceBusTrigger.QueueName
    80  		case azureServiceBusTrigger.TopicName != "":
    81  			queueOrTopicName = azureServiceBusTrigger.TopicName
    82  		default:
    83  			return nil, fmt.Errorf("neither queue name nor topic name is specified")
    84  		}
    85  
    86  		logger.With("queueOrTopicName", queueOrTopicName).Info("creating a new sender...")
    87  
    88  		sender, err = client.NewSender(queueOrTopicName, &servicebus.NewSenderOptions{})
    89  		if err != nil {
    90  			triggerLogger.Errorw("failed to create a service bus sender", zap.Error(err))
    91  			return nil, err
    92  		}
    93  
    94  		azureServiceBusClients.Store(trigger.Template.Name, sender)
    95  	}
    96  
    97  	return &AzureServiceBusTrigger{
    98  		Sensor:  sensor,
    99  		Trigger: trigger,
   100  		Sender:  sender,
   101  		Logger:  triggerLogger,
   102  	}, nil
   103  }
   104  
   105  // GetTriggerType returns the type of the trigger
   106  func (t *AzureServiceBusTrigger) GetTriggerType() apicommon.TriggerType {
   107  	return apicommon.AzureServiceBusTrigger
   108  }
   109  
   110  // FetchResource fetches the trigger resource
   111  func (t *AzureServiceBusTrigger) FetchResource(ctx context.Context) (interface{}, error) {
   112  	return t.Trigger.Template.AzureServiceBus, nil
   113  }
   114  
   115  // ApplyResourceParameters applies parameters to the trigger resource
   116  func (t *AzureServiceBusTrigger) ApplyResourceParameters(events map[string]*v1alpha1.Event, resource interface{}) (interface{}, error) {
   117  	fetchedResource, ok := resource.(*v1alpha1.AzureServiceBusTrigger)
   118  	if !ok {
   119  		return nil, fmt.Errorf("failed to interpret the fetched trigger resource")
   120  	}
   121  
   122  	resourceBytes, err := json.Marshal(fetchedResource)
   123  	if err != nil {
   124  		return nil, fmt.Errorf("failed to marshal the azure service bus trigger resource, %w", err)
   125  	}
   126  
   127  	parameters := fetchedResource.Parameters
   128  	if parameters != nil {
   129  		updatedResourceBytes, err := triggers.ApplyParams(resourceBytes, parameters, events)
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  		var sbTrigger *v1alpha1.AzureServiceBusTrigger
   134  		if err := json.Unmarshal(updatedResourceBytes, &sbTrigger); err != nil {
   135  			return nil, fmt.Errorf("failed to unmarshal the updated azure service bus trigger resource after applying resource parameters, %w", err)
   136  		}
   137  		return sbTrigger, nil
   138  	}
   139  
   140  	return resource, nil
   141  }
   142  
   143  // Execute executes the trigger
   144  func (t *AzureServiceBusTrigger) Execute(ctx context.Context, events map[string]*v1alpha1.Event, resource interface{}) (interface{}, error) {
   145  	trigger, ok := resource.(*v1alpha1.AzureServiceBusTrigger)
   146  	if !ok {
   147  		return nil, fmt.Errorf("failed to interpret the trigger resource")
   148  	}
   149  
   150  	if trigger.Payload == nil {
   151  		return nil, fmt.Errorf("payload parameters are not specified")
   152  	}
   153  
   154  	payload, err := triggers.ConstructPayload(events, trigger.Payload)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  
   159  	message := &servicebus.Message{
   160  		Body: payload,
   161  	}
   162  
   163  	err = t.Sender.SendMessage(ctx, message, &servicebus.SendMessageOptions{})
   164  	if err != nil {
   165  		return nil, fmt.Errorf("failed to send a message to the service bus, %w", err)
   166  	}
   167  	t.Logger.Info("successfully sent message to the service bus")
   168  
   169  	return nil, nil
   170  }
   171  
   172  // ApplyPolicy applies the trigger policy
   173  func (t *AzureServiceBusTrigger) ApplyPolicy(ctx context.Context, resource interface{}) error {
   174  	return nil
   175  }