File: options.go

package info (click to toggle)
golang-github-socketplane-libovsdb 0.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,468 kB
  • sloc: makefile: 59; sh: 27
file content (181 lines) | stat: -rw-r--r-- 5,786 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package client

import (
	"crypto/tls"
	"errors"
	"net/url"
	"time"

	"github.com/cenkalti/backoff/v4"
	"github.com/go-logr/logr"
	"github.com/prometheus/client_golang/prometheus"
)

const (
	defaultTCPEndpoint  = "tcp:127.0.0.1:6640"
	defaultSSLEndpoint  = "ssl:127.0.0.1:6640"
	defaultUnixEndpoint = "unix:/var/run/openvswitch/ovsdb.sock"
)

type options struct {
	endpoints             []string
	tlsConfig             *tls.Config
	reconnect             bool
	leaderOnly            bool
	validateModel         bool
	timeout               time.Duration
	backoff               backoff.BackOff
	logger                *logr.Logger
	registry              prometheus.Registerer
	shouldRegisterMetrics bool   // in case metrics are changed after-the-fact
	metricNamespace       string // prometheus metric namespace
	metricSubsystem       string // prometheus metric subsystem
	inactivityTimeout     time.Duration
}

type Option func(o *options) error

func newOptions(opts ...Option) (*options, error) {
	o := &options{}
	for _, opt := range opts {
		if err := opt(o); err != nil {
			return nil, err
		}
	}
	// if no endpoints are supplied, use the default unix socket
	if len(o.endpoints) == 0 {
		o.endpoints = []string{defaultUnixEndpoint}
	}
	return o, nil
}

// WithTLSConfig sets the tls.Config for use by the client
func WithTLSConfig(cfg *tls.Config) Option {
	return func(o *options) error {
		o.tlsConfig = cfg
		return nil
	}
}

// WithEndpoint sets the endpoint to be used by the client
// It can be used multiple times, and the first endpoint that
// successfully connects will be used.
// Endpoints are specified in OVSDB Connection Format
// For more details, see the ovsdb(7) man page
func WithEndpoint(endpoint string) Option {
	return func(o *options) error {
		ep, err := url.Parse(endpoint)
		if err != nil {
			return err
		}
		switch ep.Scheme {
		case UNIX:
			if len(ep.Path) == 0 {
				o.endpoints = append(o.endpoints, defaultUnixEndpoint)
				return nil
			}
		case TCP:
			if len(ep.Opaque) == 0 {
				o.endpoints = append(o.endpoints, defaultTCPEndpoint)
				return nil
			}
		case SSL:
			if len(ep.Opaque) == 0 {
				o.endpoints = append(o.endpoints, defaultSSLEndpoint)
				return nil
			}
		}
		o.endpoints = append(o.endpoints, endpoint)
		return nil
	}
}

// WithLeaderOnly tells the client to treat endpoints that are clustered
// and not the leader as down.
func WithLeaderOnly(leaderOnly bool) Option {
	return func(o *options) error {
		o.leaderOnly = leaderOnly
		return nil
	}
}

// WithReconnect tells the client to automatically reconnect when
// disconnected. The timeout is used to construct the context on
// each call to Connect, while backoff dictates the backoff
// algorithm to use. Using WithReconnect implies that
// requested transactions will block until the client has fully reconnected,
// rather than immediately returning an error if there is no connection.
func WithReconnect(timeout time.Duration, backoff backoff.BackOff) Option {
	return func(o *options) error {
		o.reconnect = true
		o.timeout = timeout
		o.backoff = backoff
		return nil
	}
}

// WithInactivityCheck tells the client to send Echo request to ovsdb server periodically
// upon inactivityTimeout. When Echo request fails, then it attempts to reconnect
// with server. The inactivity check is performed as long as the connection is established.
// The reconnectTimeout argument is used to construct the context on each call to Connect,
// while reconnectBackoff dictates the backoff algorithm to use.
func WithInactivityCheck(inactivityTimeout, reconnectTimeout time.Duration,
	reconnectBackoff backoff.BackOff) Option {
	return func(o *options) error {
		if reconnectTimeout >= inactivityTimeout {
			return errors.New("inactivity timeout value should be greater than reconnect timeout value")
		}
		o.reconnect = true
		o.timeout = reconnectTimeout
		o.backoff = reconnectBackoff
		o.inactivityTimeout = inactivityTimeout
		return nil
	}
}

// WithLogger allows setting a specific log sink. Otherwise, the default
// go log package is used.
func WithLogger(l *logr.Logger) Option {
	return func(o *options) error {
		o.logger = l
		return nil
	}
}

// WithMetricsRegistry allows the user to specify a Prometheus metrics registry.
// If supplied, the metrics as defined in metrics.go will be registered.
func WithMetricsRegistry(r prometheus.Registerer) Option {
	return func(o *options) error {
		o.registry = r
		o.shouldRegisterMetrics = (r != nil)
		return nil
	}
}

// WithMetricsRegistryNamespaceSubsystem allows the user to specify a Prometheus metrics registry
// and Prometheus metric namespace and subsystem of the component utilizing libovsdb.
// If supplied, the metrics as defined in metrics.go will be registered.
func WithMetricsRegistryNamespaceSubsystem(r prometheus.Registerer, namespace, subsystem string) Option {
	if namespace == "" || subsystem == "" {
		panic("libovsdb function WithMetricsRegistryNamespaceSubsystem arguments 'namespace' and 'subsystem' must not be empty")
	}
	return func(o *options) error {
		o.registry = r
		o.shouldRegisterMetrics = (r != nil)
		o.metricNamespace = namespace
		o.metricSubsystem = subsystem
		return nil
	}
}

// WithValidateModel allows for client-side tag-based schema validation on API.Create(), API.Mutate() and API.Update()
// including following constraints
// - Integer/Real Ranges: Checks if a number is within the defined minInteger/maxInteger or minReal/maxReal bounds.
// - Length/Size Constraints: Verifies that strings, sets, and maps adhere to minLength and maxLength requirements.
// - Enumerations: Ensures that a value is one of the predefined choices in a schema enum.
func WithValidateModel() Option {
	return func(o *options) error {
		o.validateModel = true
		return nil
	}
}