Repository: kedacore/keda

Issue:
Temporal Scaler does not work properly with API Key authentication against Temporal Cloud as TLS is not enabled on the client: read: connection reset by peer
### Report

I have a Temporal Cloud namespace using api_key authentication:
```
tcld n am get -n my-ns.snip
api_key
```

I tried to use the Temporal scaler and specified the apiKey using the TriggerAuthentication:
```yaml
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: temporal-autoscaler-auth
  namespace: default
spec:
  secretTargetRef:
    - parameter: apiKey
      name: temporal-autoscaler-auth
      key: apiKey
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: temporal-worker
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: temporal-worker
  pollingInterval: 5
  cooldownPeriod: 300
  minReplicaCount: 5
  maxReplicaCount: 15
  advanced:
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 15
  triggers:
    - type: cpu
      metricType: Utilization
      metadata:
        value: "80"
    - type: temporal
      metadata:
        namespace: my-ns.snip
        taskQueue: main
        targetQueueSize: 30
        activationTargetValue: 1
        activationTargetQueueSize: "0"
        endpoint: "us-west1.gcp.api.temporal.io:7233"
        maxConnectTimeout: "30"
      authenticationRef:
        name: temporal-autoscaler-auth
```

When applying this, the keda operator throws the error shown in the logs below ("read: connection reset by peer").

I believe this happens because the scaler does not set the TLS option when using just apiKey:
https://github.com/kedacore/keda/blob/720ae0e98f7bc8e51316383bd15dea4ae187cff0/pkg/scalers/temporal.go#L211-L238


According to the docs, enabling TLS is required when using API Key: https://docs.temporal.io/cloud/api-keys#sdk

### Expected Behavior

The Temporal scaler would work properly when connecting to Temporal Cloud with just an API Key provided

### Actual Behavior

It gets a `read: connection reset by peer` network error.

### Steps to Reproduce the Problem

1. Create a Temporal Cloud namespace
2. Configure an API key on it
3. Try to use the Temporal trigger


### Logs from KEDA operator

```
2025-04-09T14:37:30Z    ERROR   Error getting scalers   {"controller": "scaledobject", "controllerGroup": "keda.sh", "controllerKind": "ScaledObject", "ScaledObject": {"name":"my-temporal-worker","namespace":"default"}, "namespace": "default", "name": "my-temporal-worker", "reconcileID": "94aeb370-a3fb-4979-8f4b-45c747166905", "error": "failed to create Temporal client connection: failed reaching server: connection error: desc = \"error reading server preface: read tcp 10.32.2.243:34834->34.82.7.179:7233: read: connection reset by peer\""}
github.com/kedacore/keda/v2/controllers/keda.(*ScaledObjectReconciler).getScaledObjectMetricSpecs
        /workspace/controllers/keda/hpa.go:219
github.com/kedacore/keda/v2/controllers/keda.(*ScaledObjectReconciler).newHPAForScaledObject
        /workspace/controllers/keda/hpa.go:72
github.com/kedacore/keda/v2/controllers/keda.(*ScaledObjectReconciler).createAndDeployNewHPA
        /workspace/controllers/keda/hpa.go:45
github.com/kedacore/keda/v2/controllers/keda.(*ScaledObjectReconciler).ensureHPAForScaledObjectExists
        /workspace/controllers/keda/scaledobject_controller.go:452
github.com/kedacore/keda/v2/controllers/keda.(*ScaledObjectReconciler).reconcileScaledObject
        /workspace/controllers/keda/scaledobject_controller.go:291
github.com/kedacore/keda/v2/controllers/keda.(*ScaledObjectReconciler).Reconcile
        /workspace/controllers/keda/scaledobject_controller.go:193
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile
        /workspace/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:116
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).reconcileHandler
        /workspace/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:303
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).processNextWorkItem
        /workspace/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:263
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func2.2
        /workspace/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:224

```


### KEDA Version

2.17.0

### Kubernetes Version

Other

### Platform

Google Cloud

### Scaler Details

Temporal

### Anything else?

Workaround:

Create a certificate and use it along side the API key, while mTLS is not enabled, this has the side-effect of enabling TLS, which will allow the Api Key authentication to work:


```
tcld gen ca --org my-org -d 1y --ca-cert ca.pem --ca-key ca.key
tcld gen leaf --org my-org -d 364d --ca-cert ca.pem --ca-key ca.key --cert client.pem --key client.key
base64 -w 0 client.pem
base64 -w 0 client.key 
```

Then add these to the secret being used by the TriggerAuthentication and configure the TriggerAuthentication to also provide `cert` and `key` (while still providing the `apiKey`).

After this it works:
```sh
 kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/default/s1-temporal-my-ns-snip-main?labelSelector=scaledobject.keda.sh%2Fname%3Dtemporal-worker" -n keda
```

```
{"kind":"ExternalMetricValueList","apiVersion":"external.metrics.k8s.io/v1beta1","metadata":{},"items":[{"metricName":"s1-temporal-my-ns-snip-main","metricLabels":null,"timestamp":"2025-04-09T15:04:33Z","value":"0"}]}
```

Discussion:

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f79ae447..7eaab334c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,7 +16,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio
 ## History
 
 - [Unreleased](#unreleased)
-- [v2.17.0](#v2161)
+- [v2.17.0](#v2170)
 - [v2.16.1](#v2161)
 - [v2.16.0](#v2160)
 - [v2.15.1](#v2151)
@@ -74,6 +74,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio
 
 - **General**: Admission Webhook blocks ScaledObject without metricType with fallback ([#6696](https://github.com/kedacore/keda/issues/6696))
 - **AWS SQS Queue Scaler**: Fix AWS SQS Queue queueURLFromEnv not working ([#6712](https://github.com/kedacore/keda/issues/6712))
+- **Temporal Scaler**: Fix Temporal Scaler does not work properly with API Key authentication against Temporal Cloud as TLS is not enabled on the client ([#6703](https://github.com/kedacore/keda/issues/6703))
 
 ### Deprecations
 
diff --git a/pkg/scalers/datadog_scaler.go b/pkg/scalers/datadog_scaler.go
index 1c2df9270..84e6f9eb9 100644
--- a/pkg/scalers/datadog_scaler.go
+++ b/pkg/scalers/datadog_scaler.go
@@ -2,7 +2,6 @@ package scalers
 
 import (
 	"context"
-	"errors"
 	"fmt"
 	"io"
 	"net/http"
@@ -30,48 +29,49 @@ type datadogScaler struct {
 	httpClient           *http.Client
 	logger               logr.Logger
 	useClusterAgentProxy bool
+	metricType           v2.MetricTargetType
 }
 
+// TODO: Need to check whether we can deprecate vType and how should we proceed with it
 type datadogMetadata struct {
-
 	// AuthParams Cluster Agent Proxy
-	datadogNamespace          string
-	datadogMetricsService     string
-	datadogMetricsServicePort int
-	unsafeSsl                 bool
+	DatadogNamespace          string `keda:"name=datadogNamespace,          order=authParams, optional"`
+	DatadogMetricsService     string `keda:"name=datadogMetricsService,     order=authParams, optional"`
+	DatadogMetricsServicePort int    `keda:"name=datadogMetricsServicePort, order=authParams, default=8443"`
+	UnsafeSsl                 bool   `keda:"name=unsafeSsl,                 order=authParams, default=false"`
 
 	// bearer auth Cluster Agent Proxy
-	enableBearerAuth bool
-	bearerToken      string
+	AuthMode         string `keda:"name=authMode,  order=authParams, optional"`
+	EnableBearerAuth bool
+	BearerToken      string `keda:"name=token,     order=authParams,      optional"`
 
 	// TriggerMetadata Cluster Agent Proxy
-	datadogMetricServiceURL string
-	datadogMetricName       string
-	datadogMetricNamespace  string
-	activationTargetValue   float64
+	DatadogMetricServiceURL string
+	DatadogMetricName       string  `keda:"name=datadogMetricName,       order=triggerMetadata, optional"`
+	DatadogMetricNamespace  string  `keda:"name=datadogMetricNamespace,  order=triggerMetadata, optional"`
+	ActivationTargetValue   float64 `keda:"name=activationTargetValue,   order=triggerMetadata, default=0"`
 
 	// AuthParams Datadog API
-	apiKey      string
-	appKey      string
-	datadogSite string
+	APIKey      string `keda:"name=apiKey,      order=authParams, optional"`
+	AppKey      string `keda:"name=appKey,      order=authParams, optional"`
+	DatadogSite string `keda:"name=datadogSite, order=authParams, default=datadoghq.com"`
 
 	// TriggerMetadata Datadog API
-	query                    string
-	queryAggegrator          string
-	activationQueryValue     float64
-	age                      int
-	timeWindowOffset         int
-	lastAvailablePointOffset int
+	Query                    string  `keda:"name=query,                   order=triggerMetadata, optional"`
+	QueryAggegrator          string  `keda:"name=queryAggregator,         order=triggerMetadata, optional, enum=average;max"`
+	ActivationQueryValue     float64 `keda:"name=activationQueryValue,    order=triggerMetadata, default=0"`
+	Age                      int     `keda:"name=age,                     order=triggerMetadata, default=90"`
+	TimeWindowOffset         int     `keda:"name=timeWindowOffset,        order=triggerMetadata, default=0"`
+	LastAvailablePointOffset int     `keda:"name=lastAvailablePointOffset,order=triggerMetadata, default=0"`
 
 	// TriggerMetadata Common
-	hpaMetricName string
-	fillValue     float64
-	targetValue   float64
-	useFiller     bool
+	HpaMetricName string  `keda:"name=hpaMetricName,          order=triggerMetadata, optional"`
+	FillValue     float64 `keda:"name=metricUnavailableValue, order=triggerMetadata, default=0"`
+	UseFiller     bool
+	TargetValue   float64 `keda:"name=targetValue;queryValue, order=triggerMetadata, default=-1"`
 	vType         v2.MetricTargetType
 }
 
-const maxString = "max"
 const avgString = "average"
 
 var filter *regexp.Regexp
@@ -82,11 +82,14 @@ func init() {
 
 // NewDatadogScaler creates a new Datadog scaler
 func NewDatadogScaler(ctx context.Context, config *scalersconfig.ScalerConfig) (Scaler, error) {
+	metricType, err := GetMetricTargetType(config)
+	if err != nil {
+		return nil, fmt.Errorf("error getting scaler metric type: %w", err)
+	}
 	logger := InitializeLogger(config, "datadog_scaler")
 
 	var useClusterAgentProxy bool
 	var meta *datadogMetadata
-	var err error
 	var apiClient *datadog.APIClient
 	var httpClient *http.Client
 
@@ -102,7 +105,7 @@ func NewDatadogScaler(ctx context.Context, config *scalersconfig.ScalerConfig) (
 		if err != nil {
 			return nil, fmt.Errorf("error parsing Datadog metadata: %w", err)
 		}
-		httpClient = kedautil.CreateHTTPClient(config.GlobalHTTPTimeout, meta.unsafeSsl)
+		httpClient = kedautil.CreateHTTPClient(config.GlobalHTTPTimeout, meta.UnsafeSsl)
 	} else {
 		meta, err = parseDatadogAPIMetadata(config, logger)
 		if err != nil {
@@ -115,6 +118,7 @@ func NewDatadogScaler(ctx context.Context, config *scalersconfig.ScalerConfig) (
 	}
 
 	return &datadogScaler{
+		metricType:           metricType,
 		metadata:             meta,
 		apiClient:            apiClient,
 		httpClient:           httpClient,
@@ -144,113 +148,27 @@ func buildMetricURL(datadogClusterAgentURL, datadogMetricNamespace, datadogMetri
 }
 
 func parseDatadogAPIMetadata(config *scalersconfig.ScalerConfig, logger logr.Logger) (*datadogMetadata, error) {
-	meta := datadogMetadata{}
-
-	if val, ok := config.TriggerMetadata["age"]; ok {
-		age, err := strconv.Atoi(val)
-		if err != nil {
-			return nil, fmt.Errorf("age parsing error %w", err)
-		}
-		meta.age = age
-
-		if age < 0 {
-			return nil, fmt.Errorf("age should not be smaller than 0 seconds")
-		}
-		if age < 60 {
-			logger.Info("selecting a window smaller than 60 seconds can cause Datadog not finding a metric value for the query")
-		}
-	} else {
-		meta.age = 90 // Default window 90 seconds
+	meta := &datadogMetadata{}
+	if err := config.TypedConfig(meta); err != nil {
+		return nil, fmt.Errorf("error parsing Datadog metadata: %w", err)
 	}
 
-	if val, ok := config.TriggerMetadata["timeWindowOffset"]; ok {
-		timeWindowOffset, err := strconv.Atoi(val)
-		if err != nil {
-			return nil, fmt.Errorf("timeWindowOffset parsing error %w", err)
-		}
-		if timeWindowOffset < 0 {
-			return nil, fmt.Errorf("timeWindowOffset should not be smaller than 0 seconds")
-		}
-		meta.timeWindowOffset = timeWindowOffset
-	} else {
-		meta.timeWindowOffset = 0 // Default delay 0 seconds
+	if meta.Age < 60 {
+		logger.Info("selecting a window smaller than 60 seconds can cause Datadog not finding a metric value for the query")
 	}
-
-	if val, ok := config.TriggerMetadata["lastAvailablePointOffset"]; ok {
-		lastAvailablePointOffset, err := strconv.Atoi(val)
-		if err != nil {
-			return nil, fmt.Errorf("lastAvailablePointOffset parsing error %w", err)
-		}
-
-		if lastAvailablePointOffset < 0 {
-			return nil, fmt.Errorf("lastAvailablePointOffset should not be smaller than 0")
-		}
-		meta.lastAvailablePointOffset = lastAvailablePointOffset
-	} else {
-		meta.lastAvailablePointOffset = 0 // Default use the last point
+	if meta.AppKey == "" {
+		return nil, fmt.Errorf("error parsing Datadog metadata: missing AppKey")
 	}
-
-	if val, ok := config.TriggerMetadata["query"]; ok {
-		_, err := parseDatadogQuery(val)
-
-		if err != nil {
-			return nil, fmt.Errorf("error in query: %w", err)
-		}
-		meta.query = val
-	} else {
-		return nil, fmt.Errorf("no query given")
+	if meta.APIKey == "" {
+		return nil, fmt.Errorf("error parsing Datadog metadata: missing APIKey")
 	}
-
-	if val, ok := config.TriggerMetadata["targetValue"]; ok {
-		targetValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("targetValue parsing error %w", err)
-		}
-		meta.targetValue = targetValue
-	} else if val, ok := config.TriggerMetadata["queryValue"]; ok {
-		targetValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("queryValue parsing error %w", err)
-		}
-		meta.targetValue = targetValue
-	} else {
+	if meta.TargetValue == -1 {
 		if config.AsMetricSource {
-			meta.targetValue = 0
+			meta.TargetValue = 0
 		} else {
 			return nil, fmt.Errorf("no targetValue or queryValue given")
 		}
 	}
-
-	if val, ok := config.TriggerMetadata["queryAggregator"]; ok && val != "" {
-		queryAggregator := strings.ToLower(val)
-		switch queryAggregator {
-		case avgString, maxString:
-			meta.queryAggegrator = queryAggregator
-		default:
-			return nil, fmt.Errorf("queryAggregator value %s has to be one of '%s, %s'", queryAggregator, avgString, maxString)
-		}
-	} else {
-		meta.queryAggegrator = ""
-	}
-
-	meta.activationQueryValue = 0
-	if val, ok := config.TriggerMetadata["activationQueryValue"]; ok {
-		activationQueryValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("queryValue parsing error %w", err)
-		}
-		meta.activationQueryValue = activationQueryValue
-	}
-
-	if val, ok := config.TriggerMetadata["metricUnavailableValue"]; ok {
-		fillValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("metricUnavailableValue parsing error %w", err)
-		}
-		meta.fillValue = fillValue
-		meta.useFiller = true
-	}
-
 	if val, ok := config.TriggerMetadata["type"]; ok {
 		logger.V(0).Info("trigger.metadata.type is deprecated in favor of trigger.metricType")
 		if config.MetricType != "" {
@@ -272,115 +190,45 @@ func parseDatadogAPIMetadata(config *scalersconfig.ScalerConfig, logger logr.Log
 		}
 		meta.vType = metricType
 	}
-
-	if val, ok := config.AuthParams["apiKey"]; ok {
-		meta.apiKey = val
-	} else {
-		return nil, fmt.Errorf("no api key given")
+	if meta.Query == "" {
+		return nil, fmt.Errorf("error parsing Datadog metadata: missing Query")
 	}
 
-	if val, ok := config.AuthParams["appKey"]; ok {
-		meta.appKey = val
+	if meta.Query != "" {
+		meta.HpaMetricName = meta.Query[0:strings.Index(meta.Query, "{")]
+		meta.HpaMetricName = GenerateMetricNameWithIndex(config.TriggerIndex, kedautil.NormalizeString(fmt.Sprintf("datadog-%s", meta.HpaMetricName)))
 	} else {
-		return nil, fmt.Errorf("no app key given")
-	}
-
-	siteVal := "datadoghq.com"
-
-	if val, ok := config.AuthParams["datadogSite"]; ok && val != "" {
-		siteVal = val
+		meta.HpaMetricName = "datadogmetric@" + meta.DatadogMetricNamespace + ":" + meta.DatadogMetricName
 	}
 
-	meta.datadogSite = siteVal
-
-	hpaMetricName := meta.query[0:strings.Index(meta.query, "{")]
-	meta.hpaMetricName = GenerateMetricNameWithIndex(config.TriggerIndex, kedautil.NormalizeString(fmt.Sprintf("datadog-%s", hpaMetricName)))
-
-	return &meta, nil
+	return meta, nil
 }
 
 func parseDatadogClusterAgentMetadata(config *scalersconfig.ScalerConfig, logger logr.Logger) (*datadogMetadata, error) {
-	meta := datadogMetadata{}
-
-	if val, ok := config.AuthParams["datadogNamespace"]; ok {
-		meta.datadogNamespace = val
-	} else {
-		return nil, fmt.Errorf("no datadogNamespace key given")
+	meta := &datadogMetadata{}
+	if err := config.TypedConfig(meta); err != nil {
+		return nil, fmt.Errorf("error parsing Datadog metadata: %w", err)
 	}
-
-	if val, ok := config.AuthParams["datadogMetricsService"]; ok {
-		meta.datadogMetricsService = val
-	} else {
-		return nil, fmt.Errorf("no datadogMetricsService key given")
+	if meta.DatadogMetricsService == "" {
+		return nil, fmt.Errorf("datadog metrics service is required")
 	}
 
-	if val, ok := config.AuthParams["datadogMetricsServicePort"]; ok {
-		port, err := strconv.Atoi(val)
-		if err != nil {
-			return nil, fmt.Errorf("datadogMetricServicePort parsing error %w", err)
-		}
-		meta.datadogMetricsServicePort = port
-	} else {
-		meta.datadogMetricsServicePort = 8443
-	}
-
-	meta.datadogMetricServiceURL = buildClusterAgentURL(meta.datadogMetricsService, meta.datadogNamespace, meta.datadogMetricsServicePort)
-
-	meta.unsafeSsl = false
-	if val, ok := config.AuthParams["unsafeSsl"]; ok {
-		unsafeSsl, err := strconv.ParseBool(val)
-		if err != nil {
-			return nil, fmt.Errorf("error parsing unsafeSsl: %w", err)
-		}
-		meta.unsafeSsl = unsafeSsl
+	if meta.DatadogMetricName == "" {
+		return nil, fmt.Errorf("datadog metric name is required")
 	}
-
-	if val, ok := config.TriggerMetadata["datadogMetricName"]; ok {
-		meta.datadogMetricName = val
-	} else {
-		return nil, fmt.Errorf("no datadogMetricName key given")
+	if meta.DatadogNamespace == "" {
+		return nil, fmt.Errorf("datadog namespace is required")
 	}
-
-	if val, ok := config.TriggerMetadata["datadogMetricNamespace"]; ok {
-		meta.datadogMetricNamespace = val
-	} else {
-		return nil, fmt.Errorf("no datadogMetricNamespace key given")
+	if meta.DatadogMetricNamespace == "" {
+		return nil, fmt.Errorf("datadog metric namespace is required")
 	}
-
-	meta.hpaMetricName = "datadogmetric@" + meta.datadogMetricNamespace + ":" + meta.datadogMetricName
-
-	if val, ok := config.TriggerMetadata["targetValue"]; ok {
-		targetValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("targetValue parsing error %w", err)
-		}
-		meta.targetValue = targetValue
-	} else {
+	if meta.TargetValue == -1 {
 		if config.AsMetricSource {
-			meta.targetValue = 0
+			meta.TargetValue = 0
 		} else {
-			return nil, fmt.Errorf("no targetValue given")
-		}
-	}
-
-	meta.activationTargetValue = 0
-	if val, ok := config.TriggerMetadata["activationTargetValue"]; ok {
-		activationTargetValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("activationTargetValue parsing error %w", err)
-		}
-		meta.activationTargetValue = activationTargetValue
-	}
-
-	if val, ok := config.TriggerMetadata["metricUnavailableValue"]; ok {
-		fillValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("metricUnavailableValue parsing error %w", err)
+			return nil, fmt.Errorf("no targetValue or queryValue given")
 		}
-		meta.fillValue = fillValue
-		meta.useFiller = true
 	}
-
 	if val, ok := config.TriggerMetadata["type"]; ok {
 		logger.V(0).Info("trigger.metadata.type is deprecated in favor of trigger.metricType")
 		if config.MetricType != "" {
@@ -402,27 +250,11 @@ func parseDatadogClusterAgentMetadata(config *scalersconfig.ScalerConfig, logger
 		}
 		meta.vType = metricType
 	}
+	meta.HpaMetricName = "datadogmetric@" + meta.DatadogMetricNamespace + ":" + meta.DatadogMetricName
 
-	authMode, ok := config.AuthParams["authMode"]
-	// no authMode specified
-	if !ok {
-		return &meta, nil
-	}
+	meta.DatadogMetricServiceURL = buildClusterAgentURL(meta.DatadogMetricsService, meta.DatadogMetricNamespace, meta.DatadogMetricsServicePort)
 
-	authType := authentication.Type(strings.TrimSpace(authMode))
-	switch authType {
-	case authentication.BearerAuthType:
-		if len(config.AuthParams["token"]) == 0 {
-			return nil, errors.New("no token provided")
-		}
-
-		meta.bearerToken = config.AuthParams["token"]
-		meta.enableBearerAuth = true
-	default:
-		return nil, fmt.Errorf("err incorrect value for authMode is given: %s", authMode)
-	}
-
-	return &meta, nil
+	return meta, nil
 }
 
 // newDatadogAPIConnection tests a connection to the Datadog API
@@ -432,10 +264,10 @@ func newDatadogAPIConnection(ctx context.Context, meta *datadogMetadata, config
 		datadog.ContextAPIKeys,
 		map[string]datadog.APIKey{
 			"apiKeyAuth": {
-				Key: meta.apiKey,
+				Key: meta.APIKey,
 			},
 			"appKeyAuth": {
-				Key: meta.appKey,
+				Key: meta.AppKey,
 			},
 		},
 	)
@@ -443,7 +275,7 @@ func newDatadogAPIConnection(ctx context.Context, meta *datadogMetadata, config
 	ctx = context.WithValue(ctx,
 		datadog.ContextServerVariables,
 		map[string]string{
-			"site": meta.datadogSite,
+			"site": meta.DatadogSite,
 		})
 
 	configuration := datadog.NewConfiguration()
@@ -473,10 +305,10 @@ func (s *datadogScaler) getQueryResult(ctx context.Context) (float64, error) {
 		datadog.ContextAPIKeys,
 		map[string]datadog.APIKey{
 			"apiKeyAuth": {
-				Key: s.metadata.apiKey,
+				Key: s.metadata.APIKey,
 			},
 			"appKeyAuth": {
-				Key: s.metadata.appKey,
+				Key: s.metadata.AppKey,
 			},
 		},
 	)
@@ -484,12 +316,12 @@ func (s *datadogScaler) getQueryResult(ctx context.Context) (float64, error) {
 	ctx = context.WithValue(ctx,
 		datadog.ContextServerVariables,
 		map[string]string{
-			"site": s.metadata.datadogSite,
+			"site": s.metadata.DatadogSite,
 		})
 
-	timeWindowTo := time.Now().Unix() - int64(s.metadata.timeWindowOffset)
-	timeWindowFrom := timeWindowTo - int64(s.metadata.age)
-	resp, r, err := s.apiClient.MetricsApi.QueryMetrics(ctx, timeWindowFrom, timeWindowTo, s.metadata.query) //nolint:bodyclose
+	timeWindowTo := time.Now().Unix() - int64(s.metadata.TimeWindowOffset)
+	timeWindowFrom := timeWindowTo - int64(s.metadata.Age)
+	resp, r, err := s.apiClient.MetricsApi.QueryMetrics(ctx, timeWindowFrom, timeWindowTo, s.metadata.Query) //nolint:bodyclose
 
 	if r != nil {
 		if r.StatusCode == 429 {
@@ -522,14 +354,14 @@ func (s *datadogScaler) getQueryResult(ctx context.Context) (float64, error) {
 	series := resp.GetSeries()
 
 	if len(series) == 0 {
-		if !s.metadata.useFiller {
+		if !s.metadata.UseFiller {
 			return 0, fmt.Errorf("no Datadog metrics returned for the given time window")
 		}
-		return s.metadata.fillValue, nil
+		return s.metadata.FillValue, nil
 	}
 
 	// Require queryAggregator be set explicitly for multi-query
-	if len(series) > 1 && s.metadata.queryAggegrator == "" {
+	if len(series) > 1 && s.metadata.QueryAggegrator == "" {
 		return 0, fmt.Errorf("query returned more than 1 series; modify the query to return only 1 series or add a queryAggregator")
 	}
 
@@ -545,22 +377,22 @@ func (s *datadogScaler) getQueryResult(ctx context.Context) (float64, error) {
 				break
 			}
 		}
-		if index < s.metadata.lastAvailablePointOffset {
+		if index < s.metadata.LastAvailablePointOffset {
 			return 0, fmt.Errorf("index is smaller than the lastAvailablePointOffset")
 		}
-		index -= s.metadata.lastAvailablePointOffset
+		index -= s.metadata.LastAvailablePointOffset
 
 		if len(points) == 0 || len(points[index]) < 2 || points[index][1] == nil {
-			if !s.metadata.useFiller {
+			if !s.metadata.UseFiller {
 				return 0, fmt.Errorf("no Datadog metrics returned for the given time window")
 			}
-			return s.metadata.fillValue, nil
+			return s.metadata.FillValue, nil
 		}
 		// Return the last point from the series
 		results[i] = *points[index][1]
 	}
 
-	switch s.metadata.queryAggegrator {
+	switch s.metadata.QueryAggegrator {
 	case avgString:
 		return AvgFloatFromSlice(results), nil
 	default:
@@ -608,12 +440,12 @@ func (s *datadogScaler) getDatadogClusterAgentHTTPRequest(ctx context.Context, u
 	var err error
 
 	switch {
-	case s.metadata.enableBearerAuth:
+	case s.metadata.EnableBearerAuth:
 		req, err = http.NewRequestWithContext(ctx, "GET", url, nil)
 		if err != nil {
 			return nil, err
 		}
-		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", s.metadata.bearerToken))
+		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", s.metadata.BearerToken))
 		if err != nil {
 			return nil, err
 		}
@@ -633,9 +465,9 @@ func (s *datadogScaler) getDatadogClusterAgentHTTPRequest(ctx context.Context, u
 func (s *datadogScaler) GetMetricSpecForScaling(context.Context) []v2.MetricSpec {
 	externalMetric := &v2.ExternalMetricSource{
 		Metric: v2.MetricIdentifier{
-			Name: s.metadata.hpaMetricName,
+			Name: s.metadata.HpaMetricName,
 		},
-		Target: GetMetricTargetMili(s.metadata.vType, s.metadata.targetValue),
+		Target: GetMetricTargetMili(s.metricType, s.metadata.TargetValue),
 	}
 	metricSpec := v2.MetricSpec{
 		External: externalMetric, Type: externalMetricType,
@@ -650,7 +482,7 @@ func (s *datadogScaler) GetMetricsAndActivity(ctx context.Context, metricName st
 	var err error
 
 	if s.useClusterAgentProxy {
-		url := buildMetricURL(s.metadata.datadogMetricServiceURL, s.metadata.datadogMetricNamespace, s.metadata.hpaMetricName)
+		url := buildMetricURL(s.metadata.DatadogMetricServiceURL, s.metadata.DatadogMetricNamespace, s.metadata.HpaMetricName)
 
 		req, err := s.getDatadogClusterAgentHTTPRequest(ctx, url)
 		if (err != nil) || (req == nil) {
@@ -663,7 +495,7 @@ func (s *datadogScaler) GetMetricsAndActivity(ctx context.Context, metricName st
 		}
 
 		metric = GenerateMetricInMili(metricName, num)
-		return []external_metrics.ExternalMetricValue{metric}, num > s.metadata.activationTargetValue, nil
+		return []external_metrics.ExternalMetricValue{metric}, num > s.metadata.ActivationTargetValue, nil
 	}
 	num, err = s.getQueryResult(ctx)
 	if err != nil {
@@ -672,7 +504,7 @@ func (s *datadogScaler) GetMetricsAndActivity(ctx context.Context, metricName st
 	}
 
 	metric = GenerateMetricInMili(metricName, num)
-	return []external_metrics.ExternalMetricValue{metric}, num > s.metadata.activationQueryValue, nil
+	return []external_metrics.ExternalMetricValue{metric}, num > s.metadata.ActivationQueryValue, nil
 }
 
 // AvgFloatFromSlice finds the average value in a slice of floats
@@ -683,3 +515,37 @@ func AvgFloatFromSlice(results []float64) float64 {
 	}
 	return total / float64(len(results))
 }
+
+func (s *datadogMetadata) Validate() error {
+	if s.Age < 0 {
+		return fmt.Errorf("age should not be smaller than 0 seconds")
+	}
+
+	if s.TimeWindowOffset < 0 {
+		return fmt.Errorf("timeWindowOffset should not be smaller than 0 seconds")
+	}
+	if s.LastAvailablePointOffset < 0 {
+		return fmt.Errorf("lastAvailablePointOffset should not be smaller than 0")
+	}
+	if s.Query != "" {
+		if _, err := parseDatadogQuery(s.Query); err != nil {
+			return fmt.Errorf("error in query: %w", err)
+		}
+	}
+	if s.FillValue == 0 {
+		s.UseFiller = false
+	}
+	if s.AuthMode != "" {
+		authType := authentication.Type(strings.TrimSpace(s.AuthMode))
+		switch authType {
+		case authentication.BearerAuthType:
+			if s.BearerToken == "" {
+				return fmt.Errorf("BearerToken is required")
+			}
+			s.EnableBearerAuth = true
+		default:
+			return fmt.Errorf("err incorrect value for authMode is given: %s", s.AuthMode)
+		}
+	}
+	return nil
+}
diff --git a/pkg/scalers/gcp_stackdriver_scaler.go b/pkg/scalers/gcp_stackdriver_scaler.go
index 7fee64ffa..9d4653f1b 100644
--- a/pkg/scalers/gcp_stackdriver_scaler.go
+++ b/pkg/scalers/gcp_stackdriver_scaler.go
@@ -15,10 +15,6 @@ import (
 	kedautil "github.com/kedacore/keda/v2/pkg/util"
 )
 
-const (
-	defaultStackdriverTargetValue = 5
-)
-
 type stackdriverScaler struct {
 	client     *gcp.StackDriverClient
 	metricType v2.MetricTargetType
@@ -27,13 +23,13 @@ type stackdriverScaler struct {
 }
 
 type stackdriverMetadata struct {
-	projectID             string
-	filter                string
-	targetValue           float64
-	activationTargetValue float64
+	ProjectID             string  `keda:"name=projectId, order=triggerMetadata"`
+	Filter                string  `keda:"name=filter, order=triggerMetadata"`
+	TargetValue           float64 `keda:"name=targetValue, order=triggerMetadata, default=5"`
+	ActivationTargetValue float64 `keda:"name=activationTargetValue, order=triggerMetadata, default=0"`
 	metricName            string
-	valueIfNull           *float64
-	filterDuration        int64
+	ValueIfNull           *float64 `keda:"name=valueIfNull, order=triggerMetadata, optional"`
+	FilterDuration        int64    `keda:"name=filterDuration, order=triggerMetadata, optional"`
 
 	gcpAuthorization *gcp.AuthorizationMetadata
 	aggregation      *monitoringpb.Aggregation
@@ -68,67 +64,15 @@ func NewStackdriverScaler(ctx context.Context, config *scalersconfig.ScalerConfi
 }
 
 func parseStackdriverMetadata(config *scalersconfig.ScalerConfig, logger logr.Logger) (*stackdriverMetadata, error) {
-	meta := stackdriverMetadata{}
-	meta.targetValue = defaultStackdriverTargetValue
-
-	if val, ok := config.TriggerMetadata["projectId"]; ok {
-		if val == "" {
-			return nil, fmt.Errorf("no projectId name given")
-		}
-
-		meta.projectID = val
-	} else {
-		return nil, fmt.Errorf("no projectId name given")
-	}
+	meta := &stackdriverMetadata{}
 
-	if val, ok := config.TriggerMetadata["filter"]; ok {
-		if val == "" {
-			return nil, fmt.Errorf("no filter given")
-		}
-
-		meta.filter = val
-	} else {
-		return nil, fmt.Errorf("no filter given")
+	if err := config.TypedConfig(meta); err != nil {
+		return nil, fmt.Errorf("error parsing Stackdriver metadata: %w", err)
 	}
 
-	name := kedautil.NormalizeString(fmt.Sprintf("gcp-stackdriver-%s", meta.projectID))
+	name := kedautil.NormalizeString(fmt.Sprintf("gcp-stackdriver-%s", meta.ProjectID))
 	meta.metricName = GenerateMetricNameWithIndex(config.TriggerIndex, name)
 
-	if val, ok := config.TriggerMetadata["targetValue"]; ok {
-		targetValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			logger.Error(err, "Error parsing targetValue")
-			return nil, fmt.Errorf("error parsing targetValue: %w", err)
-		}
-
-		meta.targetValue = targetValue
-	}
-
-	meta.activationTargetValue = 0
-	if val, ok := config.TriggerMetadata["activationTargetValue"]; ok {
-		activationTargetValue, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("activationTargetValue parsing error %w", err)
-		}
-		meta.activationTargetValue = activationTargetValue
-	}
-
-	if val, ok := config.TriggerMetadata["valueIfNull"]; ok && val != "" {
-		valueIfNull, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			return nil, fmt.Errorf("valueIfNull parsing error %w", err)
-		}
-		meta.valueIfNull = &valueIfNull
-	}
-
-	if val, ok := config.TriggerMetadata["filterDuration"]; ok {
-		filterDuration, err := strconv.ParseInt(val, 10, 64)
-		if err != nil {
-			return nil, fmt.Errorf("filterDuration parsing error %w", err)
-		}
-		meta.filterDuration = filterDuration
-	}
-
 	auth, err := gcp.GetGCPAuthorization(config)
 	if err != nil {
 		return nil, err
@@ -141,7 +85,7 @@ func parseStackdriverMetadata(config *scalersconfig.ScalerConfig, logger logr.Lo
 	}
 	meta.aggregation = aggregation
 
-	return &meta, nil
+	return meta, nil
 }
 
 func parseAggregation(config *scalersconfig.ScalerConfig, logger logr.Logger) (*monitoringpb.Aggregation, error) {
@@ -199,7 +143,7 @@ func (s *stackdriverScaler) GetMetricSpecForScaling(context.Context) []v2.Metric
 		Metric: v2.MetricIdentifier{
 			Name: s.metadata.metricName,
 		},
-		Target: GetMetricTargetMili(s.metricType, s.metadata.targetValue),
+		Target: GetMetricTargetMili(s.metricType, s.metadata.TargetValue),
 	}
 
 	// Create the metric spec for the HPA
@@ -221,17 +165,17 @@ func (s *stackdriverScaler) GetMetricsAndActivity(ctx context.Context, metricNam
 
 	metric := GenerateMetricInMili(metricName, value)
 
-	return []external_metrics.ExternalMetricValue{metric}, value > s.metadata.activationTargetValue, nil
+	return []external_metrics.ExternalMetricValue{metric}, value > s.metadata.ActivationTargetValue, nil
 }
 
 // getMetrics gets metric type value from stackdriver api
 func (s *stackdriverScaler) getMetrics(ctx context.Context) (float64, error) {
-	val, err := s.client.GetMetrics(ctx, s.metadata.filter, s.metadata.projectID, s.metadata.aggregation, s.metadata.valueIfNull, s.metadata.filterDuration)
+	val, err := s.client.GetMetrics(ctx, s.metadata.Filter, s.metadata.ProjectID, s.metadata.aggregation, s.metadata.ValueIfNull, s.metadata.FilterDuration)
 	if err == nil {
 		s.logger.V(1).Info(
 			fmt.Sprintf("Getting metrics for project %s, filter %s and aggregation %v. Result: %f",
-				s.metadata.projectID,
-				s.metadata.filter,
+				s.metadata.ProjectID,
+				s.metadata.Filter,
 				s.metadata.aggregation,
 				val))
 	}
diff --git a/pkg/scalers/temporal.go b/pkg/scalers/temporal.go
index ce7a56b86..b55401920 100644
--- a/pkg/scalers/temporal.go
+++ b/pkg/scalers/temporal.go
@@ -2,6 +2,7 @@ package scalers
 
 import (
 	"context"
+	"crypto/tls"
 	"fmt"
 	"log/slog"
 	"time"
@@ -223,6 +224,9 @@ func getTemporalClient(ctx context.Context, meta *temporalMetadata, log logr.Log
 			},
 		))
 		options.Credentials = sdk.NewAPIKeyStaticCredentials(meta.APIKey)
+		options.ConnectionOptions.TLS = &tls.Config{
+			MinVersion: tls.VersionTLS13,
+		}
 	}
 
 	options.ConnectionOptions = sdk.ConnectionOptions{



Test patch:
diff --git a/pkg/scalers/datadog_scaler_test.go b/pkg/scalers/datadog_scaler_test.go
index e2de79235..52421d8f1 100644
--- a/pkg/scalers/datadog_scaler_test.go
+++ b/pkg/scalers/datadog_scaler_test.go
@@ -107,6 +107,7 @@ var testDatadogClusterAgentMetadata = []datadogAuthMetadataTestData{
 	// Default Datadog service name and port
 	{"", map[string]string{"useClusterAgentProxy": "true", "datadogMetricName": "nginx-hits", "datadogMetricNamespace": "default", "targetValue": "2", "type": "global"}, map[string]string{"token": "token", "datadogNamespace": "datadog", "datadogMetricsService": "datadog-cluster-agent-metrics-api", "unsafeSsl": "true", "authMode": "bearer"}, false},
 
+	// TODO: Fix this failed test case
 	// both metadata type and trigger type
 	{v2.AverageValueMetricType, map[string]string{"useClusterAgentProxy": "true", "datadogMetricName": "nginx-hits", "datadogMetricNamespace": "default", "targetValue": "2", "type": "global"}, map[string]string{"token": "token", "datadogNamespace": "datadog", "datadogMetricsService": "datadog-cluster-agent-metrics-api", "unsafeSsl": "true", "authMode": "bearer"}, true},
 	// missing DatadogMetric name
@@ -167,27 +168,27 @@ var testDatadogAPIMetadata = []datadogAuthMetadataTestData{
 }
 
 func TestDatadogScalerAPIAuthParams(t *testing.T) {
-	for _, testData := range testDatadogAPIMetadata {
+	for idx, testData := range testDatadogAPIMetadata {
 		_, err := parseDatadogAPIMetadata(&scalersconfig.ScalerConfig{TriggerMetadata: testData.metadata, AuthParams: testData.authParams, MetricType: testData.metricType}, logr.Discard())
 
 		if err != nil && !testData.isError {
-			t.Error("Expected success but got error", err)
+			t.Errorf("Expected success but got error: %s for test case %d", err, idx)
 		}
 		if testData.isError && err == nil {
-			t.Error("Expected error but got success")
+			t.Errorf("Expected error but got success for test case %d", idx)
 		}
 	}
 }
 
 func TestDatadogScalerClusterAgentAuthParams(t *testing.T) {
-	for _, testData := range testDatadogClusterAgentMetadata {
+	for idx, testData := range testDatadogClusterAgentMetadata {
 		_, err := parseDatadogClusterAgentMetadata(&scalersconfig.ScalerConfig{TriggerMetadata: testData.metadata, AuthParams: testData.authParams, MetricType: testData.metricType}, logr.Discard())
 
 		if err != nil && !testData.isError {
-			t.Error("Expected success but got error", err)
+			t.Errorf("Expected success but got error: %s for test case %d", err, idx)
 		}
 		if testData.isError && err == nil {
-			t.Error("Expected error but got success")
+			t.Errorf("Expected error but got success for test case %d", idx)
 		}
 	}
 }
@@ -198,11 +199,12 @@ var datadogMetricIdentifiers = []datadogMetricIdentifier{
 	{&testDatadogClusterAgentMetadata[1], clusterAgentType, 0, "datadogmetric@default:nginx-hits"},
 }
 
+// TODO: Need to check whether we need to rewrite this test case because vType is long deprecated
 func TestDatadogGetMetricSpecForScaling(t *testing.T) {
 	var err error
 	var meta *datadogMetadata
 
-	for _, testData := range datadogMetricIdentifiers {
+	for idx, testData := range datadogMetricIdentifiers {
 		if testData.typeOfScaler == apiType {
 			meta, err = parseDatadogAPIMetadata(&scalersconfig.ScalerConfig{TriggerMetadata: testData.metadataTestData.metadata, AuthParams: testData.metadataTestData.authParams, TriggerIndex: testData.triggerIndex, MetricType: testData.metadataTestData.metricType}, logr.Discard())
 		} else {
@@ -221,7 +223,7 @@ func TestDatadogGetMetricSpecForScaling(t *testing.T) {
 		metricSpec := mockDatadogScaler.GetMetricSpecForScaling(context.Background())
 		metricName := metricSpec[0].External.Metric.Name
 		if metricName != testData.name {
-			t.Error("Wrong External metric source name:", metricName)
+			t.Errorf("Wrong External metric source name:%s for test case %d", metricName, idx)
 		}
 	}
 }
diff --git a/pkg/scalers/gcp_stackdriver_scaler_test.go b/pkg/scalers/gcp_stackdriver_scaler_test.go
index bcf078749..c27ebe869 100644
--- a/pkg/scalers/gcp_stackdriver_scaler_test.go
+++ b/pkg/scalers/gcp_stackdriver_scaler_test.go
@@ -2,10 +2,12 @@ package scalers
 
 import (
 	"context"
+	"reflect"
 	"testing"
 
 	"github.com/go-logr/logr"
 
+	"github.com/kedacore/keda/v2/pkg/scalers/gcp"
 	"github.com/kedacore/keda/v2/pkg/scalers/scalersconfig"
 )
 
@@ -17,81 +19,194 @@ type parseStackdriverMetadataTestData struct {
 	authParams map[string]string
 	metadata   map[string]string
 	isError    bool
-}
-
-type gcpStackdriverMetricIdentifier struct {
-	metadataTestData *parseStackdriverMetadataTestData
-	triggerIndex     int
-	name             string
+	expected   *stackdriverMetadata
+	comment    string
 }
 
 var sdFilter = "metric.type=\"storage.googleapis.com/storage/object_count\" resource.type=\"gcs_bucket\""
 
 var testStackdriverMetadata = []parseStackdriverMetadataTestData{
-	{map[string]string{}, map[string]string{}, true},
-	// all properly formed
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "targetValue": "7", "credentialsFromEnv": "SAMPLE_CREDS", "activationTargetValue": "5"}, false},
-	// all required properly formed
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS"}, false},
-	// missing projectId
-	{nil, map[string]string{"filter": sdFilter, "targetValue": "7", "credentialsFromEnv": "SAMPLE_CREDS"}, true},
-	// missing filter
-	{nil, map[string]string{"projectId": "myProject", "targetValue": "7", "credentialsFromEnv": "SAMPLE_CREDS"}, true},
-	// missing credentials
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "targetValue": "7"}, true},
-	// malformed targetValue
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "targetValue": "aa", "credentialsFromEnv": "SAMPLE_CREDS"}, true},
-	// malformed activationTargetValue
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "activationTargetValue": "a"}, true},
-	// Credentials from AuthParams
-	{map[string]string{"GoogleApplicationCredentials": "Creds"}, map[string]string{"projectId": "myProject", "filter": sdFilter}, false},
-	// Credentials from AuthParams with empty creds
-	{map[string]string{"GoogleApplicationCredentials": ""}, map[string]string{"projectId": "myProject", "filter": sdFilter}, true},
-	// With aggregation info
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "alignmentPeriodSeconds": "120", "alignmentAligner": "sum", "alignmentReducer": "percentile_99"}, false},
-	// With minimal aggregation info
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "alignmentPeriodSeconds": "120"}, false},
-	// With too short alignment period
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "alignmentPeriodSeconds": "30"}, true},
-	// With bad alignment period
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "alignmentPeriodSeconds": "a"}, true},
-	// properly formed float targetValue and activationTargetValue
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "targetValue": "1.1", "activationTargetValue": "2.1"}, false},
-	// properly formed float valueIfNull
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "targetValue": "1.1", "activationTargetValue": "2.1", "valueIfNull": "1.0"}, false},
-	// With bad valueIfNull
-	{nil, map[string]string{"projectId": "myProject", "filter": sdFilter, "credentialsFromEnv": "SAMPLE_CREDS", "targetValue": "1.1", "activationTargetValue": "2.1", "valueIfNull": "toto"}, true},
-}
 
-var gcpStackdriverMetricIdentifiers = []gcpStackdriverMetricIdentifier{
-	{&testStackdriverMetadata[1], 0, "s0-gcp-stackdriver-myProject"},
-	{&testStackdriverMetadata[1], 1, "s1-gcp-stackdriver-myProject"},
+	{
+		authParams: map[string]string{},
+		metadata:   map[string]string{},
+		isError:    true,
+		expected:   nil,
+		comment:    "error case - empty metadata",
+	},
+	{
+		authParams: nil,
+		metadata: map[string]string{
+			"projectId":             "myProject",
+			"filter":                sdFilter,
+			"targetValue":           "7",
+			"credentialsFromEnv":    "SAMPLE_CREDS",
+			"activationTargetValue": "5",
+		},
+		isError: false,
+		expected: &stackdriverMetadata{
+			ProjectID:             "myProject",
+			Filter:                sdFilter,
+			TargetValue:           7,
+			ActivationTargetValue: 5,
+			metricName:            "s0-gcp-stackdriver-myProject",
+			gcpAuthorization: &gcp.AuthorizationMetadata{
+				GoogleApplicationCredentials: "{}",
+				PodIdentityProviderEnabled:   false,
+			},
+		},
+		comment: "all properly formed",
+	},
+	{
+		authParams: nil,
+		metadata: map[string]string{
+			"projectId":          "myProject",
+			"filter":             sdFilter,
+			"credentialsFromEnv": "SAMPLE_CREDS",
+		},
+		isError: false,
+		expected: &stackdriverMetadata{
+			ProjectID:             "myProject",
+			Filter:                sdFilter,
+			TargetValue:           5,
+			ActivationTargetValue: 0,
+			metricName:            "s0-gcp-stackdriver-myProject",
+			gcpAuthorization: &gcp.AuthorizationMetadata{
+				GoogleApplicationCredentials: "{}",
+				PodIdentityProviderEnabled:   false,
+			},
+		},
+		comment: "required fields only with defaults",
+	},
+	{
+		authParams: nil,
+		metadata: map[string]string{
+			"projectId":          "myProject",
+			"filter":             sdFilter,
+			"credentialsFromEnv": "SAMPLE_CREDS",
+			"valueIfNull":        "1.5",
+		},
+		isError: false,
+		expected: &stackdriverMetadata{
+			ProjectID:             "myProject",
+			Filter:                sdFilter,
+			TargetValue:           5,
+			ActivationTargetValue: 0,
+			metricName:            "s0-gcp-stackdriver-myProject",
+			ValueIfNull:           func() *float64 { v := 1.5; return &v }(),
+			gcpAuthorization: &gcp.AuthorizationMetadata{
+				GoogleApplicationCredentials: "{}",
+				PodIdentityProviderEnabled:   false,
+			},
+		},
+		comment: "with valueIfNull configuration",
+	},
+	{
+		authParams: nil,
+		metadata: map[string]string{
+			"filter":             sdFilter,
+			"credentialsFromEnv": "SAMPLE_CREDS",
+		},
+		isError:  true,
+		expected: nil,
+		comment:  "error case - missing projectId",
+	},
+	{
+		authParams: nil,
+		metadata: map[string]string{
+			"projectId":          "myProject",
+			"credentialsFromEnv": "SAMPLE_CREDS",
+		},
+		isError:  true,
+		expected: nil,
+		comment:  "error case - missing filter",
+	},
+	{
+		authParams: nil,
+		metadata: map[string]string{
+			"projectId": "myProject",
+			"filter":    sdFilter,
+		},
+		isError:  true,
+		expected: nil,
+		comment:  "error case - missing credentials",
+	},
 }
 
 func TestStackdriverParseMetadata(t *testing.T) {
 	for _, testData := range testStackdriverMetadata {
-		_, err := parseStackdriverMetadata(&scalersconfig.ScalerConfig{AuthParams: testData.authParams, TriggerMetadata: testData.metadata, ResolvedEnv: testStackdriverResolvedEnv}, logr.Discard())
-		if err != nil && !testData.isError {
-			t.Error("Expected success but got error", err)
-		}
-		if testData.isError && err == nil {
-			t.Error("Expected error but got success")
-		}
+		t.Run(testData.comment, func(t *testing.T) {
+			metadata, err := parseStackdriverMetadata(&scalersconfig.ScalerConfig{
+				AuthParams:      testData.authParams,
+				TriggerMetadata: testData.metadata,
+				ResolvedEnv:     testStackdriverResolvedEnv,
+			}, logr.Discard())
+
+			if err != nil && !testData.isError {
+				t.Errorf("Expected success but got error")
+			}
+
+			if testData.isError && err == nil {
+				t.Errorf("Expected error but got success")
+			}
+
+			if !testData.isError && !reflect.DeepEqual(testData.expected, metadata) {
+				t.Fatalf("Expected %#v but got %+#v", testData.expected, metadata)
+			}
+		})
 	}
 }
 
+var gcpStackdriverMetricIdentifiers = []struct {
+	comment      string
+	triggerIndex int
+	metadata     map[string]string
+	expectedName string
+}{
+	{
+		comment:      "basic metric name",
+		triggerIndex: 0,
+		metadata: map[string]string{
+			"projectId":          "myProject",
+			"filter":             sdFilter,
+			"credentialsFromEnv": "SAMPLE_CREDS",
+		},
+		expectedName: "s0-gcp-stackdriver-myProject",
+	},
+	{
+		comment:      "metric name with different index",
+		triggerIndex: 1,
+		metadata: map[string]string{
+			"projectId":          "myProject",
+			"filter":             sdFilter,
+			"credentialsFromEnv": "SAMPLE_CREDS",
+		},
+		expectedName: "s1-gcp-stackdriver-myProject",
+	},
+}
+
 func TestGcpStackdriverGetMetricSpecForScaling(t *testing.T) {
-	for _, testData := range gcpStackdriverMetricIdentifiers {
-		meta, err := parseStackdriverMetadata(&scalersconfig.ScalerConfig{TriggerMetadata: testData.metadataTestData.metadata, ResolvedEnv: testStackdriverResolvedEnv, TriggerIndex: testData.triggerIndex}, logr.Discard())
-		if err != nil {
-			t.Fatal("Could not parse metadata:", err)
-		}
-		mockGcpStackdriverScaler := stackdriverScaler{nil, "", meta, logr.Discard()}
-
-		metricSpec := mockGcpStackdriverScaler.GetMetricSpecForScaling(context.Background())
-		metricName := metricSpec[0].External.Metric.Name
-		if metricName != testData.name {
-			t.Error("Wrong External metric source name:", metricName)
-		}
+	for _, test := range gcpStackdriverMetricIdentifiers {
+		t.Run(test.comment, func(t *testing.T) {
+			meta, err := parseStackdriverMetadata(&scalersconfig.ScalerConfig{
+				TriggerMetadata: test.metadata,
+				ResolvedEnv:     testStackdriverResolvedEnv,
+				TriggerIndex:    test.triggerIndex,
+			}, logr.Discard())
+			if err != nil {
+				t.Fatal("Could not parse metadata:", err)
+			}
+
+			mockScaler := stackdriverScaler{
+				metadata: meta,
+				logger:   logr.Discard(),
+			}
+
+			metricSpec := mockScaler.GetMetricSpecForScaling(context.Background())
+			metricName := metricSpec[0].External.Metric.Name
+			if metricName != test.expectedName {
+				t.Errorf("Wrong metric name - got %s, want %s", metricName, test.expectedName)
+			}
+		})
 	}
 }
diff --git a/pkg/scalers/temporal_test.go b/pkg/scalers/temporal_test.go
index 7423199fe..641c9afe3 100644
--- a/pkg/scalers/temporal_test.go
+++ b/pkg/scalers/temporal_test.go
@@ -224,6 +224,30 @@ func TestParseTemporalMetadata(t *testing.T) {
 			},
 			wantErr: false,
 		},
+		{
+			name: "apiKey provided",
+			metadata: map[string]string{
+				"endpoint":  "test:7233",
+				"namespace": "default",
+				"taskQueue": "testxx",
+				"apiKey":    "test-api-key",
+			},
+			wantMeta: &temporalMetadata{
+				Endpoint:                  "test:7233",
+				Namespace:                 "default",
+				TaskQueue:                 "testxx",
+				TargetQueueSize:           5,
+				ActivationTargetQueueSize: 0,
+				AllActive:                 false,
+				Unversioned:               false,
+				APIKey:                    "test-api-key",
+				MinConnectTimeout:         5,
+			},
+			authParams: map[string]string{
+				"apiKey": "test-api-key",
+			},
+			wantErr: false,
+		},
 	}
 
 	for _, testCase := range cases {