Allow passing multiple `--config` flags to daprd in standalone mode

Spin-off from #6101 where support for Kubernetes mode has been dropped, to avoid modifying the CRDs.

Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
ItalyPaleAle 2023-06-29 21:12:48 +00:00
parent 46813f2fd2
commit 1e268507d1
36 changed files with 963 additions and 493 deletions

View File

@ -135,6 +135,7 @@ linters-settings:
- "github.com/cenkalti/backoff/v3": "must use github.com/cenkalti/backoff/v4"
- "github.com/benbjohnson/clock": "must use k8s.io/utils/clock"
- "github.com/ghodss/yaml": "must use sigs.k8s.io/yaml"
- "gopkg.in/yaml.v2": "must use gopkg.in/yaml.v3"
misspell:
# Correct spellings using locale preferences for US or UK.
# Default is to use a neutral variety of English.

View File

@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.2
controller-gen.kubebuilder.io/version: v0.11.3
creationTimestamp: null
name: configurations.dapr.io
labels:

View File

@ -74,8 +74,8 @@ func main() {
log.Fatal(err)
}
log.Infof("starting Dapr Runtime -- version %s -- commit %s", buildinfo.Version(), buildinfo.Commit())
log.Infof("log level set to: %s", opts.Logger.OutputLevel)
log.Infof("Starting Dapr Runtime -- version %s -- commit %s", buildinfo.Version(), buildinfo.Commit())
log.Infof("Log level set to: %s", opts.Logger.OutputLevel)
rt, err := runtime.FromConfig(&runtime.Config{
AppID: opts.AppID,
@ -108,7 +108,7 @@ func main() {
AppHealthThreshold: opts.AppHealthThreshold,
AppChannelAddress: opts.AppChannelAddress,
EnableAPILogging: opts.EnableAPILogging,
ConfigPath: opts.ConfigPath,
Config: opts.Config,
Metrics: opts.Metrics,
AppSSL: opts.AppSSL,
ComponentsPath: opts.ComponentsPath,

View File

@ -14,7 +14,6 @@ limitations under the License.
package options
import (
"errors"
"flag"
"strconv"
"strings"
@ -61,7 +60,7 @@ type Options struct {
AppHealthThreshold int
EnableAppHealthCheck bool
Mode string
ConfigPath string
Config stringSliceFlag
UnixDomainSocket string
DaprHTTPReadBufferSize int
DisableBuiltinK8sSecretStore bool
@ -87,7 +86,7 @@ func New(args []string) *Options {
flag.StringVar(&opts.AppProtocol, "app-protocol", string(protocol.HTTPProtocol), "Protocol for the application: grpc, grpcs, http, https, h2c")
flag.StringVar(&opts.ComponentsPath, "components-path", "", "Alias for --resources-path [Deprecated, use --resources-path]")
flag.Var(&opts.ResourcesPath, "resources-path", "Path for resources directory. If not specified, no resources will be loaded. Can be passed multiple times")
flag.StringVar(&opts.ConfigPath, "config", "", "Path to config file, or name of a configuration object")
flag.Var(&opts.Config, "config", "Path to config file, or name of a configuration object. In standalone mode, can be passed multiple times")
flag.StringVar(&opts.AppID, "app-id", "", "A unique ID for Dapr. Used for Service Discovery and state")
flag.StringVar(&opts.ControlPlaneAddress, "control-plane-address", "", "Address for a Dapr control plane")
flag.StringVar(&opts.SentryAddress, "sentry-address", "", "Address for the Sentry CA service")
@ -151,7 +150,7 @@ func (f stringSliceFlag) String() string {
// Set the flag value.
func (f *stringSliceFlag) Set(value string) error {
if value == "" {
return errors.New("value is empty")
return nil
}
*f = append(*f, value)
return nil

View File

@ -40,5 +40,5 @@ func TestStandaloneGlobalConfig(t *testing.T) {
opts := New([]string{"--app-id", "testapp", "--mode", string(modes.StandaloneMode), "--config", "../../../pkg/config/testdata/metric_disabled.yaml", "--metrics-port", strconv.Itoa(10000)})
assert.EqualValues(t, "testapp", opts.AppID)
assert.EqualValues(t, string(modes.StandaloneMode), opts.Mode)
assert.Equal(t, "../../../pkg/config/testdata/metric_disabled.yaml", opts.ConfigPath)
assert.Equal(t, []string{"../../../pkg/config/testdata/metric_disabled.yaml"}, []string(opts.Config))
}

4
go.mod
View File

@ -62,7 +62,7 @@ require (
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1
google.golang.org/grpc v1.54.0
google.golang.org/protobuf v1.30.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.26.3
k8s.io/apiextensions-apiserver v0.26.3
k8s.io/apimachinery v0.26.3
@ -399,7 +399,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/component-base v0.26.3 // indirect
k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect
k8s.io/klog/v2 v2.80.1 // indirect

View File

@ -35,25 +35,26 @@ import (
var log = logger.NewLogger("dapr.acl")
// ParseAccessControlSpec creates an in-memory copy of the Access Control Spec for fast lookup.
func ParseAccessControlSpec(accessControlSpec config.AccessControlSpec, isHTTP bool) (*config.AccessControlList, error) {
if accessControlSpec.TrustDomain == "" &&
accessControlSpec.DefaultAction == "" &&
(accessControlSpec.AppPolicies == nil || len(accessControlSpec.AppPolicies) == 0) {
func ParseAccessControlSpec(accessControlSpec *config.AccessControlSpec, isHTTP bool) (*config.AccessControlList, error) {
if accessControlSpec == nil ||
(accessControlSpec.TrustDomain == "" &&
accessControlSpec.DefaultAction == "" &&
len(accessControlSpec.AppPolicies) == 0) {
// No ACL has been specified
log.Debugf("No Access control policy specified")
return nil, nil
}
var accessControlList config.AccessControlList
accessControlList.PolicySpec = make(map[string]config.AccessControlListPolicySpec)
accessControlList.DefaultAction = strings.ToLower(accessControlSpec.DefaultAction)
accessControlList := config.AccessControlList{
PolicySpec: make(map[string]config.AccessControlListPolicySpec),
DefaultAction: strings.ToLower(accessControlSpec.DefaultAction),
TrustDomain: accessControlSpec.TrustDomain,
}
accessControlList.TrustDomain = accessControlSpec.TrustDomain
if accessControlSpec.TrustDomain == "" {
accessControlList.TrustDomain = config.DefaultTrustDomain
}
accessControlList.DefaultAction = accessControlSpec.DefaultAction
if accessControlSpec.DefaultAction == "" {
if accessControlSpec.AppPolicies == nil || len(accessControlSpec.AppPolicies) > 0 {
// Some app level policies have been specified but not default global action is set. Default to more secure option - Deny

View File

@ -18,6 +18,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/dapr/dapr/pkg/config"
"github.com/dapr/dapr/pkg/proto/common/v1"
@ -130,7 +131,7 @@ func initializeAccessControlList(isHTTP bool) (*config.AccessControlList, error)
},
},
}
accessControlList, err := ParseAccessControlSpec(inputSpec, isHTTP)
accessControlList, err := ParseAccessControlSpec(&inputSpec, isHTTP)
return accessControlList, err
}
@ -139,7 +140,7 @@ func TestParseAccessControlSpec(t *testing.T) {
t.Run("translate to in-memory rules", func(t *testing.T) {
accessControlList, err := initializeAccessControlList(true)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, config.DenyAccess, accessControlList.DefaultAction)
assert.Equal(t, "abcd", accessControlList.TrustDomain)
@ -237,7 +238,7 @@ func TestParseAccessControlSpec(t *testing.T) {
})
t.Run("test when no trust domain and namespace specified in app policy", func(t *testing.T) {
invalidAccessControlSpec := config.AccessControlSpec{
invalidAccessControlSpec := &config.AccessControlSpec{
DefaultAction: config.DenyAccess,
TrustDomain: "public",
AppPolicies: []config.AppPolicySpec{
@ -300,7 +301,7 @@ func TestParseAccessControlSpec(t *testing.T) {
})
t.Run("test when no trust domain is specified for the app", func(t *testing.T) {
accessControlSpec := config.AccessControlSpec{
accessControlSpec := &config.AccessControlSpec{
DefaultAction: config.DenyAccess,
TrustDomain: "",
AppPolicies: []config.AppPolicySpec{
@ -330,18 +331,23 @@ func TestParseAccessControlSpec(t *testing.T) {
})
t.Run("test when no access control policy has been specified", func(t *testing.T) {
invalidAccessControlSpec := config.AccessControlSpec{
accessControlList, err := ParseAccessControlSpec(nil, true)
require.NoError(t, err)
assert.Nil(t, accessControlList)
invalidAccessControlSpec := &config.AccessControlSpec{
DefaultAction: "",
TrustDomain: "",
AppPolicies: []config.AppPolicySpec{},
}
accessControlList, _ := ParseAccessControlSpec(invalidAccessControlSpec, true)
accessControlList, _ = ParseAccessControlSpec(invalidAccessControlSpec, true)
require.NoError(t, err)
assert.Nil(t, accessControlList)
})
t.Run("test when no default global action has been specified", func(t *testing.T) {
invalidAccessControlSpec := config.AccessControlSpec{
invalidAccessControlSpec := &config.AccessControlSpec{
TrustDomain: "public",
AppPolicies: []config.AppPolicySpec{
{
@ -377,25 +383,25 @@ func TestSpiffeID(t *testing.T) {
assert.Equal(t, "mydomain", id.TrustDomain)
assert.Equal(t, "mynamespace", id.Namespace)
assert.Equal(t, "myappid", id.AppID)
assert.Nil(t, err)
require.NoError(t, err)
})
t.Run("test parse invalid spiffe id", func(t *testing.T) {
spiffeID := "abcd"
_, err := parseSpiffeID(spiffeID)
assert.NotNil(t, err)
require.Error(t, err)
})
t.Run("test parse spiffe id with not all fields", func(t *testing.T) {
spiffeID := "spiffe://mydomain/ns/myappid"
_, err := parseSpiffeID(spiffeID)
assert.NotNil(t, err)
require.Error(t, err)
})
t.Run("test empty spiffe id", func(t *testing.T) {
spiffeID := ""
_, err := parseSpiffeID(spiffeID)
assert.NotNil(t, err)
require.Error(t, err)
})
}

View File

@ -36,31 +36,31 @@ type Configuration struct {
// ConfigurationSpec is the spec for an configuration.
type ConfigurationSpec struct {
// +optional
AppHTTPPipelineSpec PipelineSpec `json:"appHttpPipeline,omitempty"`
AppHTTPPipelineSpec *PipelineSpec `json:"appHttpPipeline,omitempty"`
// +optional
HTTPPipelineSpec PipelineSpec `json:"httpPipeline,omitempty"`
HTTPPipelineSpec *PipelineSpec `json:"httpPipeline,omitempty"`
// +optional
TracingSpec TracingSpec `json:"tracing,omitempty"`
TracingSpec *TracingSpec `json:"tracing,omitempty"`
// +kubebuilder:default={enabled:true}
MetricSpec MetricSpec `json:"metric,omitempty"`
MetricSpec *MetricSpec `json:"metric,omitempty"`
// +kubebuilder:default={enabled:true}
MetricsSpec MetricSpec `json:"metrics,omitempty"`
MetricsSpec *MetricSpec `json:"metrics,omitempty"`
// +optional
MTLSSpec MTLSSpec `json:"mtls,omitempty"`
MTLSSpec *MTLSSpec `json:"mtls,omitempty"`
// +optional
Secrets SecretsSpec `json:"secrets,omitempty"`
Secrets *SecretsSpec `json:"secrets,omitempty"`
// +optional
AccessControlSpec AccessControlSpec `json:"accessControl,omitempty"`
AccessControlSpec *AccessControlSpec `json:"accessControl,omitempty"`
// +optional
NameResolutionSpec NameResolutionSpec `json:"nameResolution,omitempty"`
NameResolutionSpec *NameResolutionSpec `json:"nameResolution,omitempty"`
// +optional
Features []FeatureSpec `json:"features,omitempty"`
// +optional
APISpec APISpec `json:"api,omitempty"`
APISpec *APISpec `json:"api,omitempty"`
// +optional
ComponentsSpec ComponentsSpec `json:"components,omitempty"`
ComponentsSpec *ComponentsSpec `json:"components,omitempty"`
// +optional
LoggingSpec LoggingSpec `json:"logging,omitempty"`
LoggingSpec *LoggingSpec `json:"logging,omitempty"`
}
// APISpec describes the configuration for Dapr APIs.
@ -78,14 +78,14 @@ type APIAccessRule struct {
Name string `json:"name"`
Version string `json:"version"`
// +optional
Protocol string `json:"protocol"`
Protocol string `json:"protocol,omitempty"`
}
// NameResolutionSpec is the spec for name resolution configuration.
type NameResolutionSpec struct {
Component string `json:"component"`
Version string `json:"version"`
Configuration DynamicValue `json:"configuration"`
Component string `json:"component"`
Version string `json:"version"`
Configuration *DynamicValue `json:"configuration"`
}
// SecretsSpec is the spec for secrets configuration.
@ -95,9 +95,9 @@ type SecretsSpec struct {
// SecretsScope defines the scope for secrets.
type SecretsScope struct {
StoreName string `json:"storeName"`
// +optional
DefaultAccess string `json:"defaultAccess,omitempty"`
StoreName string `json:"storeName"`
// +optional
AllowedSecrets []string `json:"allowedSecrets,omitempty"`
// +optional
@ -111,18 +111,25 @@ type PipelineSpec struct {
// HandlerSpec defines a request handlers.
type HandlerSpec struct {
Name string `json:"name"`
Type string `json:"type"`
SelectorSpec SelectorSpec `json:"selector,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
// +optional
SelectorSpec *SelectorSpec `json:"selector,omitempty"`
}
// MTLSSpec defines mTLS configuration.
type MTLSSpec struct {
Enabled bool `json:"enabled"`
Enabled *bool `json:"enabled"`
// +optional
WorkloadCertTTL string `json:"workloadCertTTL"`
WorkloadCertTTL *string `json:"workloadCertTTL,omitempty"`
// +optional
AllowedClockSkew string `json:"allowedClockSkew"`
AllowedClockSkew *string `json:"allowedClockSkew,omitempty"`
}
// GetEnabled returns true if mTLS is enabled.
func (m *MTLSSpec) GetEnabled() bool {
// Defaults to true if unset
return m == nil || m.Enabled == nil || *m.Enabled
}
// SelectorSpec selects target services to which the handler is to be applied.
@ -140,18 +147,18 @@ type SelectorField struct {
type TracingSpec struct {
SamplingRate string `json:"samplingRate"`
// +optional
Stdout bool `json:"stdout"`
Stdout *bool `json:"stdout,omitempty"`
// +optional
Zipkin ZipkinSpec `json:"zipkin"`
Zipkin *ZipkinSpec `json:"zipkin,omitempty"`
// +optional
Otel OtelSpec `json:"otel"`
Otel *OtelSpec `json:"otel,omitempty"`
}
// OtelSpec defines Otel exporter configurations.
type OtelSpec struct {
Protocol string `json:"protocol" yaml:"protocol"`
EndpointAddress string `json:"endpointAddress" yaml:"endpointAddress"`
IsSecure bool `json:"isSecure" yaml:"isSecure"`
IsSecure *bool `json:"isSecure" yaml:"isSecure"`
}
// ZipkinSpec defines Zipkin trace configurations.
@ -161,9 +168,9 @@ type ZipkinSpec struct {
// MetricSpec defines metrics configuration.
type MetricSpec struct {
Enabled bool `json:"enabled"`
Enabled *bool `json:"enabled"`
// +optional
Rules []MetricsRule `json:"rules"`
Rules []MetricsRule `json:"rules,omitempty"`
}
// MetricsRule defines configuration options for a metric.
@ -182,37 +189,37 @@ type MetricLabel struct {
type AppPolicySpec struct {
AppName string `json:"appId" yaml:"appId"`
// +optional
DefaultAction string `json:"defaultAction" yaml:"defaultAction"`
DefaultAction string `json:"defaultAction,omitempty" yaml:"defaultAction,omitempty"`
// +optional
TrustDomain string `json:"trustDomain" yaml:"trustDomain"`
TrustDomain string `json:"trustDomain,omitempty" yaml:"trustDomain,omitempty"`
// +optional
Namespace string `json:"namespace" yaml:"namespace"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
// +optional
AppOperationActions []AppOperationAction `json:"operations" yaml:"operations"`
AppOperationActions []AppOperationAction `json:"operations,omitempty" yaml:"operations,omitempty"`
}
// AppOperationAction defines the data structure for each app operation.
type AppOperationAction struct {
Operation string `json:"name" yaml:"name"`
Action string `json:"action" yaml:"action"`
// +optional
HTTPVerb []string `json:"httpVerb" yaml:"httpVerb"`
Action string `json:"action" yaml:"action"`
HTTPVerb []string `json:"httpVerb,omitempty" yaml:"httpVerb,omitempty"`
}
// AccessControlSpec is the spec object in ConfigurationSpec.
type AccessControlSpec struct {
// +optional
DefaultAction string `json:"defaultAction" yaml:"defaultAction"`
DefaultAction string `json:"defaultAction,omitempty" yaml:"defaultAction,omitempty"`
// +optional
TrustDomain string `json:"trustDomain" yaml:"trustDomain"`
TrustDomain string `json:"trustDomain,omitempty" yaml:"trustDomain,omitempty"`
// +optional
AppPolicies []AppPolicySpec `json:"policies" yaml:"policies"`
AppPolicies []AppPolicySpec `json:"policies,omitempty" yaml:"policies,omitempty"`
}
// FeatureSpec defines the features that are enabled/disabled.
type FeatureSpec struct {
Name string `json:"name" yaml:"name"`
Enabled bool `json:"enabled" yaml:"enabled"`
Enabled *bool `json:"enabled" yaml:"enabled"`
}
// ComponentsSpec describes the configuration for Dapr components
@ -222,6 +229,30 @@ type ComponentsSpec struct {
Deny []string `json:"deny,omitempty" yaml:"deny,omitempty"`
}
// LoggingSpec defines the configuration for logging.
type LoggingSpec struct {
// Configure API logging.
// +optional
APILogging *APILoggingSpec `json:"apiLogging,omitempty" yaml:"apiLogging,omitempty"`
}
// APILoggingSpec defines the configuration for API logging.
type APILoggingSpec struct {
// Default value for enabling API logging. Sidecars can always override this by setting `--enable-api-logging` to true or false explicitly.
// The default value is false.
// +optional
Enabled *bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`
// When enabled, obfuscates the values of URLs in HTTP API logs, logging the route name rather than the full path being invoked, which could contain PII.
// Default: false.
// This option has no effect if API logging is disabled.
// +optional
ObfuscateURLs *bool `json:"obfuscateURLs,omitempty" yaml:"obfuscateURLs,omitempty"`
// If true, health checks are not reported in API logs. Default: false.
// This option has no effect if API logging is disabled.
// +optional
OmitHealthChecks *bool `json:"omitHealthChecks,omitempty" yaml:"omitHealthChecks,omitempty"`
}
// +kubebuilder:object:root=true
// ConfigurationList is a list of Dapr event sources.
@ -232,30 +263,6 @@ type ConfigurationList struct {
Items []Configuration `json:"items"`
}
// LoggingSpec defines the configuration for logging.
type LoggingSpec struct {
// Configure API logging.
// +optional
APILogging APILoggingSpec `json:"apiLogging" yaml:"apiLogging"`
}
// APILoggingSpec defines the configuration for API logging.
type APILoggingSpec struct {
// Default value for enabling API logging. Sidecars can always override this by setting `--enable-api-logging` to true or false explicitly.
// The default value is false.
// +optional
Enabled bool `json:"enabled" yaml:"enabled"`
// When enabled, obfuscates the values of URLs in HTTP API logs, logging the route name rather than the full path being invoked, which could contain PII.
// Default: false.
// This option has no effect if API logging is disabled.
// +optional
ObfuscateURLs bool `json:"obfuscateURLs" yaml:"obfuscateURLs"`
// If true, health checks are not reported in API logs. Default: false.
// This option has no effect if API logging is disabled.
// +optional
OmitHealthChecks bool `json:"omitHealthChecks" yaml:"omitHealthChecks"`
}
// DynamicValue is a dynamic value struct for the component.metadata pair value.
type DynamicValue struct {
v1.JSON `json:",inline"`

View File

@ -43,6 +43,21 @@ func (in *APIAccessRule) DeepCopy() *APIAccessRule {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *APILoggingSpec) DeepCopyInto(out *APILoggingSpec) {
*out = *in
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
}
if in.ObfuscateURLs != nil {
in, out := &in.ObfuscateURLs, &out.ObfuscateURLs
*out = new(bool)
**out = **in
}
if in.OmitHealthChecks != nil {
in, out := &in.OmitHealthChecks, &out.OmitHealthChecks
*out = new(bool)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APILoggingSpec.
@ -225,23 +240,73 @@ func (in *ConfigurationList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConfigurationSpec) DeepCopyInto(out *ConfigurationSpec) {
*out = *in
in.AppHTTPPipelineSpec.DeepCopyInto(&out.AppHTTPPipelineSpec)
in.HTTPPipelineSpec.DeepCopyInto(&out.HTTPPipelineSpec)
out.TracingSpec = in.TracingSpec
in.MetricSpec.DeepCopyInto(&out.MetricSpec)
in.MetricsSpec.DeepCopyInto(&out.MetricsSpec)
out.MTLSSpec = in.MTLSSpec
in.Secrets.DeepCopyInto(&out.Secrets)
in.AccessControlSpec.DeepCopyInto(&out.AccessControlSpec)
in.NameResolutionSpec.DeepCopyInto(&out.NameResolutionSpec)
if in.AppHTTPPipelineSpec != nil {
in, out := &in.AppHTTPPipelineSpec, &out.AppHTTPPipelineSpec
*out = new(PipelineSpec)
(*in).DeepCopyInto(*out)
}
if in.HTTPPipelineSpec != nil {
in, out := &in.HTTPPipelineSpec, &out.HTTPPipelineSpec
*out = new(PipelineSpec)
(*in).DeepCopyInto(*out)
}
if in.TracingSpec != nil {
in, out := &in.TracingSpec, &out.TracingSpec
*out = new(TracingSpec)
(*in).DeepCopyInto(*out)
}
if in.MetricSpec != nil {
in, out := &in.MetricSpec, &out.MetricSpec
*out = new(MetricSpec)
(*in).DeepCopyInto(*out)
}
if in.MetricsSpec != nil {
in, out := &in.MetricsSpec, &out.MetricsSpec
*out = new(MetricSpec)
(*in).DeepCopyInto(*out)
}
if in.MTLSSpec != nil {
in, out := &in.MTLSSpec, &out.MTLSSpec
*out = new(MTLSSpec)
(*in).DeepCopyInto(*out)
}
if in.Secrets != nil {
in, out := &in.Secrets, &out.Secrets
*out = new(SecretsSpec)
(*in).DeepCopyInto(*out)
}
if in.AccessControlSpec != nil {
in, out := &in.AccessControlSpec, &out.AccessControlSpec
*out = new(AccessControlSpec)
(*in).DeepCopyInto(*out)
}
if in.NameResolutionSpec != nil {
in, out := &in.NameResolutionSpec, &out.NameResolutionSpec
*out = new(NameResolutionSpec)
(*in).DeepCopyInto(*out)
}
if in.Features != nil {
in, out := &in.Features, &out.Features
*out = make([]FeatureSpec, len(*in))
copy(*out, *in)
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.APISpec != nil {
in, out := &in.APISpec, &out.APISpec
*out = new(APISpec)
(*in).DeepCopyInto(*out)
}
if in.ComponentsSpec != nil {
in, out := &in.ComponentsSpec, &out.ComponentsSpec
*out = new(ComponentsSpec)
(*in).DeepCopyInto(*out)
}
if in.LoggingSpec != nil {
in, out := &in.LoggingSpec, &out.LoggingSpec
*out = new(LoggingSpec)
(*in).DeepCopyInto(*out)
}
in.APISpec.DeepCopyInto(&out.APISpec)
in.ComponentsSpec.DeepCopyInto(&out.ComponentsSpec)
out.LoggingSpec = in.LoggingSpec
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationSpec.
@ -273,6 +338,11 @@ func (in *DynamicValue) DeepCopy() *DynamicValue {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FeatureSpec) DeepCopyInto(out *FeatureSpec) {
*out = *in
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureSpec.
@ -288,7 +358,11 @@ func (in *FeatureSpec) DeepCopy() *FeatureSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HandlerSpec) DeepCopyInto(out *HandlerSpec) {
*out = *in
in.SelectorSpec.DeepCopyInto(&out.SelectorSpec)
if in.SelectorSpec != nil {
in, out := &in.SelectorSpec, &out.SelectorSpec
*out = new(SelectorSpec)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HandlerSpec.
@ -304,7 +378,11 @@ func (in *HandlerSpec) DeepCopy() *HandlerSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LoggingSpec) DeepCopyInto(out *LoggingSpec) {
*out = *in
out.APILogging = in.APILogging
if in.APILogging != nil {
in, out := &in.APILogging, &out.APILogging
*out = new(APILoggingSpec)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoggingSpec.
@ -320,6 +398,21 @@ func (in *LoggingSpec) DeepCopy() *LoggingSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MTLSSpec) DeepCopyInto(out *MTLSSpec) {
*out = *in
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
}
if in.WorkloadCertTTL != nil {
in, out := &in.WorkloadCertTTL, &out.WorkloadCertTTL
*out = new(string)
**out = **in
}
if in.AllowedClockSkew != nil {
in, out := &in.AllowedClockSkew, &out.AllowedClockSkew
*out = new(string)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MTLSSpec.
@ -357,6 +450,11 @@ func (in *MetricLabel) DeepCopy() *MetricLabel {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
*out = *in
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
}
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]MetricsRule, len(*in))
@ -401,7 +499,11 @@ func (in *MetricsRule) DeepCopy() *MetricsRule {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NameResolutionSpec) DeepCopyInto(out *NameResolutionSpec) {
*out = *in
in.Configuration.DeepCopyInto(&out.Configuration)
if in.Configuration != nil {
in, out := &in.Configuration, &out.Configuration
*out = new(DynamicValue)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NameResolutionSpec.
@ -417,6 +519,11 @@ func (in *NameResolutionSpec) DeepCopy() *NameResolutionSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OtelSpec) DeepCopyInto(out *OtelSpec) {
*out = *in
if in.IsSecure != nil {
in, out := &in.IsSecure, &out.IsSecure
*out = new(bool)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OtelSpec.
@ -536,8 +643,21 @@ func (in *SelectorSpec) DeepCopy() *SelectorSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TracingSpec) DeepCopyInto(out *TracingSpec) {
*out = *in
out.Zipkin = in.Zipkin
out.Otel = in.Otel
if in.Stdout != nil {
in, out := &in.Stdout, &out.Stdout
*out = new(bool)
**out = **in
}
if in.Zipkin != nil {
in, out := &in.Zipkin, &out.Zipkin
*out = new(ZipkinSpec)
**out = **in
}
if in.Otel != nil {
in, out := &in.Otel, &out.Otel
*out = new(OtelSpec)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingSpec.

View File

@ -25,13 +25,14 @@ import (
env "github.com/dapr/dapr/pkg/config/env"
grpcRetry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
yaml "gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"github.com/dapr/dapr/pkg/buildinfo"
operatorv1pb "github.com/dapr/dapr/pkg/proto/operator/v1"
"github.com/dapr/dapr/utils"
"github.com/dapr/kit/ptr"
)
// Feature Flags section
@ -99,35 +100,35 @@ type AccessControlListOperationAction struct {
}
type ConfigurationSpec struct {
HTTPPipelineSpec PipelineSpec `json:"httpPipeline,omitempty" yaml:"httpPipeline,omitempty"`
AppHTTPPipelineSpec PipelineSpec `json:"appHttpPipeline,omitempty" yaml:"appHttpPipeline,omitempty"`
TracingSpec TracingSpec `json:"tracing,omitempty" yaml:"tracing,omitempty"`
MTLSSpec MTLSSpec `json:"mtls,omitempty" yaml:"mtls,omitempty"`
MetricSpec MetricSpec `json:"metric,omitempty" yaml:"metric,omitempty"`
MetricsSpec MetricSpec `json:"metrics,omitempty" yaml:"metrics,omitempty"`
Secrets SecretsSpec `json:"secrets,omitempty" yaml:"secrets,omitempty"`
AccessControlSpec AccessControlSpec `json:"accessControl,omitempty" yaml:"accessControl,omitempty"`
NameResolutionSpec NameResolutionSpec `json:"nameResolution,omitempty" yaml:"nameResolution,omitempty"`
Features []FeatureSpec `json:"features,omitempty" yaml:"features,omitempty"`
APISpec APISpec `json:"api,omitempty" yaml:"api,omitempty"`
ComponentsSpec ComponentsSpec `json:"components,omitempty" yaml:"components,omitempty"`
LoggingSpec LoggingSpec `json:"logging,omitempty" yaml:"logging,omitempty"`
HTTPPipelineSpec *PipelineSpec `json:"httpPipeline,omitempty" yaml:"httpPipeline,omitempty"`
AppHTTPPipelineSpec *PipelineSpec `json:"appHttpPipeline,omitempty" yaml:"appHttpPipeline,omitempty"`
TracingSpec *TracingSpec `json:"tracing,omitempty" yaml:"tracing,omitempty"`
MTLSSpec *MTLSSpec `json:"mtls,omitempty" yaml:"mtls,omitempty"`
MetricSpec *MetricSpec `json:"metric,omitempty" yaml:"metric,omitempty"`
MetricsSpec *MetricSpec `json:"metrics,omitempty" yaml:"metrics,omitempty"`
Secrets *SecretsSpec `json:"secrets,omitempty" yaml:"secrets,omitempty"`
AccessControlSpec *AccessControlSpec `json:"accessControl,omitempty" yaml:"accessControl,omitempty"`
NameResolutionSpec *NameResolutionSpec `json:"nameResolution,omitempty" yaml:"nameResolution,omitempty"`
Features []FeatureSpec `json:"features,omitempty" yaml:"features,omitempty"`
APISpec *APISpec `json:"api,omitempty" yaml:"api,omitempty"`
ComponentsSpec *ComponentsSpec `json:"components,omitempty" yaml:"components,omitempty"`
LoggingSpec *LoggingSpec `json:"logging,omitempty" yaml:"logging,omitempty"`
}
type SecretsSpec struct {
Scopes []SecretsScope `json:"scopes"`
Scopes []SecretsScope `json:"scopes,omitempty"`
}
// SecretsScope defines the scope for secrets.
type SecretsScope struct {
DefaultAccess string `json:"defaultAccess,omitempty" yaml:"defaultAccess,omitempty"`
StoreName string `json:"storeName" yaml:"storeName"`
StoreName string `json:"storeName,omitempty" yaml:"storeName,omitempty"`
AllowedSecrets []string `json:"allowedSecrets,omitempty" yaml:"allowedSecrets,omitempty"`
DeniedSecrets []string `json:"deniedSecrets,omitempty" yaml:"deniedSecrets,omitempty"`
}
type PipelineSpec struct {
Handlers []HandlerSpec `json:"handlers" yaml:"handlers"`
Handlers []HandlerSpec `json:"handlers,omitempty" yaml:"handlers,omitempty"`
}
// APISpec describes the configuration for Dapr APIs.
@ -171,9 +172,9 @@ func (r APIAccessRules) GetRulesByProtocol(protocol APIAccessRuleProtocol) []API
}
type HandlerSpec struct {
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
Version string `json:"version" yaml:"version"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
SelectorSpec SelectorSpec `json:"selector,omitempty" yaml:"selector,omitempty"`
}
@ -183,7 +184,7 @@ func (h HandlerSpec) LogName() string {
}
type SelectorSpec struct {
Fields []SelectorField `json:"fields" yaml:"fields"`
Fields []SelectorField `json:"fields,omitempty" yaml:"fields,omitempty"`
}
type SelectorField struct {
@ -192,75 +193,89 @@ type SelectorField struct {
}
type TracingSpec struct {
SamplingRate string `json:"samplingRate" yaml:"samplingRate"`
Stdout bool `json:"stdout" yaml:"stdout"`
Zipkin ZipkinSpec `json:"zipkin" yaml:"zipkin"`
Otel OtelSpec `json:"otel" yaml:"otel"`
SamplingRate string `json:"samplingRate,omitempty" yaml:"samplingRate,omitempty"`
Stdout bool `json:"stdout,omitempty" yaml:"stdout,omitempty"`
Zipkin *ZipkinSpec `json:"zipkin,omitempty" yaml:"zipkin,omitempty"`
Otel *OtelSpec `json:"otel,omitempty" yaml:"otel,omitempty"`
}
// ZipkinSpec defines Zipkin exporter configurations.
type ZipkinSpec struct {
EndpointAddress string `json:"endpointAddress" yaml:"endpointAddress"`
EndpointAddress string `json:"endpointAddress,omitempty" yaml:"endpointAddress,omitempty"`
}
// OtelSpec defines Otel exporter configurations.
type OtelSpec struct {
Protocol string `json:"protocol" yaml:"protocol"`
EndpointAddress string `json:"endpointAddress" yaml:"endpointAddress"`
IsSecure bool `json:"isSecure" yaml:"isSecure"`
Protocol string `json:"protocol,omitempty" yaml:"protocol,omitempty"`
EndpointAddress string `json:"endpointAddress,omitempty" yaml:"endpointAddress,omitempty"`
// Defaults to true
IsSecure *bool `json:"isSecure,omitempty" yaml:"isSecure,omitempty"`
}
// GetIsSecure returns true if the connection should be secured.
func (o OtelSpec) GetIsSecure() bool {
// Defaults to true if nil
return o.IsSecure == nil || *o.IsSecure
}
// MetricSpec configuration for metrics.
type MetricSpec struct {
Enabled bool `json:"enabled" yaml:"enabled"`
Rules []MetricsRule `json:"rules" yaml:"rules"`
// Defaults to true
Enabled *bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`
Rules []MetricsRule `json:"rules,omitempty" yaml:"rules,omitempty"`
}
// GetEnabled returns true if metrics are enabled.
func (m MetricSpec) GetEnabled() bool {
// Defaults to true if nil
return m.Enabled == nil || *m.Enabled
}
// MetricsRule defines configuration options for a metric.
type MetricsRule struct {
Name string `json:"name" yaml:"name"`
Labels []MetricLabel `json:"labels" yaml:"labels"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Labels []MetricLabel `json:"labels,omitempty" yaml:"labels,omitempty"`
}
// MetricsLabel defines an object that allows to set regex expressions for a label.
type MetricLabel struct {
Name string `json:"name" yaml:"name"`
Regex map[string]string `json:"regex" yaml:"regex"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Regex map[string]string `json:"regex,omitempty" yaml:"regex,omitempty"`
}
// AppPolicySpec defines the policy data structure for each app.
type AppPolicySpec struct {
AppName string `json:"appId" yaml:"appId"`
DefaultAction string `json:"defaultAction" yaml:"defaultAction"`
TrustDomain string `json:"trustDomain" yaml:"trustDomain"`
Namespace string `json:"namespace" yaml:"namespace"`
AppOperationActions []AppOperation `json:"operations" yaml:"operations"`
AppName string `json:"appId,omitempty" yaml:"appId,omitempty"`
DefaultAction string `json:"defaultAction,omitempty" yaml:"defaultAction,omitempty"`
TrustDomain string `json:"trustDomain,omitempty" yaml:"trustDomain,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
AppOperationActions []AppOperation `json:"operations,omitempty" yaml:"operations,omitempty"`
}
// AppOperation defines the data structure for each app operation.
type AppOperation struct {
Operation string `json:"name" yaml:"name"`
HTTPVerb []string `json:"httpVerb" yaml:"httpVerb"`
Action string `json:"action" yaml:"action"`
Operation string `json:"name,omitempty" yaml:"name,omitempty"`
HTTPVerb []string `json:"httpVerb,omitempty" yaml:"httpVerb,omitempty"`
Action string `json:"action,omitempty" yaml:"action,omitempty"`
}
// AccessControlSpec is the spec object in ConfigurationSpec.
type AccessControlSpec struct {
DefaultAction string `json:"defaultAction" yaml:"defaultAction"`
TrustDomain string `json:"trustDomain" yaml:"trustDomain"`
AppPolicies []AppPolicySpec `json:"policies" yaml:"policies"`
DefaultAction string `json:"defaultAction,omitempty" yaml:"defaultAction,omitempty"`
TrustDomain string `json:"trustDomain,omitempty" yaml:"trustDomain,omitempty"`
AppPolicies []AppPolicySpec `json:"policies,omitempty" yaml:"policies,omitempty"`
}
type NameResolutionSpec struct {
Component string `json:"component" yaml:"component"`
Version string `json:"version" yaml:"version"`
Configuration interface{} `json:"configuration" yaml:"configuration"`
Component string `json:"component,omitempty" yaml:"component,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
Configuration any `json:"configuration,omitempty" yaml:"configuration,omitempty"`
}
type MTLSSpec struct {
Enabled bool `json:"enabled" yaml:"enabled"`
WorkloadCertTTL string `json:"workloadCertTTL" yaml:"workloadCertTTL"`
AllowedClockSkew string `json:"allowedClockSkew" yaml:"allowedClockSkew"`
Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`
WorkloadCertTTL string `json:"workloadCertTTL,omitempty" yaml:"workloadCertTTL,omitempty"`
AllowedClockSkew string `json:"allowedClockSkew,omitempty" yaml:"allowedClockSkew,omitempty"`
}
// SpiffeID represents the separated fields in a spiffe id.
@ -285,7 +300,7 @@ type ComponentsSpec struct {
// LoggingSpec defines the configuration for logging.
type LoggingSpec struct {
// Configure API logging.
APILogging APILoggingSpec `json:"apiLogging,omitempty" yaml:"apiLogging,omitempty"`
APILogging *APILoggingSpec `json:"apiLogging,omitempty" yaml:"apiLogging,omitempty"`
}
// APILoggingSpec defines the configuration for API logging.
@ -296,7 +311,7 @@ type APILoggingSpec struct {
// When enabled, obfuscates the values of URLs in HTTP API logs, logging the route name rather than the full path being invoked, which could contain PII.
// Default: false.
// This option has no effect if API logging is disabled.
ObfuscateURLs bool `json:"obfuscateURLs" yaml:"obfuscateURLs"`
ObfuscateURLs bool `json:"obfuscateURLs,omitempty" yaml:"obfuscateURLs,omitempty"`
// If true, health checks are not reported in API logs. Default: false.
// This option has no effect if API logging is disabled.
OmitHealthChecks bool `json:"omitHealthChecks,omitempty" yaml:"omitHealthChecks,omitempty"`
@ -306,19 +321,15 @@ type APILoggingSpec struct {
func LoadDefaultConfiguration() *Configuration {
return &Configuration{
Spec: ConfigurationSpec{
TracingSpec: TracingSpec{
SamplingRate: "",
Otel: OtelSpec{
IsSecure: true,
TracingSpec: &TracingSpec{
Otel: &OtelSpec{
IsSecure: ptr.Of(true),
},
},
MetricSpec: MetricSpec{
Enabled: true,
MetricSpec: &MetricSpec{
Enabled: ptr.Of(true),
},
MetricsSpec: MetricSpec{
Enabled: true,
},
AccessControlSpec: AccessControlSpec{
AccessControlSpec: &AccessControlSpec{
DefaultAction: AllowAccess,
TrustDomain: "public",
},
@ -327,36 +338,41 @@ func LoadDefaultConfiguration() *Configuration {
}
// LoadStandaloneConfiguration gets the path to a config file and loads it into a configuration.
func LoadStandaloneConfiguration(config string) (*Configuration, string, error) {
_, err := os.Stat(config)
if err != nil {
return nil, "", err
}
b, err := os.ReadFile(config)
if err != nil {
return nil, "", err
}
// Parse environment variables from yaml
b = []byte(os.ExpandEnv(string(b)))
func LoadStandaloneConfiguration(configs ...string) (*Configuration, error) {
conf := LoadDefaultConfiguration()
err = yaml.Unmarshal(b, conf)
if err != nil {
return nil, string(b), err
}
err = sortAndValidateSecretsConfiguration(conf)
if err != nil {
return nil, string(b), err
// Load all config files and apply them on top of the default config
for _, config := range configs {
_, err := os.Stat(config)
if err != nil {
return nil, err
}
b, err := os.ReadFile(config)
if err != nil {
return nil, err
}
// Parse environment variables from yaml
b = []byte(os.ExpandEnv(string(b)))
err = yaml.Unmarshal(b, conf)
if err != nil {
return nil, err
}
}
sortMetricsSpec(conf)
return conf, string(b), nil
err := conf.sortAndValidateSecretsConfiguration()
if err != nil {
return nil, err
}
conf.sortMetricsSpec()
return conf, nil
}
// LoadKubernetesConfiguration gets configuration from the Kubernetes operator with a given name.
func LoadKubernetesConfiguration(config, namespace string, podName string, operatorClient operatorv1pb.OperatorClient) (*Configuration, error) {
func LoadKubernetesConfiguration(config string, namespace string, podName string, operatorClient operatorv1pb.OperatorClient) (*Configuration, error) {
resp, err := operatorClient.GetConfiguration(context.Background(), &operatorv1pb.GetConfigurationRequest{
Name: config,
Namespace: namespace,
@ -365,21 +381,22 @@ func LoadKubernetesConfiguration(config, namespace string, podName string, opera
if err != nil {
return nil, err
}
if resp.GetConfiguration() == nil {
b := resp.GetConfiguration()
if len(b) == 0 {
return nil, fmt.Errorf("configuration %s not found", config)
}
conf := LoadDefaultConfiguration()
err = json.Unmarshal(resp.GetConfiguration(), conf)
err = json.Unmarshal(b, conf)
if err != nil {
return nil, err
}
err = sortAndValidateSecretsConfiguration(conf)
err = conf.sortAndValidateSecretsConfiguration()
if err != nil {
return nil, err
}
sortMetricsSpec(conf)
conf.sortMetricsSpec()
return conf, nil
}
@ -410,46 +427,11 @@ func SetTracingSpecFromEnv(conf *Configuration) {
}
if insecure := os.Getenv(env.OtlpExporterInsecure); insecure == "true" {
conf.Spec.TracingSpec.Otel.IsSecure = false
conf.Spec.TracingSpec.Otel.IsSecure = ptr.Of(false)
}
}
}
// Apply .metrics if set. If not, retain .metric.
func sortMetricsSpec(conf *Configuration) {
if !conf.Spec.MetricsSpec.Enabled {
conf.Spec.MetricSpec.Enabled = false
}
if len(conf.Spec.MetricsSpec.Rules) > 0 {
conf.Spec.MetricSpec.Rules = conf.Spec.MetricsSpec.Rules
}
}
// Validate the secrets configuration and sort to the allowed and denied lists if present.
func sortAndValidateSecretsConfiguration(conf *Configuration) error {
scopes := conf.Spec.Secrets.Scopes
set := sets.NewString()
for _, scope := range scopes {
// validate scope
if set.Has(scope.StoreName) {
return fmt.Errorf("%q storeName is repeated in secrets configuration", scope.StoreName)
}
if scope.DefaultAccess != "" &&
!strings.EqualFold(scope.DefaultAccess, AllowAccess) &&
!strings.EqualFold(scope.DefaultAccess, DenyAccess) {
return fmt.Errorf("defaultAccess %q can be either allow or deny", scope.DefaultAccess)
}
set.Insert(scope.StoreName)
// modify scope
sort.Strings(scope.AllowedSecrets)
sort.Strings(scope.DeniedSecrets)
}
return nil
}
// IsSecretAllowed Check if the secret is allowed to be accessed.
func (c SecretsScope) IsSecretAllowed(key string) bool {
// By default, set allow access for the secret store.
@ -515,3 +497,133 @@ func (c Configuration) EnabledFeatures() []string {
}
return features[:i]
}
// GetTracingSpec returns the tracing spec.
// It's a short-hand that includes nil-checks for safety.
func (c Configuration) GetTracingSpec() TracingSpec {
if c.Spec.TracingSpec == nil {
return TracingSpec{}
}
return *c.Spec.TracingSpec
}
// GetMTLSSpec returns the mTLS spec.
// It's a short-hand that includes nil-checks for safety.
func (c Configuration) GetMTLSSpec() MTLSSpec {
if c.Spec.MTLSSpec == nil {
return MTLSSpec{}
}
return *c.Spec.MTLSSpec
}
// GetMetricsSpec returns the metrics spec.
// It's a short-hand that includes nil-checks for safety.
func (c Configuration) GetMetricsSpec() MetricSpec {
if c.Spec.MetricSpec == nil {
return MetricSpec{}
}
return *c.Spec.MetricSpec
}
// GetAPISpec returns the API spec.
// It's a short-hand that includes nil-checks for safety.
func (c Configuration) GetAPISpec() APISpec {
if c.Spec.APISpec == nil {
return APISpec{}
}
return *c.Spec.APISpec
}
// GetLoggingSpec returns the Logging spec.
// It's a short-hand that includes nil-checks for safety.
func (c Configuration) GetLoggingSpec() LoggingSpec {
if c.Spec.LoggingSpec == nil {
return LoggingSpec{}
}
return *c.Spec.LoggingSpec
}
// GetLoggingSpec returns the Logging.APILogging spec.
// It's a short-hand that includes nil-checks for safety.
func (c Configuration) GetAPILoggingSpec() APILoggingSpec {
if c.Spec.LoggingSpec == nil || c.Spec.LoggingSpec.APILogging == nil {
return APILoggingSpec{}
}
return *c.Spec.LoggingSpec.APILogging
}
// ToYAML returns the Configuration represented as YAML.
func (c *Configuration) ToYAML() (string, error) {
b, err := yaml.Marshal(c)
if err != nil {
return "", err
}
return string(b), nil
}
// String implements fmt.Stringer and is used for debugging. It returns the Configuration object encoded as YAML.
func (c *Configuration) String() string {
enc, err := c.ToYAML()
if err != nil {
return "Failed to marshal Configuration object to YAML: " + err.Error()
}
return enc
}
// Apply .metrics if set. If not, retain .metric.
func (c *Configuration) sortMetricsSpec() {
if c.Spec.MetricsSpec != nil {
if c.Spec.MetricsSpec.Enabled != nil {
c.Spec.MetricSpec.Enabled = c.Spec.MetricsSpec.Enabled
}
if len(c.Spec.MetricsSpec.Rules) > 0 {
c.Spec.MetricSpec.Rules = c.Spec.MetricsSpec.Rules
}
}
}
// Validate the secrets configuration and sort to the allowed and denied lists if present.
func (c *Configuration) sortAndValidateSecretsConfiguration() error {
if c.Spec.Secrets == nil {
return nil
}
set := sets.NewString()
for _, scope := range c.Spec.Secrets.Scopes {
// validate scope
if set.Has(scope.StoreName) {
return fmt.Errorf("%s storeName is repeated in secrets configuration", scope.StoreName)
}
if scope.DefaultAccess != "" &&
!strings.EqualFold(scope.DefaultAccess, AllowAccess) &&
!strings.EqualFold(scope.DefaultAccess, DenyAccess) {
return fmt.Errorf("defaultAccess %s can be either allow or deny", scope.DefaultAccess)
}
set.Insert(scope.StoreName)
// modify scope
sort.Strings(scope.AllowedSecrets)
sort.Strings(scope.DeniedSecrets)
}
return nil
}
// ToYAML returns the ConfigurationSpec represented as YAML.
func (c ConfigurationSpec) ToYAML() (string, error) {
b, err := yaml.Marshal(&c)
if err != nil {
return "", err
}
return string(b), nil
}
// String implements fmt.Stringer and is used for debugging. It returns the Configuration object encoded as YAML.
func (c ConfigurationSpec) String() string {
enc, err := c.ToYAML()
if err != nil {
return fmt.Sprintf("Failed to marshal ConfigurationSpec object to YAML: %v", err)
}
return enc
}

View File

@ -14,12 +14,17 @@ limitations under the License.
package config
import (
"bytes"
"os"
"reflect"
"sort"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/dapr/dapr/pkg/buildinfo"
"github.com/dapr/kit/ptr"
)
func TestLoadStandaloneConfiguration(t *testing.T) {
@ -47,7 +52,7 @@ func TestLoadStandaloneConfiguration(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, _, err := LoadStandaloneConfiguration(tc.path)
config, err := LoadStandaloneConfiguration(tc.path)
if tc.errorExpected {
assert.Error(t, err, "Expected an error")
assert.Nil(t, config, "Config should not be loaded")
@ -58,72 +63,165 @@ func TestLoadStandaloneConfiguration(t *testing.T) {
})
}
t.Run("Parse environment variables", func(t *testing.T) {
t.Run("parse environment variables", func(t *testing.T) {
t.Setenv("DAPR_SECRET", "keepitsecret")
config, _, err := LoadStandaloneConfiguration("./testdata/env_variables_config.yaml")
config, err := LoadStandaloneConfiguration("./testdata/env_variables_config.yaml")
assert.NoError(t, err, "Unexpected error")
assert.NotNil(t, config, "Config not loaded as expected")
assert.Equal(t, "keepitsecret", config.Spec.Secrets.Scopes[0].AllowedSecrets[0])
})
}
func TestLoadStandaloneConfigurationKindName(t *testing.T) {
t.Run("test Kind and Name", func(t *testing.T) {
config, _, err := LoadStandaloneConfiguration("./testdata/config.yaml")
t.Run("check Kind and Name", func(t *testing.T) {
config, err := LoadStandaloneConfiguration("./testdata/config.yaml")
assert.NoError(t, err, "Unexpected error")
assert.NotNil(t, config, "Config not loaded as expected")
assert.Equal(t, "secretappconfig", config.ObjectMeta.Name)
assert.Equal(t, "Configuration", config.TypeMeta.Kind)
})
t.Run("metrics spec", func(t *testing.T) {
testCases := []struct {
name string
confFile string
metricEnabled bool
}{
{
name: "metric is enabled by default",
confFile: "./testdata/config.yaml",
metricEnabled: true,
},
{
name: "metric is disabled by config",
confFile: "./testdata/metric_disabled.yaml",
metricEnabled: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, err := LoadStandaloneConfiguration(tc.confFile)
assert.NoError(t, err)
assert.Equal(t, tc.metricEnabled, config.Spec.MetricSpec.GetEnabled())
})
}
})
t.Run("components spec", func(t *testing.T) {
testCases := []struct {
name string
confFile string
componentsDeny []string
}{
{
name: "component deny list",
confFile: "./testdata/components_config.yaml",
componentsDeny: []string{"foo.bar", "hello.world/v1"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, err := LoadStandaloneConfiguration(tc.confFile)
assert.NoError(t, err)
assert.True(t, reflect.DeepEqual(tc.componentsDeny, config.Spec.ComponentsSpec.Deny))
})
}
})
t.Run("features spec", func(t *testing.T) {
testCases := []struct {
name string
confFile string
featureName Feature
featureEnabled bool
}{
{
name: "feature is enabled",
confFile: "./testdata/feature_config.yaml",
featureName: Feature("Actor.Reentrancy"),
featureEnabled: true,
},
{
name: "feature is disabled",
confFile: "./testdata/feature_config.yaml",
featureName: Feature("Test.Feature"),
featureEnabled: false,
},
{
name: "feature is disabled if missing",
confFile: "./testdata/feature_config.yaml",
featureName: Feature("Test.Missing"),
featureEnabled: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, err := LoadStandaloneConfiguration(tc.confFile)
require.NoError(t, err)
config.LoadFeatures()
assert.Equal(t, tc.featureEnabled, config.IsFeatureEnabled(tc.featureName))
})
}
})
t.Run("mTLS spec", func(t *testing.T) {
config, err := LoadStandaloneConfiguration("./testdata/mtls_config.yaml")
require.NoError(t, err)
mtlsSpec := config.GetMTLSSpec()
assert.True(t, mtlsSpec.Enabled)
assert.Equal(t, "25s", mtlsSpec.WorkloadCertTTL)
assert.Equal(t, "1h", mtlsSpec.AllowedClockSkew)
})
t.Run("multiple configurations", func(t *testing.T) {
config, err := LoadStandaloneConfiguration("./testdata/feature_config.yaml", "./testdata/mtls_config.yaml")
require.NoError(t, err)
// From feature_config.yaml
config.LoadFeatures()
assert.True(t, config.IsFeatureEnabled("Actor.Reentrancy"))
assert.False(t, config.IsFeatureEnabled("Test.Feature"))
// From mtls_config.yaml
mtlsSpec := config.GetMTLSSpec()
assert.True(t, mtlsSpec.Enabled)
assert.Equal(t, "25s", mtlsSpec.WorkloadCertTTL)
assert.Equal(t, "1h", mtlsSpec.AllowedClockSkew)
})
t.Run("multiple configurations with overriding", func(t *testing.T) {
config, err := LoadStandaloneConfiguration("./testdata/feature_config.yaml", "./testdata/mtls_config.yaml", "./testdata/override.yaml")
require.NoError(t, err)
// From feature_config.yaml
// Should both be overridden
config.LoadFeatures()
assert.False(t, config.IsFeatureEnabled("Actor.Reentrancy"))
assert.True(t, config.IsFeatureEnabled("Test.Feature"))
// From mtls_config.yaml
mtlsSpec := config.GetMTLSSpec()
assert.False(t, mtlsSpec.Enabled) // Overridden
assert.Equal(t, "25s", mtlsSpec.WorkloadCertTTL)
assert.Equal(t, "1h", mtlsSpec.AllowedClockSkew)
// Spec part encoded as YAML
compareWithFile(t, "./testdata/override_spec_gen.yaml", config.Spec.String())
// Complete YAML
compareWithFile(t, "./testdata/override_gen.yaml", config.String())
})
}
func TestMetricSpecForStandAlone(t *testing.T) {
testCases := []struct {
name string
confFile string
metricEnabled bool
}{
{
name: "metric is enabled by default",
confFile: "./testdata/config.yaml",
metricEnabled: true,
},
{
name: "metric is disabled by config",
confFile: "./testdata/metric_disabled.yaml",
metricEnabled: false,
},
}
func compareWithFile(t *testing.T, file string, expect string) {
f, err := os.ReadFile(file)
require.NoError(t, err)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, _, err := LoadStandaloneConfiguration(tc.confFile)
assert.NoError(t, err)
assert.Equal(t, tc.metricEnabled, config.Spec.MetricSpec.Enabled)
})
}
}
// Replace all "\r\n" with "\n" because (*wave hands*, *lesigh*) ... Windows
f = bytes.ReplaceAll(f, []byte{'\r', '\n'}, []byte{'\n'})
func TestComponentsSpecForStandAlone(t *testing.T) {
testCases := []struct {
name string
confFile string
componentsDeny []string
}{
{
name: "component deny list",
confFile: "./testdata/components_config.yaml",
componentsDeny: []string{"foo.bar", "hello.world/v1"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, _, err := LoadStandaloneConfiguration(tc.confFile)
assert.NoError(t, err)
assert.True(t, reflect.DeepEqual(tc.componentsDeny, config.Spec.ComponentsSpec.Deny))
})
}
assert.Equal(t, expect, string(f))
}
func TestSortAndValidateSecretsConfigration(t *testing.T) {
@ -140,7 +238,7 @@ func TestSortAndValidateSecretsConfigration(t *testing.T) {
name: "incorrect default access",
config: Configuration{
Spec: ConfigurationSpec{
Secrets: SecretsSpec{
Secrets: &SecretsSpec{
Scopes: []SecretsScope{
{
StoreName: "testStore",
@ -156,7 +254,7 @@ func TestSortAndValidateSecretsConfigration(t *testing.T) {
name: "empty default access",
config: Configuration{
Spec: ConfigurationSpec{
Secrets: SecretsSpec{
Secrets: &SecretsSpec{
Scopes: []SecretsScope{
{
StoreName: "testStore",
@ -171,7 +269,7 @@ func TestSortAndValidateSecretsConfigration(t *testing.T) {
name: "repeated store Name",
config: Configuration{
Spec: ConfigurationSpec{
Secrets: SecretsSpec{
Secrets: &SecretsSpec{
Scopes: []SecretsScope{
{
StoreName: "testStore",
@ -191,7 +289,7 @@ func TestSortAndValidateSecretsConfigration(t *testing.T) {
name: "simple secrets config",
config: Configuration{
Spec: ConfigurationSpec{
Secrets: SecretsSpec{
Secrets: &SecretsSpec{
Scopes: []SecretsScope{
{
StoreName: "testStore",
@ -208,7 +306,7 @@ func TestSortAndValidateSecretsConfigration(t *testing.T) {
name: "case-insensitive default access",
config: Configuration{
Spec: ConfigurationSpec{
Secrets: SecretsSpec{
Secrets: &SecretsSpec{
Scopes: []SecretsScope{
{
StoreName: "testStore",
@ -224,10 +322,10 @@ func TestSortAndValidateSecretsConfigration(t *testing.T) {
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := sortAndValidateSecretsConfiguration(&tc.config)
err := tc.config.sortAndValidateSecretsConfiguration()
if tc.errorExpected {
assert.Error(t, err, "expected validation to fail")
} else {
} else if tc.config.Spec.Secrets != nil {
for _, scope := range tc.config.Spec.Secrets.Scopes {
assert.True(t, sort.StringsAreSorted(scope.AllowedSecrets), "expected sorted slice")
assert.True(t, sort.StringsAreSorted(scope.DeniedSecrets), "expected sorted slice")
@ -340,56 +438,18 @@ func TestFeatureEnabled(t *testing.T) {
},
}
config.LoadFeatures()
assert.True(t, config.IsFeatureEnabled("testEnabled"))
assert.False(t, config.IsFeatureEnabled("testDisabled"))
assert.False(t, config.IsFeatureEnabled("testMissing"))
}
func TestFeatureSpecForStandAlone(t *testing.T) {
testCases := []struct {
name string
confFile string
featureName Feature
featureEnabled bool
}{
{
name: "Feature is enabled",
confFile: "./testdata/feature_config.yaml",
featureName: Feature("Actor.Reentrancy"),
featureEnabled: true,
},
{
name: "Feature is disabled",
confFile: "./testdata/feature_config.yaml",
featureName: Feature("Test.Feature"),
featureEnabled: false,
},
{
name: "Feature is disabled if missing",
confFile: "./testdata/feature_config.yaml",
featureName: Feature("Test.Missing"),
featureEnabled: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config, _, err := LoadStandaloneConfiguration(tc.confFile)
require.NoError(t, err)
config.LoadFeatures()
assert.Equal(t, tc.featureEnabled, config.IsFeatureEnabled(tc.featureName))
})
}
}
func TestMTLSSpecForStandAlone(t *testing.T) {
t.Run("test mtls spec config", func(t *testing.T) {
config, _, err := LoadStandaloneConfiguration("./testdata/mtls_config.yaml")
require.NoError(t, err)
assert.True(t, config.Spec.MTLSSpec.Enabled)
assert.Equal(t, "25s", config.Spec.MTLSSpec.WorkloadCertTTL)
assert.Equal(t, "1h", config.Spec.MTLSSpec.AllowedClockSkew)
})
// Test config.EnabledFeatures
// We sort the values before comparing because order isn't guaranteed (and doesn't matter)
actual := config.EnabledFeatures()
expect := append([]string{"testEnabled"}, buildinfo.Features()...)
sort.Strings(actual)
sort.Strings(expect)
assert.EqualValues(t, actual, expect)
}
func TestSetTracingSpecFromEnv(t *testing.T) {
@ -405,42 +465,84 @@ func TestSetTracingSpecFromEnv(t *testing.T) {
assert.Equal(t, "otlpendpoint:1234", conf.Spec.TracingSpec.Otel.EndpointAddress)
assert.Equal(t, "http", conf.Spec.TracingSpec.Otel.Protocol)
assert.Equal(t, false, conf.Spec.TracingSpec.Otel.IsSecure)
require.False(t, conf.Spec.TracingSpec.Otel.GetIsSecure())
// Spec from config file should not be overridden
conf = LoadDefaultConfiguration()
conf.Spec.TracingSpec.Otel.EndpointAddress = "configfileendpoint:4321"
conf.Spec.TracingSpec.Otel.Protocol = "grpc"
conf.Spec.TracingSpec.Otel.IsSecure = true
conf.Spec.TracingSpec.Otel.IsSecure = ptr.Of(true)
// set tracing spec from env
SetTracingSpecFromEnv(conf)
assert.Equal(t, "configfileendpoint:4321", conf.Spec.TracingSpec.Otel.EndpointAddress)
assert.Equal(t, "grpc", conf.Spec.TracingSpec.Otel.Protocol)
assert.Equal(t, true, conf.Spec.TracingSpec.Otel.IsSecure)
require.True(t, conf.Spec.TracingSpec.Otel.GetIsSecure())
}
func TestSortMetrics(t *testing.T) {
t.Run("metrics overrides metric", func(t *testing.T) {
t.Run("metrics overrides metric - enabled false", func(t *testing.T) {
config := &Configuration{
Spec: ConfigurationSpec{
MetricSpec: MetricSpec{
Enabled: true,
MetricSpec: &MetricSpec{
Enabled: ptr.Of(true),
Rules: []MetricsRule{
{
Name: "rule",
},
},
},
MetricsSpec: MetricSpec{
Enabled: false,
MetricsSpec: &MetricSpec{
Enabled: ptr.Of(false),
},
},
}
sortMetricsSpec(config)
assert.False(t, config.Spec.MetricSpec.Enabled)
config.sortMetricsSpec()
assert.False(t, config.Spec.MetricSpec.GetEnabled())
assert.Equal(t, "rule", config.Spec.MetricSpec.Rules[0].Name)
})
t.Run("metrics overrides metric - enabled true", func(t *testing.T) {
config := &Configuration{
Spec: ConfigurationSpec{
MetricSpec: &MetricSpec{
Enabled: ptr.Of(false),
Rules: []MetricsRule{
{
Name: "rule",
},
},
},
MetricsSpec: &MetricSpec{
Enabled: ptr.Of(true),
},
},
}
config.sortMetricsSpec()
assert.True(t, config.Spec.MetricSpec.GetEnabled())
assert.Equal(t, "rule", config.Spec.MetricSpec.Rules[0].Name)
})
t.Run("nil metrics enabled doesn't overrides", func(t *testing.T) {
config := &Configuration{
Spec: ConfigurationSpec{
MetricSpec: &MetricSpec{
Enabled: ptr.Of(true),
Rules: []MetricsRule{
{
Name: "rule",
},
},
},
MetricsSpec: &MetricSpec{},
},
}
config.sortMetricsSpec()
assert.True(t, config.Spec.MetricSpec.GetEnabled())
assert.Equal(t, "rule", config.Spec.MetricSpec.Rules[0].Name)
})
}

View File

@ -5,6 +5,6 @@ metadata:
spec:
secrets:
scopes:
- storeName: "local"
defaultAccess: "allow"
allowedSecrets: ["daprsecret","redissecret"]
- storeName: "local"
defaultAccess: "allow"
allowedSecrets: ["daprsecret","redissecret"]

View File

@ -5,6 +5,6 @@ metadata:
spec:
secrets:
scopes:
- storeName: "local"
defaultAccess: "allow"
allowedSecrets: ["${DAPR_SECRET}"]
- storeName: "local"
defaultAccess: "allow"
allowedSecrets: ["${DAPR_SECRET}"]

View File

@ -4,7 +4,7 @@ metadata:
name: daprConfig
spec:
features:
- name: Actor.Reentrancy
enabled: true
- name: Test.Feature
enabled: false
- name: Actor.Reentrancy
enabled: true
- name: Test.Feature
enabled: false

View File

@ -5,7 +5,7 @@ metadata:
spec:
secrets:
scopes:
- storeName: "local"
defaultAccess: "allow"
- storeName: "local"
defaultAccess: "deny"
- storeName: "local"
defaultAccess: "allow"
- storeName: "local"
defaultAccess: "deny"

11
pkg/config/testdata/override.yaml vendored Normal file
View File

@ -0,0 +1,11 @@
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: daprsystem
namespace: default
spec:
mtls:
enabled: false
features:
- name: Test.Feature
enabled: true

33
pkg/config/testdata/override_gen.yaml vendored Normal file
View File

@ -0,0 +1,33 @@
kind: Configuration
apiversion: ""
metadata:
name: daprsystem
generatename: ""
namespace: default
selflink: ""
uid: ""
resourceversion: ""
generation: 0
creationtimestamp: "0001-01-01T00:00:00Z"
deletiontimestamp: null
deletiongraceperiodseconds: null
labels: {}
annotations: {}
ownerreferences: []
finalizers: []
managedfields: []
spec:
tracing:
otel:
isSecure: true
mtls:
workloadCertTTL: 25s
allowedClockSkew: 1h
metric:
enabled: true
accessControl:
defaultAction: allow
trustDomain: public
features:
- name: Test.Feature
enabled: true

View File

@ -0,0 +1,14 @@
tracing:
otel:
isSecure: true
mtls:
workloadCertTTL: 25s
allowedClockSkew: 1h
metric:
enabled: true
accessControl:
defaultAction: allow
trustDomain: public
features:
- name: Test.Feature
enabled: true

View File

@ -215,9 +215,8 @@ func ConstructSubscriptionSpanAttributes(topic string) map[string]string {
}
// StartInternalCallbackSpan starts trace span for internal callback such as input bindings and pubsub subscription.
func StartInternalCallbackSpan(ctx context.Context, spanName string, parent trace.SpanContext, spec config.TracingSpec) (context.Context, trace.Span) {
traceEnabled := diagUtils.IsTracingEnabled(spec.SamplingRate)
if !traceEnabled {
func StartInternalCallbackSpan(ctx context.Context, spanName string, parent trace.SpanContext, spec *config.TracingSpec) (context.Context, trace.Span) {
if spec == nil || !diagUtils.IsTracingEnabled(spec.SamplingRate) {
return ctx, nil
}

View File

@ -122,7 +122,7 @@ func TestStartInternalCallbackSpan(t *testing.T) {
otel.SetTracerProvider(tp)
t.Run("traceparent is provided and sampling is enabled", func(t *testing.T) {
traceSpec := config.TracingSpec{SamplingRate: "1"}
traceSpec := &config.TracingSpec{SamplingRate: "1"}
scConfig := trace.SpanContextConfig{
TraceID: trace.TraceID{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54},
@ -142,7 +142,7 @@ func TestStartInternalCallbackSpan(t *testing.T) {
})
t.Run("traceparent is provided with sampling flag = 1 but sampling is disabled", func(t *testing.T) {
traceSpec := config.TracingSpec{SamplingRate: "0"}
traceSpec := &config.TracingSpec{SamplingRate: "0"}
scConfig := trace.SpanContextConfig{
TraceID: trace.TraceID{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54},

View File

@ -238,7 +238,7 @@ func (s *server) getMiddlewareOptions() []grpcGo.ServerOption {
intrStream = append(intrStream, diag.GRPCTraceStreamServerInterceptor(s.config.AppID, s.tracingSpec))
}
if s.metricSpec.Enabled {
if s.metricSpec.GetEnabled() {
s.logger.Info("Enabled gRPC metrics middleware")
intr = append(intr, diag.DefaultGRPCMonitoring.UnaryServerInterceptor())

View File

@ -243,7 +243,7 @@ func (s *server) useTracing(r chi.Router) {
}
func (s *server) useMetrics(r chi.Router) {
if !s.metricSpec.Enabled {
if !s.metricSpec.GetEnabled() {
return
}

View File

@ -23,7 +23,7 @@ import (
"github.com/dapr/dapr/utils"
"github.com/dapr/kit/logger"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
const (

View File

@ -172,7 +172,7 @@ func mTLSEnabled(daprClient scheme.Interface) bool {
for _, c := range resp.Items {
if c.GetName() == defaultConfig {
return c.Spec.MTLSSpec.Enabled
return c.Spec.MTLSSpec.GetEnabled()
}
}
log.Infof("Dapr system configuration (%s) is not found, use default value %t for mTLSEnabled", defaultConfig, defaultMtlsEnabled)

View File

@ -138,7 +138,6 @@ func GetSidecarContainer(cfg ContainerConfig) (*corev1.Container, error) {
"--control-plane-address", cfg.ControlPlaneAddress,
"--app-protocol", cfg.Annotations.GetStringOrDefault(annotations.KeyAppProtocol, annotations.DefaultAppProtocol),
"--placement-host-address", cfg.PlacementServiceAddress,
"--config", cfg.Annotations.GetString(annotations.KeyConfig),
"--log-level", cfg.Annotations.GetStringOrDefault(annotations.KeyLogLevel, annotations.DefaultLogLevel),
"--app-max-concurrency", strconv.Itoa(int(maxConcurrency)),
"--sentry-address", cfg.SentryAddress,
@ -150,6 +149,10 @@ func GetSidecarContainer(cfg ContainerConfig) (*corev1.Container, error) {
"--disable-builtin-k8s-secret-store=" + strconv.FormatBool(disableBuiltinK8sSecretStore),
}
if v := cfg.Annotations.GetString(annotations.KeyConfig); v != "" {
args = append(args, "--config", v)
}
if v, ok := cfg.Annotations[annotations.KeyAppChannel]; ok && v != "" {
args = append(args, "--app-channel-address", v)
}

View File

@ -18,6 +18,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@ -34,14 +35,14 @@ const (
func TestGetResourceRequirements(t *testing.T) {
t.Run("no resource requirements", func(t *testing.T) {
r, err := getResourceRequirements(nil)
assert.Nil(t, err)
require.NoError(t, err)
assert.Nil(t, r)
})
t.Run("valid resource limits", func(t *testing.T) {
a := map[string]string{annotations.KeyCPULimit: "100m", annotations.KeyMemoryLimit: "1Gi"}
r, err := getResourceRequirements(a)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, "100m", r.Limits.Cpu().String())
assert.Equal(t, "1Gi", r.Limits.Memory().String())
})
@ -63,7 +64,7 @@ func TestGetResourceRequirements(t *testing.T) {
t.Run("valid resource requests", func(t *testing.T) {
a := map[string]string{annotations.KeyCPURequest: "100m", annotations.KeyMemoryRequest: "1Gi"}
r, err := getResourceRequirements(a)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, "100m", r.Requests.Cpu().String())
assert.Equal(t, "1Gi", r.Requests.Memory().String())
})
@ -163,7 +164,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -173,6 +173,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--log-as-json",
"--enable-mtls",
}
@ -237,7 +238,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -247,6 +247,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--log-as-json",
"--enable-mtls",
}
@ -311,7 +312,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -321,6 +321,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--log-as-json",
"--enable-mtls",
}
@ -383,7 +384,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -393,6 +393,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--log-as-json",
"--enable-mtls",
}
@ -456,7 +457,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "some-host:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -466,6 +466,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--log-as-json",
"--enable-mtls",
}
@ -511,7 +512,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -521,6 +521,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--enable-mtls",
}
@ -554,7 +555,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -564,6 +564,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--enable-mtls",
}
@ -597,7 +598,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -607,6 +607,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "5",
"--disable-builtin-k8s-secret-store=false",
"--config", defaultTestConfig,
"--enable-mtls",
}
@ -684,7 +685,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -694,6 +694,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=true",
"--config", defaultTestConfig,
"--enable-mtls",
}
@ -730,7 +731,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -740,6 +740,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=true",
"--config", defaultTestConfig,
"--enable-mtls",
}
@ -764,7 +765,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -774,6 +774,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=true",
"--config", defaultTestConfig,
"--enable-api-logging=true",
"--enable-mtls",
}
@ -799,7 +800,6 @@ func TestGetSidecarContainer(t *testing.T) {
"--control-plane-address", "controlplane:9000",
"--app-protocol", "http",
"--placement-host-address", "placement:50000",
"--config", defaultTestConfig,
"--log-level", "info",
"--app-max-concurrency", "-1",
"--sentry-address", "sentry:50000",
@ -809,6 +809,7 @@ func TestGetSidecarContainer(t *testing.T) {
"--dapr-http-read-buffer-size", "-1",
"--dapr-graceful-shutdown-seconds", "-1",
"--disable-builtin-k8s-secret-store=true",
"--config", defaultTestConfig,
"--enable-api-logging=false",
"--enable-mtls",
}

View File

@ -33,6 +33,6 @@ func LoadConfiguration(name string, client client.Client) (*Config, error) {
return nil, err
}
return &Config{
MTLSEnabled: conf.Spec.MTLSSpec.Enabled,
MTLSEnabled: conf.Spec.MTLSSpec.GetEnabled(),
}, nil
}

View File

@ -38,6 +38,7 @@ import (
"github.com/dapr/dapr/pkg/runtime/security"
"github.com/dapr/dapr/pkg/validation"
"github.com/dapr/dapr/utils"
"github.com/dapr/kit/ptr"
)
const (
@ -95,7 +96,7 @@ type Config struct {
AppHealthThreshold int
EnableAppHealthCheck bool
Mode string
ConfigPath string
Config []string
UnixDomainSocket string
DaprHTTPReadBufferSize int
DisableBuiltinK8sSecretStore bool
@ -127,7 +128,7 @@ type internalConfig struct {
gracefulShutdownDuration time.Duration
enableAPILogging *bool
disableBuiltinK8sSecretStore bool
configPath string
config []string
certChain *credentials.CertChain
}
@ -166,9 +167,6 @@ func FromConfig(cfg *Config) (*DaprRuntime, error) {
return nil, err
}
var globalConfig *config.Configuration
var configErr error
if intc.mTLSEnabled || intc.mode == modes.KubernetesMode {
intc.certChain, err = security.GetCertChain()
if err != nil {
@ -188,18 +186,26 @@ func FromConfig(cfg *Config) (*DaprRuntime, error) {
operatorClient = client
}
var accessControlList *config.AccessControlList
namespace := os.Getenv("NAMESPACE")
podName := os.Getenv("POD_NAME")
if intc.configPath != "" {
var (
globalConfig *config.Configuration
configErr error
)
if len(intc.config) > 0 {
switch intc.mode {
case modes.KubernetesMode:
log.Debug("Loading Kubernetes config resource: " + intc.configPath)
globalConfig, configErr = config.LoadKubernetesConfiguration(intc.configPath, namespace, podName, operatorClient)
if len(intc.config) > 1 {
// We are not returning an error here because in Kubernetes mode, the injector itself doesn't allow multiple configuration flags to be added, so this should never happen in normal environments
log.Warnf("Multiple configurations are not supported in Kubernetes mode; only the first one will be loaded")
}
log.Debug("Loading Kubernetes config resource: " + intc.config[0])
globalConfig, configErr = config.LoadKubernetesConfiguration(intc.config[0], namespace, podName, operatorClient)
case modes.StandaloneMode:
log.Debug("Loading config from file: " + intc.configPath)
globalConfig, _, configErr = config.LoadStandaloneConfiguration(intc.configPath)
log.Debug("Loading config from file(s): " + strings.Join(intc.config, ", "))
globalConfig, configErr = config.LoadStandaloneConfiguration(intc.config...)
}
}
@ -218,8 +224,9 @@ func FromConfig(cfg *Config) (*DaprRuntime, error) {
}
// Initialize metrics only if MetricSpec is enabled.
if globalConfig.Spec.MetricSpec.Enabled {
if mErr := diag.InitMetrics(intc.id, namespace, globalConfig.Spec.MetricSpec.Rules); mErr != nil {
metricsSpec := globalConfig.GetMetricsSpec()
if metricsSpec.GetEnabled() {
if mErr := diag.InitMetrics(intc.id, namespace, metricsSpec.Rules); mErr != nil {
log.Errorf(rterrors.NewInit(rterrors.InitFailure, "metrics", mErr).Error())
}
}
@ -241,7 +248,7 @@ func FromConfig(cfg *Config) (*DaprRuntime, error) {
}
}
accessControlList, err = acl.ParseAccessControlSpec(
accessControlList, err := acl.ParseAccessControlSpec(
globalConfig.Spec.AccessControlSpec,
intc.appConnectionConfig.Protocol.IsHTTP(),
)
@ -251,7 +258,7 @@ func FromConfig(cfg *Config) (*DaprRuntime, error) {
// API logging can be enabled for this app or for every app, globally in the config
if intc.enableAPILogging == nil {
intc.enableAPILogging = &globalConfig.Spec.LoggingSpec.APILogging.Enabled
intc.enableAPILogging = ptr.Of(globalConfig.GetAPILoggingSpec().Enabled)
}
return newDaprRuntime(intc, globalConfig, accessControlList, resiliencyProvider), nil
@ -261,7 +268,7 @@ func (c *Config) toInternal() (*internalConfig, error) {
intc := &internalConfig{
id: c.AppID,
mode: modes.DaprMode(c.Mode),
configPath: c.ConfigPath,
config: c.Config,
sentryServiceAddress: c.SentryAddress,
allowedOrigins: c.AllowedOrigins,
kubernetes: configmodes.KubernetesConfig{

View File

@ -281,7 +281,7 @@ func newDaprRuntime(runtimeConfig *internalConfig, globalConfig *config.Configur
}
rt.componentAuthorizers = []ComponentAuthorizer{rt.namespaceComponentAuthorizer}
if globalConfig != nil && len(globalConfig.Spec.ComponentsSpec.Deny) > 0 {
if globalConfig != nil && globalConfig.Spec.ComponentsSpec != nil && len(globalConfig.Spec.ComponentsSpec.Deny) > 0 {
dl := newComponentDenyList(globalConfig.Spec.ComponentsSpec.Deny)
rt.componentAuthorizers = append(rt.componentAuthorizers, dl.IsAllowed)
}
@ -345,7 +345,7 @@ func (a *DaprRuntime) getOperatorClient() (operatorv1pb.OperatorClient, error) {
// setupTracing set up the trace exporters. Technically we don't need to pass `hostAddress` in,
// but we do so here to explicitly call out the dependency on having `hostAddress` computed.
func (a *DaprRuntime) setupTracing(hostAddress string, tpStore tracerProviderStore) error {
tracingSpec := a.globalConfig.Spec.TracingSpec
tracingSpec := a.globalConfig.GetTracingSpec()
// Register stdout trace exporter if user wants to debug requests or log as Info level.
if tracingSpec.Stdout {
@ -353,7 +353,7 @@ func (a *DaprRuntime) setupTracing(hostAddress string, tpStore tracerProviderSto
}
// Register zipkin trace exporter if ZipkinSpec is specified
if tracingSpec.Zipkin.EndpointAddress != "" {
if tracingSpec.Zipkin != nil && tracingSpec.Zipkin.EndpointAddress != "" {
zipkinExporter, err := zipkin.New(tracingSpec.Zipkin.EndpointAddress)
if err != nil {
return err
@ -362,24 +362,23 @@ func (a *DaprRuntime) setupTracing(hostAddress string, tpStore tracerProviderSto
}
// Register otel trace exporter if OtelSpec is specified
if tracingSpec.Otel.EndpointAddress != "" && tracingSpec.Otel.Protocol != "" {
if tracingSpec.Otel != nil && tracingSpec.Otel.EndpointAddress != "" && tracingSpec.Otel.Protocol != "" {
endpoint := tracingSpec.Otel.EndpointAddress
protocol := tracingSpec.Otel.Protocol
if protocol != "http" && protocol != "grpc" {
return fmt.Errorf("invalid protocol %v provided for Otel endpoint", protocol)
}
isSecure := tracingSpec.Otel.IsSecure
var client otlptrace.Client
if protocol == "http" {
clientOptions := []otlptracehttp.Option{otlptracehttp.WithEndpoint(endpoint)}
if !isSecure {
if !tracingSpec.Otel.GetIsSecure() {
clientOptions = append(clientOptions, otlptracehttp.WithInsecure())
}
client = otlptracehttp.NewClient(clientOptions...)
} else {
clientOptions := []otlptracegrpc.Option{otlptracegrpc.WithEndpoint(endpoint)}
if !isSecure {
if !tracingSpec.Otel.GetIsSecure() {
clientOptions = append(clientOptions, otlptracegrpc.WithInsecure())
}
client = otlptracegrpc.NewClient(clientOptions...)
@ -666,50 +665,59 @@ func (a *DaprRuntime) appHealthChanged(status uint8) {
func (a *DaprRuntime) populateSecretsConfiguration() {
// Populate in a map for easy lookup by store name.
if a.globalConfig.Spec.Secrets == nil {
return
}
for _, scope := range a.globalConfig.Spec.Secrets.Scopes {
a.compStore.AddSecretsConfiguration(scope.StoreName, scope)
}
}
func (a *DaprRuntime) buildHTTPPipelineForSpec(spec config.PipelineSpec, targetPipeline string) (pipeline httpMiddleware.Pipeline, err error) {
if a.globalConfig != nil {
pipeline.Handlers = make([]func(next nethttp.Handler) nethttp.Handler, 0, len(spec.Handlers))
for i := 0; i < len(spec.Handlers); i++ {
middlewareSpec := spec.Handlers[i]
component, exists := a.compStore.GetComponent(middlewareSpec.Type, middlewareSpec.Name)
if !exists {
// Log the error but continue with initializing the pipeline
log.Error("couldn't find middleware component defined in configuration with name %s and type %s/%s",
middlewareSpec.Name, middlewareSpec.Type, middlewareSpec.Version)
continue
}
md := middleware.Metadata{Base: a.toBaseMetadata(component)}
handler, err := a.httpMiddlewareRegistry.Create(middlewareSpec.Type, middlewareSpec.Version, md, middlewareSpec.LogName())
if err != nil {
e := fmt.Sprintf("process component %s error: %s", component.Name, err.Error())
if !component.Spec.IgnoreErrors {
log.Warn("error processing middleware component, daprd process will exit gracefully")
a.Shutdown(a.runtimeConfig.gracefulShutdownDuration)
log.Fatal(e)
// This error is only caught by tests, since during normal execution we panic
return pipeline, errors.New("dapr panicked")
}
log.Error(e)
continue
}
log.Infof("enabled %s/%s %s middleware", middlewareSpec.Type, targetPipeline, middlewareSpec.Version)
pipeline.Handlers = append(pipeline.Handlers, handler)
pipeline.Handlers = make([]func(next nethttp.Handler) nethttp.Handler, 0, len(spec.Handlers))
for i := 0; i < len(spec.Handlers); i++ {
middlewareSpec := spec.Handlers[i]
component, exists := a.compStore.GetComponent(middlewareSpec.Type, middlewareSpec.Name)
if !exists {
// Log the error but continue with initializing the pipeline
log.Error("couldn't find middleware component defined in configuration with name %s and type %s/%s",
middlewareSpec.Name, middlewareSpec.Type, middlewareSpec.Version)
continue
}
md := middleware.Metadata{Base: a.toBaseMetadata(component)}
handler, err := a.httpMiddlewareRegistry.Create(middlewareSpec.Type, middlewareSpec.Version, md, middlewareSpec.LogName())
if err != nil {
e := fmt.Sprintf("process component %s error: %s", component.Name, err.Error())
if !component.Spec.IgnoreErrors {
log.Warn("error processing middleware component, daprd process will exit gracefully")
a.Shutdown(a.runtimeConfig.gracefulShutdownDuration)
log.Fatal(e)
// This error is only caught by tests, since during normal execution we panic
return pipeline, errors.New("dapr panicked")
}
log.Error(e)
continue
}
log.Infof("enabled %s/%s %s middleware", middlewareSpec.Type, targetPipeline, middlewareSpec.Version)
pipeline.Handlers = append(pipeline.Handlers, handler)
}
return pipeline, nil
}
func (a *DaprRuntime) buildHTTPPipeline() (httpMiddleware.Pipeline, error) {
return a.buildHTTPPipelineForSpec(a.globalConfig.Spec.HTTPPipelineSpec, "http")
if a.globalConfig == nil || a.globalConfig.Spec.HTTPPipelineSpec == nil {
return httpMiddleware.Pipeline{}, nil
}
return a.buildHTTPPipelineForSpec(*a.globalConfig.Spec.HTTPPipelineSpec, "http")
}
func (a *DaprRuntime) buildAppHTTPPipeline() (httpMiddleware.Pipeline, error) {
return a.buildHTTPPipelineForSpec(a.globalConfig.Spec.AppHTTPPipelineSpec, "app channel")
if a.globalConfig == nil || a.globalConfig.Spec.AppHTTPPipelineSpec == nil {
return httpMiddleware.Pipeline{}, nil
}
return a.buildHTTPPipelineForSpec(*a.globalConfig.Spec.AppHTTPPipelineSpec, "app channel")
}
func (a *DaprRuntime) initBinding(c componentsV1alpha1.Component) error {
@ -1537,7 +1545,7 @@ func (a *DaprRuntime) startHTTPServer(port int, publicPort *int, profilePort int
PubsubAdapter: a.getPublishAdapter(),
Actors: a.actor,
SendToOutputBindingFn: a.sendToOutputBinding,
TracingSpec: a.globalConfig.Spec.TracingSpec,
TracingSpec: a.globalConfig.GetTracingSpec(),
Shutdown: a.ShutdownWithWait,
GetComponentsCapabilitiesFn: a.getComponentsCapabilitesMap,
MaxRequestBodySize: int64(a.runtimeConfig.maxRequestBodySize) << 20, // Convert from MB to bytes
@ -1559,17 +1567,17 @@ func (a *DaprRuntime) startHTTPServer(port int, publicPort *int, profilePort int
UnixDomainSocket: a.runtimeConfig.unixDomainSocket,
ReadBufferSizeKB: a.runtimeConfig.readBufferSize,
EnableAPILogging: *a.runtimeConfig.enableAPILogging,
APILoggingObfuscateURLs: a.globalConfig.Spec.LoggingSpec.APILogging.ObfuscateURLs,
APILogHealthChecks: !a.globalConfig.Spec.LoggingSpec.APILogging.OmitHealthChecks,
APILoggingObfuscateURLs: a.globalConfig.GetAPILoggingSpec().ObfuscateURLs,
APILogHealthChecks: !a.globalConfig.GetAPILoggingSpec().OmitHealthChecks,
}
server := http.NewServer(http.NewServerOpts{
API: a.daprHTTPAPI,
Config: serverConf,
TracingSpec: a.globalConfig.Spec.TracingSpec,
MetricSpec: a.globalConfig.Spec.MetricSpec,
TracingSpec: a.globalConfig.GetTracingSpec(),
MetricSpec: a.globalConfig.GetMetricsSpec(),
Pipeline: pipeline,
APISpec: a.globalConfig.Spec.APISpec,
APISpec: a.globalConfig.GetAPISpec(),
})
if err := server.StartNonBlocking(); err != nil {
return err
@ -1582,7 +1590,7 @@ func (a *DaprRuntime) startHTTPServer(port int, publicPort *int, profilePort int
func (a *DaprRuntime) startGRPCInternalServer(api grpc.API, port int) error {
// Since GRPCInteralServer is encrypted & authenticated, it is safe to listen on *
serverConf := a.getNewServerConfig([]string{""}, port)
server := grpc.NewInternalServer(api, serverConf, a.globalConfig.Spec.TracingSpec, a.globalConfig.Spec.MetricSpec, a.authenticator, a.proxy)
server := grpc.NewInternalServer(api, serverConf, a.globalConfig.GetTracingSpec(), a.globalConfig.GetMetricsSpec(), a.authenticator, a.proxy)
if err := server.StartNonBlocking(); err != nil {
return err
}
@ -1593,7 +1601,7 @@ func (a *DaprRuntime) startGRPCInternalServer(api grpc.API, port int) error {
func (a *DaprRuntime) startGRPCAPIServer(api grpc.API, port int) error {
serverConf := a.getNewServerConfig(a.runtimeConfig.apiListenAddresses, port)
server := grpc.NewAPIServer(api, serverConf, a.globalConfig.Spec.TracingSpec, a.globalConfig.Spec.MetricSpec, a.globalConfig.Spec.APISpec, a.proxy, a.workflowEngine)
server := grpc.NewAPIServer(api, serverConf, a.globalConfig.GetTracingSpec(), a.globalConfig.GetMetricsSpec(), a.globalConfig.GetAPISpec(), a.proxy, a.workflowEngine)
if err := server.StartNonBlocking(); err != nil {
return err
}
@ -1632,7 +1640,7 @@ func (a *DaprRuntime) getGRPCAPI() grpc.API {
DirectMessaging: a.directMessaging,
Actors: a.actor,
SendToOutputBindingFn: a.sendToOutputBinding,
TracingSpec: a.globalConfig.Spec.TracingSpec,
TracingSpec: a.globalConfig.GetTracingSpec(),
AccessControlList: a.accessControlList,
Shutdown: a.ShutdownWithWait,
GetComponentsCapabilitiesFn: a.getComponentsCapabilitesMap,
@ -2240,8 +2248,11 @@ func (a *DaprRuntime) initNameResolution() error {
var err error
resolverMetadata := nr.Metadata{}
resolverName := a.globalConfig.Spec.NameResolutionSpec.Component
resolverVersion := a.globalConfig.Spec.NameResolutionSpec.Version
var resolverName, resolverVersion string
if a.globalConfig.Spec.NameResolutionSpec != nil {
resolverName = a.globalConfig.Spec.NameResolutionSpec.Component
resolverVersion = a.globalConfig.Spec.NameResolutionSpec.Version
}
if resolverName == "" {
switch a.runtimeConfig.mode {
@ -2262,7 +2273,9 @@ func (a *DaprRuntime) initNameResolution() error {
fName := utils.ComponentLogName(resolverName, "nameResolution", resolverVersion)
resolver, err = a.nameResolutionRegistry.Create(resolverName, resolverVersion, fName)
resolverMetadata.Name = resolverName
resolverMetadata.Configuration = a.globalConfig.Spec.NameResolutionSpec.Configuration
if a.globalConfig.Spec.NameResolutionSpec != nil {
resolverMetadata.Configuration = a.globalConfig.Spec.NameResolutionSpec.Configuration
}
resolverMetadata.Properties = map[string]string{
nr.DaprHTTPPort: strconv.Itoa(a.runtimeConfig.httpPort),
nr.DaprPort: strconv.Itoa(a.runtimeConfig.internalGRPCPort),
@ -2578,7 +2591,7 @@ func (a *DaprRuntime) initActors() error {
GRPCConnectionFn: a.grpc.GetGRPCConnection,
Config: actorConfig,
CertChain: a.runtimeConfig.certChain,
TracingSpec: a.globalConfig.Spec.TracingSpec,
TracingSpec: a.globalConfig.GetTracingSpec(),
Resiliency: a.resiliency,
StateStoreName: a.actorStateStoreName,
CompStore: a.compStore,
@ -3271,7 +3284,7 @@ func (a *DaprRuntime) getAppHTTPChannelConfig(pipeline httpMiddleware.Pipeline,
CompStore: a.compStore,
MaxConcurrency: a.runtimeConfig.appConnectionConfig.MaxConcurrency,
Pipeline: pipeline,
TracingSpec: a.globalConfig.Spec.TracingSpec,
TracingSpec: a.globalConfig.GetTracingSpec(),
MaxRequestBodySizeMB: a.runtimeConfig.maxRequestBodySize,
}
@ -3534,7 +3547,7 @@ func pubsubTopicKey(componentName, topicName string) string {
func createGRPCManager(runtimeConfig *internalConfig, globalConfig *config.Configuration) *grpc.Manager {
grpcAppChannelConfig := &grpc.AppChannelConfig{}
if globalConfig != nil {
grpcAppChannelConfig.TracingSpec = globalConfig.Spec.TracingSpec
grpcAppChannelConfig.TracingSpec = globalConfig.GetTracingSpec()
grpcAppChannelConfig.AllowInsecureTLS = globalConfig.IsFeatureEnabled(config.AppChannelAllowInsecureTLS)
}
if runtimeConfig != nil {

View File

@ -931,7 +931,9 @@ func TestInitNameResolution(t *testing.T) {
rt := NewTestDaprRuntime(modes.StandaloneMode)
// target resolver
rt.globalConfig.Spec.NameResolutionSpec.Component = "targetResolver"
rt.globalConfig.Spec.NameResolutionSpec = &config.NameResolutionSpec{
Component: "targetResolver",
}
// registered resolver
initMockResolverForRuntime(rt, "anotherResolver", nil)
@ -948,7 +950,9 @@ func TestInitNameResolution(t *testing.T) {
rt := NewTestDaprRuntime(modes.StandaloneMode)
// target resolver
rt.globalConfig.Spec.NameResolutionSpec.Component = "someResolver"
rt.globalConfig.Spec.NameResolutionSpec = &config.NameResolutionSpec{
Component: "someResolver",
}
// registered resolver
initMockResolverForRuntime(rt, "someResolver", nil)
@ -965,7 +969,24 @@ func TestInitNameResolution(t *testing.T) {
rt := NewTestDaprRuntime(modes.StandaloneMode)
// target resolver
rt.globalConfig.Spec.NameResolutionSpec.Component = ""
rt.globalConfig.Spec.NameResolutionSpec = &config.NameResolutionSpec{}
// registered resolver
initMockResolverForRuntime(rt, "mdns", nil)
// act
err := rt.initNameResolution()
// assert
assert.NoError(t, err, "expected no error")
})
t.Run("test init nameresolution nil in StandaloneMode", func(t *testing.T) {
// given
rt := NewTestDaprRuntime(modes.StandaloneMode)
// target resolver
rt.globalConfig.Spec.NameResolutionSpec = nil
// registered resolver
initMockResolverForRuntime(rt, "mdns", nil)
@ -982,7 +1003,24 @@ func TestInitNameResolution(t *testing.T) {
rt := NewTestDaprRuntime(modes.KubernetesMode)
// target resolver
rt.globalConfig.Spec.NameResolutionSpec.Component = ""
rt.globalConfig.Spec.NameResolutionSpec = &config.NameResolutionSpec{}
// registered resolver
initMockResolverForRuntime(rt, "kubernetes", nil)
// act
err := rt.initNameResolution()
// assert
assert.NoError(t, err, "expected no error")
})
t.Run("test init nameresolution nil in KubernetesMode", func(t *testing.T) {
// given
rt := NewTestDaprRuntime(modes.KubernetesMode)
// target resolver
rt.globalConfig.Spec.NameResolutionSpec = nil
// registered resolver
initMockResolverForRuntime(rt, "kubernetes", nil)
@ -1014,7 +1052,7 @@ func TestSetupTracing(t *testing.T) {
}, {
name: "bad host address, failing zipkin",
tracingConfig: config.TracingSpec{
Zipkin: config.ZipkinSpec{
Zipkin: &config.ZipkinSpec{
EndpointAddress: "localhost",
},
},
@ -1022,7 +1060,7 @@ func TestSetupTracing(t *testing.T) {
}, {
name: "zipkin trace exporter",
tracingConfig: config.TracingSpec{
Zipkin: config.ZipkinSpec{
Zipkin: &config.ZipkinSpec{
EndpointAddress: "http://foo.bar",
},
},
@ -1030,9 +1068,9 @@ func TestSetupTracing(t *testing.T) {
}, {
name: "otel trace http exporter",
tracingConfig: config.TracingSpec{
Otel: config.OtelSpec{
Otel: &config.OtelSpec{
EndpointAddress: "foo.bar",
IsSecure: false,
IsSecure: ptr.Of(false),
Protocol: "http",
},
},
@ -1040,9 +1078,9 @@ func TestSetupTracing(t *testing.T) {
}, {
name: "invalid otel trace exporter protocol",
tracingConfig: config.TracingSpec{
Otel: config.OtelSpec{
Otel: &config.OtelSpec{
EndpointAddress: "foo.bar",
IsSecure: false,
IsSecure: ptr.Of(false),
Protocol: "tcp",
},
},
@ -1056,12 +1094,12 @@ func TestSetupTracing(t *testing.T) {
}, {
name: "all trace exporters",
tracingConfig: config.TracingSpec{
Otel: config.OtelSpec{
Otel: &config.OtelSpec{
EndpointAddress: "http://foo.bar",
IsSecure: false,
IsSecure: ptr.Of(false),
Protocol: "http",
},
Zipkin: config.ZipkinSpec{
Zipkin: &config.ZipkinSpec{
EndpointAddress: "http://foo.bar",
},
Stdout: true,
@ -1073,7 +1111,7 @@ func TestSetupTracing(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
rt := NewTestDaprRuntime(modes.StandaloneMode)
defer stopRuntime(t, rt)
rt.globalConfig.Spec.TracingSpec = tc.tracingConfig
rt.globalConfig.Spec.TracingSpec = &tc.tracingConfig
if tc.hostAddress != "" {
rt.hostAddress = tc.hostAddress
}
@ -2458,10 +2496,12 @@ func TestPopulateSecretsConfiguration(t *testing.T) {
// setup
rt := NewTestDaprRuntime(modes.StandaloneMode)
defer stopRuntime(t, rt)
rt.globalConfig.Spec.Secrets.Scopes = []config.SecretsScope{
{
StoreName: "testMock",
DefaultAccess: "allow",
rt.globalConfig.Spec.Secrets = &config.SecretsSpec{
Scopes: []config.SecretsScope{
{
StoreName: "testMock",
DefaultAccess: "allow",
},
},
}
@ -6069,10 +6109,10 @@ func initMockStateStoreForRuntime(rt *DaprRuntime, encryptKey string, e error) *
func TestTraceShutdown(t *testing.T) {
rt := NewTestDaprRuntime(modes.StandaloneMode)
rt.runtimeConfig.gracefulShutdownDuration = 5 * time.Second
rt.globalConfig.Spec.TracingSpec = config.TracingSpec{
Otel: config.OtelSpec{
rt.globalConfig.Spec.TracingSpec = &config.TracingSpec{
Otel: &config.OtelSpec{
EndpointAddress: "foo.bar",
IsSecure: false,
IsSecure: ptr.Of(false),
Protocol: "http",
},
}

View File

@ -137,7 +137,7 @@ func getKubernetesConfig(configName string) (SentryConfig, error) {
func getSelfhostedConfig(configName string) (SentryConfig, error) {
defaultConfig := getDefaultConfig()
daprConfig, _, err := daprGlobalConfig.LoadStandaloneConfiguration(configName)
daprConfig, err := daprGlobalConfig.LoadStandaloneConfiguration(configName)
if err != nil {
return defaultConfig, err
}
@ -149,8 +149,9 @@ func getSelfhostedConfig(configName string) (SentryConfig, error) {
}
func parseConfiguration(conf SentryConfig, daprConfig *daprGlobalConfig.Configuration) (SentryConfig, error) {
if daprConfig.Spec.MTLSSpec.WorkloadCertTTL != "" {
d, err := time.ParseDuration(daprConfig.Spec.MTLSSpec.WorkloadCertTTL)
mtlsSpec := daprConfig.GetMTLSSpec()
if mtlsSpec.WorkloadCertTTL != "" {
d, err := time.ParseDuration(mtlsSpec.WorkloadCertTTL)
if err != nil {
return conf, fmt.Errorf("error parsing WorkloadCertTTL duration: %w", err)
}
@ -158,8 +159,8 @@ func parseConfiguration(conf SentryConfig, daprConfig *daprGlobalConfig.Configur
conf.WorkloadCertTTL = d
}
if daprConfig.Spec.MTLSSpec.AllowedClockSkew != "" {
d, err := time.ParseDuration(daprConfig.Spec.MTLSSpec.AllowedClockSkew)
if mtlsSpec.AllowedClockSkew != "" {
d, err := time.ParseDuration(mtlsSpec.AllowedClockSkew)
if err != nil {
return conf, fmt.Errorf("error parsing AllowedClockSkew duration: %w", err)
}

View File

@ -26,7 +26,7 @@ func TestConfig(t *testing.T) {
t.Run("parse configuration", func(t *testing.T) {
daprConfig := daprDaprConfig.Configuration{
Spec: daprDaprConfig.ConfigurationSpec{
MTLSSpec: daprDaprConfig.MTLSSpec{
MTLSSpec: &daprDaprConfig.MTLSSpec{
Enabled: true,
WorkloadCertTTL: "5s",
AllowedClockSkew: "1h",

View File

@ -217,7 +217,7 @@ func TestServiceInvocationWithAllowLists(t *testing.T) {
t.Logf("configuration name: daprsystem, get failed: %s \n", err.Error())
os.Exit(-1)
}
if !config.Spec.MTLSSpec.Enabled {
if !config.Spec.MTLSSpec.GetEnabled() {
t.Logf("mtls disabled. can't running unit tests")
return
}

View File

@ -31,7 +31,7 @@ import (
"github.com/dapr/dapr/tests/runner/summary"
"github.com/stretchr/testify/require"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
var (

View File

@ -11,7 +11,7 @@ code-generate: controller-gen
$(CONTROLLER_GEN) object:headerFile="./tools/boilerplate.go.txt" \
crd:crdVersions=v1 paths="./pkg/apis/..." output:crd:artifacts:config=config/crd/bases
$(CONTROLLER_GEN) object:headerFile="./tools/boilerplate.go.txt" \
paths="./pkg/apis/..."
paths="./pkg/apis/..."
# find or download controller-gen
# download controller-gen if necessary
@ -21,7 +21,7 @@ ifeq (, $(shell which controller-gen))
set -e ;\
CONTROLLER_GEN_TMP_DIR="$$(mktemp -d)" ;\
cd "$$CONTROLLER_GEN_TMP_DIR" ;\
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.5.0 ; \
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.11.3 ; \
rm -rf "$$CONTROLLER_GEN_TMP_DIR" ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen