blob: 3246ca0c337371f964fadab72039d99f6c9b26f0 [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package mocks
17
18import (
khenaidooc7005fc2019-11-18 19:23:57 -050019 "fmt"
khenaidoo59ce9dd2019-11-11 13:05:32 -050020 "go.etcd.io/etcd/embed"
21 "log"
khenaidooc7005fc2019-11-18 19:23:57 -050022 "net/url"
khenaidoo59ce9dd2019-11-11 13:05:32 -050023 "os"
24 "time"
25)
26
27const (
khenaidooc7005fc2019-11-18 19:23:57 -050028 serverStartUpTimeout = 10 * time.Second // Maximum time allowed to wait for the Etcd server to be ready
29 defaultLocalPersistentStorage = "voltha.test.embed.etcd"
khenaidoo59ce9dd2019-11-11 13:05:32 -050030)
31
32//EtcdServer represents an embedded Etcd server. It is used for testing only.
33type EtcdServer struct {
34 server *embed.Etcd
35}
36
khenaidooc7005fc2019-11-18 19:23:57 -050037func islogLevelValid(logLevel string) bool {
38 valid := []string{"debug", "info", "warn", "error", "panic", "fatal"}
39 for _, l := range valid {
40 if l == logLevel {
41 return true
42 }
43 }
44 return false
45}
46
47/*
48* MKConfig creates an embedded Etcd config
49* :param configName: A name for this config
50* :param clientPort: The port the etcd client will connect to (do not use 2379 for unit test)
51* :param peerPort: The port the etcd server will listen for its peers (do not use 2380 for unit test)
52* :param localPersistentStorageDir: The name of a local directory which will hold the Etcd server data
53* :param logLevel: One of debug, info, warn, error, panic, or fatal. Default 'info'.
54 */
55func MKConfig(configName string, clientPort, peerPort int, localPersistentStorageDir string, logLevel string) *embed.Config {
56 cfg := embed.NewConfig()
57 cfg.Name = configName
58 cfg.Dir = localPersistentStorageDir
59 cfg.Logger = "zap"
60 if !islogLevelValid(logLevel) {
61 log.Fatalf("Invalid log level -%s", logLevel)
62 }
63 cfg.LogLevel = logLevel
64 acurl, err := url.Parse(fmt.Sprintf("http://localhost:%d", clientPort))
65 if err != nil {
66 log.Fatalf("Invalid client port -%d", clientPort)
67 }
68 cfg.ACUrls = []url.URL{*acurl}
69 cfg.LCUrls = []url.URL{*acurl}
70
71 apurl, err := url.Parse(fmt.Sprintf("http://localhost:%d", peerPort))
72 if err != nil {
73 log.Fatalf("Invalid peer port -%d", peerPort)
74 }
75 cfg.LPUrls = []url.URL{*apurl}
76 cfg.APUrls = []url.URL{*apurl}
77
78 cfg.ClusterState = embed.ClusterStateFlagNew
79 cfg.InitialCluster = cfg.Name + "=" + apurl.String()
80
81 return cfg
82}
83
khenaidoo59ce9dd2019-11-11 13:05:32 -050084//getDefaultCfg specifies the default config
85func getDefaultCfg() *embed.Config {
86 cfg := embed.NewConfig()
khenaidooc7005fc2019-11-18 19:23:57 -050087 cfg.Dir = defaultLocalPersistentStorage
khenaidoo59ce9dd2019-11-11 13:05:32 -050088 cfg.Logger = "zap"
89 cfg.LogLevel = "error"
90 return cfg
91}
92
93//StartEtcdServer creates and starts an embedded Etcd server. A local directory to store data is created for the
94//embedded server lifetime (for the duration of a unit test. The server runs at localhost:2379.
95func StartEtcdServer(cfg *embed.Config) *EtcdServer {
96 // If the server is already running, just return
97 if cfg == nil {
98 cfg = getDefaultCfg()
99 }
100 // Remove the local directory as
101 // a safeguard for the case where a prior test failed
khenaidooc7005fc2019-11-18 19:23:57 -0500102 if err := os.RemoveAll(cfg.Dir); err != nil {
103 log.Fatalf("Failure removing local directory %s", cfg.Dir)
khenaidoo59ce9dd2019-11-11 13:05:32 -0500104 }
105 e, err := embed.StartEtcd(cfg)
106 if err != nil {
107 log.Fatal(err)
108 }
109 select {
110 case <-e.Server.ReadyNotify():
111 log.Printf("Embedded Etcd server is ready!")
112 case <-time.After(serverStartUpTimeout):
113 e.Server.HardStop() // trigger a shutdown
114 e.Close()
115 log.Fatal("Embedded Etcd server took too long to start!")
116 case err := <-e.Err():
117 e.Server.HardStop() // trigger a shutdown
118 e.Close()
119 log.Fatalf("Embedded Etcd server errored out - %s", err)
120 }
121 return &EtcdServer{server: e}
122}
123
124//Stop closes the embedded Etcd server and removes the local data directory as well
125func (es *EtcdServer) Stop() {
126 if es != nil {
khenaidooc7005fc2019-11-18 19:23:57 -0500127 storage := es.server.Config().Dir
khenaidoo59ce9dd2019-11-11 13:05:32 -0500128 es.server.Server.HardStop()
129 es.server.Close()
khenaidooc7005fc2019-11-18 19:23:57 -0500130 if err := os.RemoveAll(storage); err != nil {
khenaidoo59ce9dd2019-11-11 13:05:32 -0500131 log.Fatalf("Failure removing local directory %s", es.server.Config().Dir)
132 }
133 }
134}