1 package couchctl
2
3 import (
4 "flag"
5 "fmt"
6 "os"
7 "time"
8
9 "github.com/peterbourgon/ff/v3"
10
11 "edge-infra.dev/pkg/edge/apis/meta"
12 "edge-infra.dev/pkg/edge/constants/api/cluster"
13 "edge-infra.dev/pkg/edge/constants/api/fleet"
14 "edge-infra.dev/pkg/edge/datasync/couchdb"
15 v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
16 )
17
18 type Config struct {
19 CompactRatio float64
20
21 RequeueTime time.Duration
22 ServerNotReady time.Duration
23 DatabaseNotFound time.Duration
24 IngressNotReady time.Duration
25 PollingInterval time.Duration
26 ReplicationPollingInterval time.Duration
27 ReplicationChangesInterval time.Duration
28 EnablementWatchInterval time.Duration
29 ReplicationDBCreated time.Duration
30 DatasyncDNSName string
31 CouchDBPort string
32 FleetType string
33 ClusterType string
34 BannerEdgeID string
35 ProjectID string
36 SiteID string
37 CouchNamespace string
38 CouchCTLNamespace string
39 InterlockAPIURL string
40 NodeUID string
41 NodeClass string
42 NodeRole string
43 ReplicationEventFromSource bool
44 ReconcileConcurrency int
45 }
46
47 func NewConfig() (*Config, error) {
48 cfg := &Config{}
49
50 fs := flag.NewFlagSet("couchctl", flag.ExitOnError)
51
52 cfg.BindFlags(fs)
53
54 if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarNoPrefix(), ff.WithIgnoreUndefined(true)); err != nil {
55 return cfg, err
56 }
57
58 if err := cfg.Validate(); err != nil {
59 return cfg, err
60 }
61
62 return cfg, nil
63 }
64
65 func (c *Config) BindFlags(fs *flag.FlagSet) {
66 fs.Float64Var(
67 &c.CompactRatio,
68 "compact-ratio",
69 0,
70 "compact db = sizes.file / sizes.active > compact-ratio, set to zero to disable",
71 )
72
73 fs.IntVar(
74 &c.ReconcileConcurrency,
75 "reconcile-concurrency",
76 10,
77 "reconcile concurrency for couch resources",
78 )
79
80 fs.DurationVar(
81 &c.RequeueTime,
82 "requeue-time",
83 30*time.Second,
84 "requeue on error",
85 )
86
87 fs.DurationVar(
88 &c.ServerNotReady,
89 "server-not-ready",
90 30*time.Second,
91 "server not ready requeue duration",
92 )
93
94 fs.DurationVar(
95 &c.DatabaseNotFound,
96 "database-not-found",
97 30*time.Second,
98 "database not found requeue duration",
99 )
100
101 fs.DurationVar(
102 &c.ReplicationDBCreated,
103 "replication-db-created",
104 5*time.Second,
105 "replication db created",
106 )
107
108 fs.DurationVar(
109 &c.IngressNotReady,
110 "ingress-not-ready",
111 1*time.Minute,
112 "Ingress not ready requeue duration",
113 )
114
115 fs.DurationVar(
116 &c.PollingInterval,
117 "polling-interval",
118 2*time.Minute,
119 "polling interval for couchdb resources etc..",
120 )
121
122 fs.DurationVar(
123 &c.ReplicationPollingInterval,
124 "replication-polling-interval",
125 10*time.Minute,
126 "polling interval for replication etc..",
127 )
128
129 fs.DurationVar(
130 &c.ReplicationChangesInterval,
131 "replication-changes-interval",
132 30*time.Second,
133 "polling interval for replication changes etc..",
134 )
135
136 fs.DurationVar(
137 &c.EnablementWatchInterval,
138 "enablement-watch-interval",
139 2*time.Minute,
140 "couchdb enablement watch interval, needed to start reconcilers",
141 )
142
143 fs.StringVar(
144 &c.DatasyncDNSName,
145 "datasync-dns-name",
146 "datasync-preprod.dev",
147 "exact dns name know as shown in gcp, remove the ending dot(.). e.g.. 'datasync-preprod.dev', optional for stores",
148 )
149
150 fs.StringVar(
151 &c.CouchDBPort,
152 "couchdb-port",
153 couchdb.Port,
154 "Couch DB port",
155 )
156
157 fs.StringVar(
158 &c.FleetType,
159 "fleet-type",
160 "",
161 "Fleet Type",
162 )
163
164 fs.StringVar(
165 &c.ClusterType,
166 "cluster-type",
167 "",
168 "Cluster Type",
169 )
170
171 fs.StringVar(
172 &c.BannerEdgeID,
173 "banner-edge-id",
174 "",
175 "Cluster Banner Edge ID",
176 )
177
178 fs.StringVar(
179 &c.ProjectID,
180 "project-id",
181 "",
182 "Cluster Project ID",
183 )
184
185 fs.StringVar(
186 &c.SiteID,
187 "site-id",
188 "",
189 "BSL Info Site ID",
190 )
191
192 fs.StringVar(
193 &c.CouchNamespace,
194 "couch-namespace",
195 "data-sync-couchdb",
196 "Couch DB namespace",
197 )
198
199 fs.StringVar(
200 &c.CouchCTLNamespace,
201 "couchctl-namespace",
202 "couchctl",
203 "Couch CTL namespace",
204 )
205
206 fs.StringVar(
207 &c.InterlockAPIURL,
208 "interlock-api-url",
209 "interlock.interlock.svc.cluster.local",
210 "Interlock API URL",
211 )
212
213 fs.StringVar(
214 &c.NodeUID,
215 "node-uid",
216 "",
217 "Node UID",
218 )
219
220 fs.StringVar(
221 &c.NodeClass,
222 "node-class",
223 "",
224 "Node Class",
225 )
226
227 fs.StringVar(
228 &c.NodeRole,
229 "node-role",
230 "",
231 "Node Role",
232 )
233
234 fs.BoolVar(
235 &c.ReplicationEventFromSource,
236 "replication-event-from-source",
237 false,
238 "Replication Event From Source",
239 )
240 }
241
242 func (c *Config) Validate() error {
243 if c.FleetType == "" {
244 return fmt.Errorf("missing FLEET_TYPE environment variable")
245 }
246 if c.ClusterType == "" {
247 return fmt.Errorf("missing CLUSTER_TYPE environment variable")
248 }
249 if c.BannerEdgeID == "" {
250 return fmt.Errorf("missing BANNER_EDGE_ID environment variable")
251 }
252 if c.ProjectID == "" {
253 return fmt.Errorf("missing PROJECT_ID environment variable")
254 }
255
256 if c.RequeueTime == 0 {
257 return fmt.Errorf("missing REQUEUE_TIME environment variable")
258 }
259 if c.ServerNotReady == 0 {
260 return fmt.Errorf("missing SERVER_NOT_READY environment variable")
261 }
262 if c.DatabaseNotFound == 0 {
263 return fmt.Errorf("missing DATABASE_NOT_FOUND environment variable")
264 }
265 if c.ReplicationDBCreated == 0 {
266 return fmt.Errorf("missing REPLICATION_DB_CREATED environment variable")
267 }
268 if c.IngressNotReady == 0 {
269 return fmt.Errorf("missing INGRESS_NOT_READY environment variable")
270 }
271 if c.PollingInterval == 0 {
272 return fmt.Errorf("missing POLLING_INTERVAL environment variable")
273 }
274 if c.ReplicationPollingInterval == 0 {
275 return fmt.Errorf("missing REPLICATION_POLLING_INTERVAL environment variable")
276 }
277 if c.ReplicationChangesInterval == 0 {
278 return fmt.Errorf("missing REPLICATION_CHANGES_INTERVAL environment variable")
279 }
280 if c.EnablementWatchInterval == 0 {
281 return fmt.Errorf("missing ENABLEMENT_WATCH_INTERVAL environment variable")
282 }
283 if c.CouchDBPort == "" {
284 return fmt.Errorf("missing COUCHDB_PORT environment variable")
285 }
286 if c.DatasyncDNSName == "" {
287 return fmt.Errorf("DATASYNC_DNS_NAME is not provided for couchdb masters")
288 }
289 if c.CouchNamespace == "" {
290 return fmt.Errorf("missing COUCH_NAMESPACE environment variable")
291 }
292 if c.CouchCTLNamespace == "" {
293 return fmt.Errorf("missing COUCHCTL_NAMESPACE environment variable")
294 }
295 if c.InterlockAPIURL == "" {
296 return fmt.Errorf("missing INTERLOCK_API_URL environment variable")
297 }
298 if c.IsDSDS() {
299 if c.NodeUID == "" {
300 return fmt.Errorf("missing NODE_UID environment variable")
301 }
302 if c.NodeClass == "" {
303 return fmt.Errorf("missing NODE_CLASS environment variable")
304 }
305 if c.NodeRole == "" {
306 return fmt.Errorf("missing NODE_ROLE environment variable")
307 }
308 }
309 return nil
310 }
311
312 func (c *Config) ReplicationDB() string {
313 return couchdb.ReplicationDBPrefix + meta.Hash(c.BannerEdgeID)
314 }
315
316 func (c *Config) IsGKE() bool {
317 return c.ClusterType == cluster.DSDS
318 }
319
320 func (c *Config) IsDSDS() bool {
321 return c.ClusterType == cluster.DSDS
322 }
323
324 func (c *Config) IsGeneric() bool {
325 return c.ClusterType == cluster.Generic
326 }
327
328 func (c *Config) IsStore() bool {
329 return c.FleetType == fleet.Store || c.FleetType == fleet.BasicStore
330 }
331
332 func (c *Config) CloudURL() string {
333 return fmt.Sprintf("https://%s.%s", c.BannerEdgeID, c.DatasyncDNSName)
334 }
335
336 func (c *Config) IsCPNode() bool {
337 return v1ien.Role(c.NodeRole) == v1ien.ControlPlane
338 }
339
View as plain text