RIC-208 - KA Decision: ask K8S to restart E2T instance 94/3194/1
authorIrina <ib565x@intl.att.com>
Tue, 7 Apr 2020 13:37:20 +0000 (16:37 +0300)
committerIrina <ib565x@intl.att.com>
Tue, 7 Apr 2020 13:37:37 +0000 (16:37 +0300)
Change-Id: Ia5a0d0fe50e6f5f43210d760e9de779fea549c10
Signed-off-by: Irina <ib565x@intl.att.com>
36 files changed:
E2Manager/app/main.go
E2Manager/configuration/configuration.go
E2Manager/configuration/configuration_test.go
E2Manager/container-tag.yaml
E2Manager/go.mod
E2Manager/go.sum
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go
E2Manager/kub_config.yml [new file with mode: 0644]
E2Manager/managers/e2t_instances_manager.go
E2Manager/managers/e2t_instances_manager_test.go
E2Manager/managers/e2t_keep_alive_worker_test.go
E2Manager/managers/e2t_shutdown_manager.go
E2Manager/managers/e2t_shutdown_manager_test.go
E2Manager/managers/kubernetes_manager.go [new file with mode: 0644]
E2Manager/managers/kubernetes_manager_test.go [new file with mode: 0644]
E2Manager/mocks/e2t_instances_manager_mock.go
E2Manager/models/e2_term_init_payload.go
E2Manager/rNibWriter/rNibWriter_test.go
E2Manager/resources/configuration.yaml
E2Manager/router_test.txt [deleted file]
E2Manager/services/rnib_data_service.go
Swagger/E2Manager_API.yaml
tools/KubernetesSimulator/Dockerfile [new file with mode: 0644]
tools/KubernetesSimulator/api/swagger.yaml [new file with mode: 0755]
tools/KubernetesSimulator/configuration/configuration.go [new file with mode: 0644]
tools/KubernetesSimulator/configuration/configuration_test.go [new file with mode: 0644]
tools/KubernetesSimulator/go.mod [new file with mode: 0644]
tools/KubernetesSimulator/go.sum [new file with mode: 0644]
tools/KubernetesSimulator/go/controller.go [new file with mode: 0755]
tools/KubernetesSimulator/go/logger.go [new file with mode: 0755]
tools/KubernetesSimulator/go/request.go [new file with mode: 0755]
tools/KubernetesSimulator/go/routers.go [new file with mode: 0755]
tools/KubernetesSimulator/main.go [new file with mode: 0755]
tools/KubernetesSimulator/resources/configuration.yaml [new file with mode: 0644]
tools/RoutingManagerSimulator/api/swagger.yaml

index f597e9c..d5e16a2 100644 (file)
@@ -57,11 +57,12 @@ func main() {
        var msgImpl *rmrCgo.Context
        rmrMessenger := msgImpl.Init("tcp:"+strconv.Itoa(config.Rmr.Port), config.Rmr.MaxMsgSize, 0, logger)
        rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
+       kubernetes := managers.NewKubernetesManager(logger, config)
        ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
        e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
        routingManagerClient := clients.NewRoutingManagerClient(logger, config, clients.NewHttpClient())
        e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
-       e2tShutdownManager := managers.NewE2TShutdownManager(logger, config, rnibDataService, e2tInstancesManager, e2tAssociationManager)
+       e2tShutdownManager := managers.NewE2TShutdownManager(logger, config, rnibDataService, e2tInstancesManager, e2tAssociationManager, kubernetes)
        e2tKeepAliveWorker := managers.NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManager, config)
        rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider()
        rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager)
index 9ef7c33..54a0410 100644 (file)
@@ -38,6 +38,10 @@ type Configuration struct {
        RoutingManager struct {
                BaseUrl string
        }
+       Kubernetes struct {
+               ConfigPath string
+               Namespace  string
+       }
        NotificationResponseBuffer   int
        BigRedButtonTimeoutSec       int
        MaxConnectionAttempts        int
@@ -69,6 +73,7 @@ func ParseConfiguration() *Configuration {
        config.populateHttpConfig(viper.Sub("http"))
        config.populateLoggingConfig(viper.Sub("logging"))
        config.populateRoutingManagerConfig(viper.Sub("routingManager"))
+       config.populateKubernetesConfig(viper.Sub("kubernetes"))
        config.NotificationResponseBuffer = viper.GetInt("notificationResponseBuffer")
        config.BigRedButtonTimeoutSec = viper.GetInt("bigRedButtonTimeoutSec")
        config.MaxConnectionAttempts = viper.GetInt("maxConnectionAttempts")
@@ -110,6 +115,14 @@ func (c *Configuration) populateRoutingManagerConfig(rmConfig *viper.Viper) {
        c.RoutingManager.BaseUrl = rmConfig.GetString("baseUrl")
 }
 
+func (c *Configuration) populateKubernetesConfig(rmConfig *viper.Viper) {
+       if rmConfig == nil {
+               panic(fmt.Sprintf("#configuration.populateKubernetesConfig - failed to populate Kubernetes configuration: The entry 'kubernetes' not found\n"))
+       }
+       c.Kubernetes.ConfigPath = rmConfig.GetString("configPath")
+       c.Kubernetes.Namespace = rmConfig.GetString("namespace")
+}
+
 func (c *Configuration) populateGlobalRicIdConfig(globalRicIdConfig *viper.Viper) {
        if globalRicIdConfig == nil {
                panic(fmt.Sprintf("#configuration.populateGlobalRicIdConfig - failed to populate Global RicId configuration: The entry 'globalRicId' not found\n"))
@@ -122,7 +135,7 @@ func (c *Configuration) String() string {
        return fmt.Sprintf("{logging.logLevel: %s, http.port: %d, rmr: { port: %d, maxMsgSize: %d}, routingManager.baseUrl: %s, "+
                "notificationResponseBuffer: %d, bigRedButtonTimeoutSec: %d, maxConnectionAttempts: %d, maxRnibConnectionAttempts: %d, "+
                "rnibRetryIntervalMs: %d, keepAliveResponseTimeoutMs: %d, keepAliveDelayMs: %d, e2tInstanceDeletionTimeoutMs: %d, "+
-               "globalRicId: { plmnId: %s, ricNearRtId: %s}}",
+               "globalRicId: { plmnId: %s, ricNearRtId: %s}, kubernetes: {configPath: %s, namespace: %s}}",
                c.Logging.LogLevel,
                c.Http.Port,
                c.Rmr.Port,
@@ -138,5 +151,7 @@ func (c *Configuration) String() string {
                c.E2TInstanceDeletionTimeoutMs,
                c.GlobalRicId.PlmnId,
                c.GlobalRicId.RicNearRtId,
+               c.Kubernetes.ConfigPath,
+               c.Kubernetes.Namespace,
        )
 }
index 38f8bba..ce0448d 100644 (file)
@@ -42,6 +42,8 @@ func TestParseConfigurationSuccess(t *testing.T) {
        assert.NotNil(t, config.GlobalRicId)
        assert.NotEmpty(t, config.GlobalRicId.PlmnId)
        assert.NotEmpty(t, config.GlobalRicId.RicNearRtId)
+       assert.NotEmpty(t, config.Kubernetes.Namespace)
+       assert.NotEmpty(t, config.Kubernetes.ConfigPath)
 }
 
 func TestStringer(t *testing.T) {
@@ -206,6 +208,7 @@ func TestGlobalRicIdConfigNotFoundFailure(t *testing.T) {
                "logging": map[string]interface{}{"logLevel": "info"},
                "http": map[string]interface{}{"port": 3800},
                "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
+               "kubernetes":    map[string]interface{}{"namespace": "test", "ConfigPath": "test"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
@@ -218,3 +221,35 @@ func TestGlobalRicIdConfigNotFoundFailure(t *testing.T) {
        assert.PanicsWithValue(t, "#configuration.populateGlobalRicIdConfig - failed to populate Global RicId configuration: The entry 'globalRicId' not found\n",
                func() { ParseConfiguration() })
 }
+
+func TestKubernetesConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{
+               "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
+               "logging": map[string]interface{}{"logLevel": "info"},
+               "http": map[string]interface{}{"port": 3800},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
+               "globalRicId":    map[string]interface{}{"plmnId": "131014", "ricNearRtId": "556670"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.populateKubernetesConfig - failed to populate Kubernetes configuration: The entry 'kubernetes' not found\n",
+               func() { ParseConfiguration() })
+}
index 323a4dc..4504e37 100644 (file)
@@ -1,4 +1,4 @@
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
 ---
-tag: 4.0.3
+tag: 4.4.1
index a15e96a..02a35a1 100644 (file)
@@ -1,30 +1,31 @@
 module e2mgr
 
 require (
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.33
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.33
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.33
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.34
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.34
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.34
        gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.2
        github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
        github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
        github.com/golang/protobuf v1.3.4
        github.com/gorilla/mux v1.7.0
+       github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
+       github.com/imdario/mergo v0.3.9 // indirect
        github.com/magiconair/properties v1.8.1
        github.com/pelletier/go-toml v1.5.0 // indirect
        github.com/pkg/errors v0.8.1
-       github.com/spf13/afero v1.2.2 // indirect
        github.com/spf13/jwalterweatherman v1.1.0 // indirect
-       github.com/spf13/pflag v1.0.5 // indirect
        github.com/spf13/viper v1.4.0
        github.com/stretchr/objx v0.2.0 // indirect
        github.com/stretchr/testify v1.4.0
        go.uber.org/multierr v1.2.0 // indirect
        go.uber.org/zap v1.11.0
        golang.org/x/net v0.0.0-20191021144547-ec77196f6094 // indirect
-       golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 // indirect
-       golang.org/x/text v0.3.2 // indirect
        gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
-       gopkg.in/yaml.v2 v2.2.4
+       gopkg.in/yaml.v2 v2.2.8
+       k8s.io/api v0.17.0
+       k8s.io/apimachinery v0.17.0
+       k8s.io/client-go v0.17.0
 )
 
 replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2
index 06cbede..d72ec0e 100644 (file)
@@ -1,17 +1,35 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.32/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.33 h1:QqWDNf3E8OpevC8swnZFxd56oW/7+5kVa9Ps4LWAZy8=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.33/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.34 h1:d53dCN59dZftx847pzyo/zIKk0XJjOqMAx4VwxJHO10=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.34/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.32/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.33 h1:VwfmU5yww6nejkRK2qYD/+VYy6+RBHWHihInHwgK1EE=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.33/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.34 h1:7jxKtb+VPgwHKxQuWne1mG09rsi330erwb1u4OsWEaA=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.34/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.33 h1:dUTtIlG3F1+qyDZ1OIVsVFwygAioLNUkjiMzxTaHV9o=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.33/go.mod h1:oPHTwdTeaOEuvqVRAog9WoCTW7O6ynE6rOyFB/sp9C0=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.34 h1:niBDUlmhq+8dhXt7z8KW+ZBq/0XlnM4FzvrLYlub1co=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.34/go.mod h1:tcc2L3Fb7hTvxK+QVTCbWjBX//078qOgPMwA9ZyCxY4=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 h1:UK7awyRKIkVdokWvvkYvazlg3EWIfMnIqCcJxTnLlDA=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
+github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
+github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
+github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
+github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
+github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
+github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
+github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
@@ -28,48 +46,102 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
+github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
+github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
+github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
 github.com/go-ozzo/ozzo-validation v3.5.0+incompatible h1:sUy/in/P6askYr16XJgTKq/0SZhiWsdg4WZGaLsGQkM=
 github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
 github.com/go-redis/redis v6.15.3+incompatible h1:NZ0O90AhLSvSrvLZ/S9h7D4kl1mW2PrKyxL7MyBKO2g=
 github.com/go-redis/redis v6.15.3+incompatible/go.mod h1:W2YCLaZryXHirdd9QqwkiVUxCQsrx8SbLq9Uqk7JS7A=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
+github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
 github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
+github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
+github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
+github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
+github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
+github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
 github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
 github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
+github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
+github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
+github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -82,23 +154,41 @@ github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDe
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
 github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.5.0 h1:5BakdOZdtKJ1FFk6QdL8iSGrMWsXgchNJcrnarjbmJQ=
 github.com/pelletier/go-toml v1.5.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
+github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -126,6 +216,7 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
+github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -137,6 +228,7 @@ github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -147,6 +239,7 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
@@ -158,44 +251,79 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.11.0 h1:gSmpCfs+R47a4yQPAI4xJ0IPDLTRGXskm6UelqNXpqE=
 go.uber.org/zap v1.11.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20191021144547-ec77196f6094 h1:5O4U9trLjNpuhpynaDsqwCk+Tw6seqJz1EbqbnzHrc8=
 golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
 golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
@@ -207,6 +335,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
@@ -216,4 +346,44 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+k8s.io/api v0.0.0-20190111032252-67edc246be36 h1:XrFGq/4TDgOxYOxtNROTyp2ASjHjBIITdk/+aJD+zyY=
+k8s.io/api v0.0.0-20190111032252-67edc246be36/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
+k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
+k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
+k8s.io/api v0.18.0 h1:lwYk8Vt7rsVTwjRU6pzEsa9YNhThbmbocQlKvNBB4EQ=
+k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
+k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
+k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
+k8s.io/apimachinery v0.18.0 h1:fuPfYpk3cs1Okp/515pAf0dNhL66+8zk8RLbSX+EgAE=
+k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
+k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg=
+k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
+k8s.io/client-go v4.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
+k8s.io/client-go v10.0.0+incompatible h1:F1IqCqw7oMBzDkqlcBymRq1450wD0eNqLE9jzUrIi34=
+k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
+k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=
+k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
+k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
+k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
+k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
+k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
+k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
+k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
+k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+k8s.io/utils v0.0.0-20200327001022-6496210b90e8 h1:6JFbaLjRyBz8K2Jvt+pcT+N3vvwMZfg8MfVENwe9aag=
+k8s.io/utils v0.0.0-20200327001022-6496210b90e8/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
+sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
index 0059b2a..4aa4039 100644 (file)
@@ -62,7 +62,7 @@ func (h E2TermInitNotificationHandler) Handle(request *models.NotificationReques
                return
        }
 
-       h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T address: %s - handling E2_TERM_INIT", e2tAddress)
+       h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T payload: %s - handling E2_TERM_INIT", unmarshalledPayload)
 
        e2tInstance, err := h.e2tInstancesManager.GetE2TInstance(e2tAddress)
 
@@ -74,7 +74,7 @@ func (h E2TermInitNotificationHandler) Handle(request *models.NotificationReques
                        return
                }
 
-               h.HandleNewE2TInstance(e2tAddress)
+               h.HandleNewE2TInstance(e2tAddress, unmarshalledPayload.PodName)
                return
        }
 
@@ -105,7 +105,7 @@ func (h E2TermInitNotificationHandler) HandleExistingE2TInstance(e2tInstance *en
        }
 }
 
-func (h E2TermInitNotificationHandler) HandleNewE2TInstance(e2tAddress string) {
+func (h E2TermInitNotificationHandler) HandleNewE2TInstance(e2tAddress string, podName string) {
 
        err := h.routingManagerClient.AddE2TInstance(e2tAddress)
 
@@ -114,5 +114,5 @@ func (h E2TermInitNotificationHandler) HandleNewE2TInstance(e2tAddress string) {
                return
        }
 
-       _ = h.e2tInstancesManager.AddE2TInstance(e2tAddress)
+       _ = h.e2tInstancesManager.AddE2TInstance(e2tAddress, podName)
 }
\ No newline at end of file
index 159008c..bcdbbd6 100644 (file)
@@ -45,6 +45,7 @@ import (
 const (
        e2tInitPayload = "{\"address\":\"10.0.2.15\", \"fqdn\":\"\"}"
        e2tInstanceAddress = "10.0.2.15"
+       podName = "podNAme_test"
 )
 
 func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
@@ -166,7 +167,7 @@ func TestE2TermInitNewE2TInstance__RoutingManagerError(t *testing.T) {
 
 func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) {
        _, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
        notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
        handler.Handle(notificationRequest)
@@ -189,7 +190,7 @@ func TestE2TermInitHandlerSuccessOneRan(t *testing.T) {
        var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
        writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
        writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
@@ -223,7 +224,7 @@ func TestE2TermInitHandlerSuccessOneRan_RoutingManagerError(t *testing.T) {
        var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
        writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
        writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
@@ -250,7 +251,7 @@ func TestE2TermInitHandlerSuccessOneRanShuttingdown(t *testing.T) {
        var argNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0}
        writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
        notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
@@ -270,7 +271,7 @@ func TestE2TermInitHandlerSuccessOneRan_ToBeDeleted(t *testing.T) {
        var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
        writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.State = entities.ToBeDeleted
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
 
@@ -312,7 +313,7 @@ func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) {
        var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""}
        writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
@@ -352,7 +353,7 @@ func TestE2TermInitHandlerSuccessTwoRansSecondRanShutdown(t *testing.T) {
        var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
        readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
        writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
@@ -391,7 +392,7 @@ func TestE2TermInitHandlerSuccessTwoRansFirstNotFoundFailure(t *testing.T) {
        var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""}
        writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
@@ -419,7 +420,7 @@ func TestE2TermInitHandlerSuccessTwoRansFirstRnibInternalErrorFailure(t *testing
        var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
        readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewInternalError(fmt.Errorf("internal error")))
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
        readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
@@ -436,7 +437,7 @@ func TestE2TermInitHandlerSuccessTwoRansFirstRnibInternalErrorFailure(t *testing
 func TestE2TermInitHandlerSuccessZeroRans(t *testing.T) {
        _, handler, _, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
        notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
 
@@ -451,7 +452,7 @@ func TestE2TermInitHandlerFailureGetNodebInternalError(t *testing.T) {
        var nodebInfo *entities.NodebInfo
        readerMock.On("GetNodeb", "test1").Return(nodebInfo, common.NewInternalError(fmt.Errorf("internal error")))
 
-       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress)
+       e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
        e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1")
        e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
        notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
diff --git a/E2Manager/kub_config.yml b/E2Manager/kub_config.yml
new file mode 100644 (file)
index 0000000..0163244
--- /dev/null
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Config
+users:
+- name: someuser
+  user:
+    token: sometoken
+clusters:
+- cluster:
+    certificate-authority-data: somedata
+    server: 10.0.2.15:59009
+  name: self-hosted-cluster
+contexts:
+- context:
+    cluster: self-hosted-cluster
+    user: svcs-acct-dply
+  name: svcs-acct-context
+current-context: svcs-acct-context
index f8def48..982524c 100644 (file)
@@ -42,7 +42,7 @@ type IE2TInstancesManager interface {
        GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error)
        GetE2TInstances() ([]*entities.E2TInstance, error)
        GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error)
-       AddE2TInstance(e2tAddress string) error
+       AddE2TInstance(e2tAddress string, podName string) error
        RemoveE2TInstance(e2tAddress string) error
        SelectE2TInstance() (string, error)
        AddRansToInstance(e2tAddress string, ranNames []string) error
@@ -198,12 +198,12 @@ func findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances []*entities.E2T
        return minInstance
 }
 
-func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string) error {
+func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string, podName string) error {
 
        m.mux.Lock()
        defer m.mux.Unlock()
 
-       e2tInstance := entities.NewE2TInstance(e2tAddress)
+       e2tInstance := entities.NewE2TInstance(e2tAddress, podName)
        err := m.rnibDataService.SaveE2TInstance(e2tInstance)
 
        if err != nil {
@@ -232,7 +232,7 @@ func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string) error {
                return err
        }
 
-       m.logger.Infof("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - successfully added E2T instance", e2tInstance.Address)
+       m.logger.Infof("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s, pod name: %s - successfully added E2T instance", e2tInstance.Address, e2tInstance.PodName)
        return nil
 }
 
index 2674349..863bfe1 100644 (file)
@@ -36,6 +36,7 @@ import (
 
 const E2TAddress = "10.10.2.15:9800"
 const E2TAddress2 = "10.10.2.16:9800"
+const PodName = "som_ pod_name"
 
 func initE2TInstancesManagerTest(t *testing.T) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *E2TInstancesManager) {
        logger, err := logger.InitLogger(logger.DebugLevel)
@@ -54,7 +55,7 @@ func initE2TInstancesManagerTest(t *testing.T) (*mocks.RnibReaderMock, *mocks.Rn
 func TestAddNewE2TInstanceSaveE2TInstanceFailure(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
-       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
        assert.NotNil(t, err)
        rnibReaderMock.AssertNotCalled(t, "GetE2TAddresses")
 }
@@ -64,7 +65,7 @@ func TestAddNewE2TInstanceGetE2TAddressesInternalFailure(t *testing.T) {
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
        e2tAddresses := []string{}
        rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewInternalError(errors.New("Error")))
-       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
        assert.NotNil(t, err)
        rnibReaderMock.AssertNotCalled(t, "SaveE2TAddresses")
 }
@@ -76,7 +77,7 @@ func TestAddNewE2TInstanceSaveE2TAddressesFailure(t *testing.T) {
        rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
        E2TAddresses = append(E2TAddresses, E2TAddress)
        rnibWriterMock.On("SaveE2TAddresses", E2TAddresses).Return(common.NewResourceNotFoundError(""))
-       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
        assert.NotNil(t, err)
 }
 
@@ -87,7 +88,7 @@ func TestAddNewE2TInstanceNoE2TAddressesSuccess(t *testing.T) {
        rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewResourceNotFoundError(""))
        e2tAddresses = append(e2tAddresses, E2TAddress)
        rnibWriterMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
-       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
        assert.Nil(t, err)
        rnibWriterMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
 }
@@ -99,7 +100,7 @@ func TestAddNewE2TInstanceEmptyE2TAddressesSuccess(t *testing.T) {
        rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
        e2tAddresses = append(e2tAddresses, E2TAddress)
        rnibWriterMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
-       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
        assert.Nil(t, err)
        rnibWriterMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
 }
@@ -111,7 +112,7 @@ func TestAddNewE2TInstanceExistingE2TAddressesSuccess(t *testing.T) {
        rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
        E2TAddresses = append(E2TAddresses, E2TAddress)
        rnibWriterMock.On("SaveE2TAddresses", E2TAddresses).Return(nil)
-       err := e2tInstancesManager.AddE2TInstance(E2TAddress)
+       err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
        assert.Nil(t, err)
 }
 
@@ -127,7 +128,7 @@ func TestGetE2TInstanceFailure(t *testing.T) {
 func TestGetE2TInstanceSuccess(t *testing.T) {
        rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
        address := "10.10.2.15:9800"
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, PodName)
        rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
        res, err := e2tInstancesManager.GetE2TInstance(address)
        assert.Nil(t, err)
@@ -147,7 +148,7 @@ func TestAddRanToInstanceGetInstanceFailure(t *testing.T) {
 
 func TestAddRanToInstanceSaveInstanceFailure(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for test")))
 
@@ -159,7 +160,7 @@ func TestAddRanToInstanceSaveInstanceFailure(t *testing.T) {
 
 func TestAddRanToInstanceSuccess(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
-       e2tInstance := entities.NewE2TInstance(E2TAddress)
+       e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
        rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
 
        updateE2TInstance := *e2tInstance
@@ -186,7 +187,7 @@ func TestRemoveRanFromInstanceGetInstanceFailure(t *testing.T) {
 func TestRemoveRanFromInstanceSaveInstanceFailure(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for test")))
 
@@ -199,7 +200,7 @@ func TestRemoveRanFromInstanceSaveInstanceFailure(t *testing.T) {
 func TestRemoveRanFromInstanceSuccess(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
-       e2tInstance := entities.NewE2TInstance(E2TAddress)
+       e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance.AssociatedRanList = []string{"test0", "test1"}
        updatedE2TInstance := *e2tInstance
        updatedE2TInstance.AssociatedRanList = []string{"test0"}
@@ -263,10 +264,10 @@ func TestSelectE2TInstancesEmptyE2TInstancesList(t *testing.T) {
 func TestSelectE2TInstancesNoActiveE2TInstance(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        addresses := []string{E2TAddress, E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.ToBeDeleted
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.ToBeDeleted
        e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
 
@@ -282,9 +283,9 @@ func TestSelectE2TInstancesNoActiveE2TInstance(t *testing.T) {
 func TestSelectE2TInstancesSuccess(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        addresses := []string{E2TAddress, E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
 
        rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
@@ -299,7 +300,7 @@ func TestSelectE2TInstancesSuccess(t *testing.T) {
 func TestActivateE2TInstanceSuccess(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.ToBeDeleted
        e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
        rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
@@ -338,7 +339,7 @@ func TestResetKeepAliveTimestampGetInternalFailure(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
        address := "10.10.2.15:9800"
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, PodName)
        rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, common.NewInternalError(errors.New("Error")))
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
 
@@ -351,7 +352,7 @@ func TestAResetKeepAliveTimestampSaveInternalFailure(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
        address := "10.10.2.15:9800"
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, PodName)
        rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
 
@@ -363,7 +364,7 @@ func TestResetKeepAliveTimestampSuccess(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
        address := "10.10.2.15:9800"
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, PodName)
        rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
 
@@ -377,7 +378,7 @@ func TestResetKeepAliveTimestampToBeDeleted(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
        address := "10.10.2.15:9800"
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, PodName)
        e2tInstance.State = entities.ToBeDeleted
        rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
 
@@ -405,9 +406,9 @@ func TestResetKeepAliveTimestampsForAllE2TInstancesNoActiveInstances(t *testing.
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        e2tAddresses := []string{E2TAddress, E2TAddress2}
        rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.ToBeDeleted
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.ToBeDeleted
        rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
        e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
@@ -418,9 +419,9 @@ func TestResetKeepAliveTimestampsForAllE2TInstancesOneActiveInstance(t *testing.
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        e2tAddresses := []string{E2TAddress, E2TAddress2}
        rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.ToBeDeleted
        rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
@@ -432,9 +433,9 @@ func TestResetKeepAliveTimestampsForAllE2TInstancesSaveE2TInstanceFailure(t *tes
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        e2tAddresses := []string{E2TAddress, E2TAddress2}
        rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.ToBeDeleted
        rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
@@ -498,7 +499,7 @@ func TestRemoveE2TInstanceRnibErrorInSaveAddresses(t *testing.T) {
 func TestSetE2tInstanceStateCurrentStateHasChanged(t *testing.T) {
        rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
-       e2tInstance := entities.NewE2TInstance(E2TAddress)
+       e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance.State = entities.Active
 
        rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
@@ -512,7 +513,7 @@ func TestSetE2tInstanceStateCurrentStateHasChanged(t *testing.T) {
 func TestSetE2tInstanceStateErrorInSaveE2TInstance(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
 
-       e2tInstance := entities.NewE2TInstance(E2TAddress)
+       e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance.State = entities.ToBeDeleted
        rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
        rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for testing")))
@@ -536,9 +537,9 @@ func TestClearRansOfAllE2TInstancesEmptyList(t *testing.T) {
 func TestClearRansOfAllE2TInstancesErrorInSaveE2TInstance(t *testing.T) {
        rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
        addresses := []string{E2TAddress, E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
 
        rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
index 0100f28..21d26b7 100644 (file)
@@ -95,9 +95,9 @@ func TestShutdownExpiredE2T_NotExpired_InternalError(t *testing.T) {
        rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
 
        addresses := []string{E2TAddress,E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
 
        readerMock.On("GetE2TAddresses").Return(addresses, nil)
@@ -122,9 +122,9 @@ func TestShutdownExpiredE2T_NotExpired(t *testing.T) {
        rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
 
        addresses := []string{E2TAddress,E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
 
        readerMock.On("GetE2TAddresses").Return(addresses, nil)
@@ -139,12 +139,12 @@ func TestShutdownExpiredE2T_One_E2TExpired(t *testing.T) {
        _, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
 
        addresses := []string{E2TAddress,E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
 
        time.Sleep(time.Duration(400) * time.Millisecond)
 
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
 
        readerMock.On("GetE2TAddresses").Return(addresses, nil)
@@ -160,10 +160,10 @@ func TestShutdownExpiredE2T_Two_E2TExpired(t *testing.T) {
        _, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
 
        addresses := []string{E2TAddress,E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
 
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
 
        time.Sleep(time.Duration(400) * time.Millisecond)
@@ -182,7 +182,7 @@ func TestExecute_Two_E2TExpired(t *testing.T) {
        rmrMessengerMock, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
 
        addresses := []string{E2TAddress,E2TAddress2}
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
 
        readerMock.On("GetE2TAddresses").Return(addresses, nil)
index 2bb5d0f..bb89e3b 100644 (file)
@@ -39,15 +39,17 @@ type E2TShutdownManager struct {
        rnibDataService       services.RNibDataService
        e2TInstancesManager   IE2TInstancesManager
        e2tAssociationManager *E2TAssociationManager
+       kubernetesManager     *KubernetesManager
 }
 
-func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager) *E2TShutdownManager {
+func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager, kubernetes *KubernetesManager) *E2TShutdownManager {
        return &E2TShutdownManager{
                logger:                logger,
                config:                config,
                rnibDataService:       rnibDataService,
                e2TInstancesManager:   e2TInstancesManager,
                e2tAssociationManager: e2tAssociationManager,
+               kubernetesManager:     kubernetes,
        }
 }
 
@@ -60,6 +62,8 @@ func (m E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error {
                return nil
        }
 
+       go m.kubernetesManager.DeletePod(e2tInstance.PodName)
+
        err := m.markE2tInstanceToBeDeleted(e2tInstance)
        if err != nil {
                m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to mark E2T %s as 'ToBeDeleted'.", e2tInstance.Address)
@@ -78,7 +82,6 @@ func (m E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error {
                return err
        }
 
-
        m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s was shutdown successfully.", e2tInstance.Address)
        return nil
 }
index 570cf62..21de338 100644 (file)
@@ -35,6 +35,8 @@ import (
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
        "io/ioutil"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/client-go/kubernetes/fake"
        "net/http"
        "testing"
        "time"
@@ -42,7 +44,7 @@ import (
 
 const E2TAddress3 = "10.10.2.17:9800"
 
-func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
+func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock, *KubernetesManager) {
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, E2TInstanceDeletionTimeoutMs: 15000}
 
@@ -54,22 +56,23 @@ func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibR
        httpClientMock := &mocks.HttpClientMock{}
        rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
        associationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient)
+       kubernetesManager := initKubernetesManagerTest(t)
 
-       shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager)
+       shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager, kubernetesManager)
 
-       return shutdownManager, readerMock, writerMock, httpClientMock
+       return shutdownManager, readerMock, writerMock, httpClientMock, kubernetesManager
 }
 
 func TestShutdownSuccess1OutOf3Instances(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.Active
        e2tInstance2.AssociatedRanList = []string{"test3"}
-       e2tInstance3 := entities.NewE2TInstance(E2TAddress3)
+       e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
        e2tInstance3.State = entities.Active
        e2tInstance3.AssociatedRanList = []string{"test4"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -115,9 +118,9 @@ func TestShutdownSuccess1OutOf3Instances(t *testing.T) {
 }
 
 func TestShutdownSuccess1InstanceWithoutRans(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -141,9 +144,9 @@ func TestShutdownSuccess1InstanceWithoutRans(t *testing.T) {
 }
 
 func TestShutdownSuccess1Instance2Rans(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -182,9 +185,9 @@ func TestShutdownSuccess1Instance2Rans(t *testing.T) {
 }
 
 func TestShutdownE2tInstanceAlreadyBeingDeleted(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.ToBeDeleted
        e2tInstance1.AssociatedRanList = []string{"test1"}
        e2tInstance1.DeletionTimestamp = time.Now().UnixNano()
@@ -199,9 +202,9 @@ func TestShutdownE2tInstanceAlreadyBeingDeleted(t *testing.T) {
 }
 
 func TestShutdownFailureMarkInstanceAsToBeDeleted(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(e2managererrors.NewRnibDbError())
@@ -216,15 +219,15 @@ func TestShutdownFailureMarkInstanceAsToBeDeleted(t *testing.T) {
 }
 
 func TestShutdownFailureRoutingManagerError(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.Active
        e2tInstance2.AssociatedRanList = []string{"test3"}
-       e2tInstance3 := entities.NewE2TInstance(E2TAddress3)
+       e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
        e2tInstance3.State = entities.Active
        e2tInstance3.AssociatedRanList = []string{"test4"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -271,9 +274,9 @@ func TestShutdownFailureRoutingManagerError(t *testing.T) {
 }
 
 func TestShutdownFailureInClearNodebsAssociation(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -295,9 +298,9 @@ func TestShutdownFailureInClearNodebsAssociation(t *testing.T) {
 }
 
 func TestShutdownResourceNotFoundErrorInGetNodeb(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -321,9 +324,9 @@ func TestShutdownResourceNotFoundErrorInGetNodeb(t *testing.T) {
 }
 
 func TestShutdownResourceGeneralErrorInGetNodeb(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -358,15 +361,15 @@ func TestShutdownResourceGeneralErrorInGetNodeb(t *testing.T) {
 }
 
 func TestShutdownFailureInRemoveE2TInstance(t *testing.T) {
-       shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
+       shutdownManager, readerMock, writerMock, httpClientMock,_  := initE2TShutdownManagerTest(t)
 
-       e2tInstance1 := entities.NewE2TInstance(E2TAddress)
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
        e2tInstance1.State = entities.Active
        e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
-       e2tInstance2 := entities.NewE2TInstance(E2TAddress2)
+       e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
        e2tInstance2.State = entities.Active
        e2tInstance2.AssociatedRanList = []string{"test3"}
-       e2tInstance3 := entities.NewE2TInstance(E2TAddress3)
+       e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
        e2tInstance3.State = entities.Active
        e2tInstance3.AssociatedRanList = []string{"test4"}
        writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
@@ -405,4 +408,100 @@ func TestShutdownFailureInRemoveE2TInstance(t *testing.T) {
        readerMock.AssertExpectations(t)
        writerMock.AssertExpectations(t)
        httpClientMock.AssertExpectations(t)
+}
+
+func TestShutdownSuccess2Instance2Rans(t *testing.T) {
+       shutdownManager, readerMock, writerMock, httpClientMock,kubernetesManager  := initE2TShutdownManagerTest(t)
+
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
+       e2tInstance1.State = entities.Active
+       e2tInstance1.AssociatedRanList = []string{"test2"}
+       writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
+
+       nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress2, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
+
+       data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test2"}, nil)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
+
+       writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+       readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
+       writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
+
+       nodeb1new := *nodeb1
+       nodeb1new.AssociatedE2TInstanceAddress = ""
+       nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       nodeb2new := *nodeb2
+       nodeb2new.AssociatedE2TInstanceAddress = ""
+       nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil)
+
+       test := TestStruct{
+               description: "namespace, 2 pods in Oran",
+               namespace:   "oran",
+               objs:        []runtime.Object{pod("oran", PodName), pod("oran", "e2t_2"), pod("some-namespace", "POD_Test_1")},
+       }
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := shutdownManager.Shutdown(e2tInstance1)
+
+               assert.Nil(t, err)
+               readerMock.AssertExpectations(t)
+               writerMock.AssertExpectations(t)
+               httpClientMock.AssertExpectations(t)
+       })
+}
+
+func TestShutdownSuccess2Instance2RansNoPod(t *testing.T) {
+       shutdownManager, readerMock, writerMock, httpClientMock,kubernetesManager  := initE2TShutdownManagerTest(t)
+
+       e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
+       e2tInstance1.State = entities.Active
+       e2tInstance1.AssociatedRanList = []string{"test2"}
+       writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
+
+       nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress2, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
+
+       data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test2"}, nil)
+       marshaled, _ := json.Marshal(data)
+       body := bytes.NewBuffer(marshaled)
+       respBody := ioutil.NopCloser(bytes.NewBufferString(""))
+       httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
+
+       writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
+       readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
+       writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
+
+       nodeb1new := *nodeb1
+       nodeb1new.AssociatedE2TInstanceAddress = ""
+       nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       nodeb2new := *nodeb2
+       nodeb2new.AssociatedE2TInstanceAddress = ""
+       nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil)
+
+       test := TestStruct{
+               description: "namespace, 2 pods in Oran",
+               namespace:   "oran",
+               objs:        []runtime.Object{pod("oran", "e2t_2"), pod("some-namespace", "POD_Test_1")},
+       }
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := shutdownManager.Shutdown(e2tInstance1)
+
+               assert.Nil(t, err)
+               readerMock.AssertExpectations(t)
+               writerMock.AssertExpectations(t)
+               httpClientMock.AssertExpectations(t)
+       })
 }
\ No newline at end of file
diff --git a/E2Manager/managers/kubernetes_manager.go b/E2Manager/managers/kubernetes_manager.go
new file mode 100644 (file)
index 0000000..5c3e8ee
--- /dev/null
@@ -0,0 +1,140 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package managers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/client-go/kubernetes"
+       "k8s.io/client-go/tools/clientcmd"
+       "path/filepath"
+)
+
+type KubernetesManager struct {
+       Logger    *logger.Logger
+       ClientSet kubernetes.Interface
+       Config    *configuration.Configuration
+}
+
+func NewKubernetesManager(logger *logger.Logger, config *configuration.Configuration) *KubernetesManager {
+       return &KubernetesManager{
+               Logger:    logger,
+               ClientSet: createClientSet(logger, config),
+               Config:    config,
+       }
+}
+
+/*func (km KubernetesManager) GetAndDeletePod(namespace string, podName string) {
+       km.logger.Infof("#KubernetesManager.GetAndDeletePod - namespace: %s, POD name: %s ", namespace, podName)
+
+       config, err := clientcmd.BuildConfigFromFlags("", "kubeConfigPath")
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       clientSet, _ := kubernetesManager.NewForConfig(config)
+
+       podInterface := km.GetPodInterface(clientSet.CoreV1(), namespace, podName)
+
+       if podInterface == nil{
+               return
+       }
+
+       km.DeletePod(podInterface, podName)
+}*/
+
+func createClientSet(logger *logger.Logger, config *configuration.Configuration) kubernetes.Interface {
+       ////path := os.Getenv("HOME") + "/.kube/config"
+
+       absConfigPath,err := filepath.Abs(config.Kubernetes.ConfigPath)
+       if err != nil {
+               logger.Errorf("#KubernetesManager.init - error: %s", err)
+               return nil
+       }
+
+       kubernetesConfig, err := clientcmd.BuildConfigFromFlags("", absConfigPath)
+       if err != nil {
+               logger.Errorf("#KubernetesManager.init - error: %s", err)
+               return nil
+       }
+
+       clientSet, err := kubernetes.NewForConfig(kubernetesConfig)
+       if err != nil {
+               logger.Errorf("#KubernetesManager.init - error: %s", err)
+               return nil
+       }
+       return clientSet
+}
+
+/*func (km KubernetesManager) DeletePod(podInterface v1.PodInterface, podName string) {
+       km.logger.Infof("#KubernetesManager.DeletePod - POD name %s ", podName)
+
+       err := podInterface.Delete(podName, &metaV1.DeleteOptions{})
+
+       if err != nil{
+               km.logger.Warnf("#KubernetesManager.DeletePod - POD %s can't be deleted", podName)
+               return
+       }
+       km.logger.Infof("#KubernetesManager.DeletePod - POD %s was deleted", podName)
+}
+*/
+func (km KubernetesManager) DeletePod(podName string) error {
+       km.Logger.Infof("#KubernetesManager.DeletePod - POD name: %s ", podName)
+
+       if km.ClientSet == nil {
+               km.Logger.Errorf("#KubernetesManager.DeletePod - no kubernetesManager connection")
+               return e2managererrors.NewInternalError()
+       }
+
+       if len(podName) == 0 {
+               km.Logger.Warnf("#KubernetesManager.DeletePod - empty pod name")
+               return e2managererrors.NewInternalError()
+       }
+
+       err := km.ClientSet.CoreV1().Pods(km.Config.Kubernetes.Namespace).Delete(podName, &metaV1.DeleteOptions{})
+
+       if err != nil {
+               km.Logger.Errorf("#KubernetesManager.DeletePod - POD %s can't be deleted, error: %s", podName, err)
+               return err
+       }
+
+       km.Logger.Infof("#KubernetesManager.DeletePod - POD %s was deleted", podName)
+       return nil
+}
+
+/*func (km KubernetesManager) GetPodInterface(client v1.CoreV1Interface, namespace string, podName string) v1.PodInterface{
+       km.logger.Infof("#KubernetesManager.GetPodInterface - namespace: %s, POD name: %s ", namespace, podName)
+
+
+       podInterface := client.Pods(namespace)
+       pod, err := podInterface.Get(podName, metaV1.GetOptions{})
+
+       if err != nil{
+               km.logger.Warnf("#KubernetesManager.GetPodInterface - POD name: %s not found", podName)
+               return nil
+       }
+
+       km.logger.Infof("#KubernetesManager.GetPodInterface - POD status: %s ", pod.Status.String())
+
+       return podInterface
+}*/
diff --git a/E2Manager/managers/kubernetes_manager_test.go b/E2Manager/managers/kubernetes_manager_test.go
new file mode 100644 (file)
index 0000000..0f207ed
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package managers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "github.com/stretchr/testify/assert"
+       "k8s.io/api/core/v1"
+       metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/client-go/kubernetes/fake"
+       "testing"
+)
+
+type TestStruct struct {
+       description string
+       namespace   string
+       expected    []string
+       objs        []runtime.Object
+}
+
+func initKubernetesManagerTest(t *testing.T) *KubernetesManager {
+       logger, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#... - failed to initialize logger, error: %s", err)
+       }
+       config := &configuration.Configuration{}
+       config.Kubernetes.Namespace = "oran"
+       config.Kubernetes.ConfigPath = "somePath"
+
+       kubernetesManager := NewKubernetesManager(logger, config)
+
+       return kubernetesManager
+}
+
+func TestDelete_NoPodName(t *testing.T) {
+       test := TestStruct{
+               description: "2 namespace, 2 pods in oran",
+               namespace:   "oran",
+               objs:        []runtime.Object{pod("oran", "POD_Test_1"), pod("oran", "POD_Test_2"), pod("some-namespace", "POD_Test_1")},
+       }
+
+       kubernetesManager := initKubernetesManagerTest(t)
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := kubernetesManager.DeletePod("")
+               assert.NotNil(t, err)
+       })
+}
+
+func TestDelete_NoPods(t *testing.T) {
+       test := TestStruct{
+               description: "no pods",
+               namespace:   "oran",
+               expected:    nil,
+               objs:        nil,
+       }
+
+       kubernetesManager := initKubernetesManagerTest(t)
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := kubernetesManager.DeletePod("POD_Test")
+               assert.NotNil(t, err)
+       })
+}
+
+func TestDelete_PodExists(t *testing.T) {
+       test := TestStruct{
+               description: "2 namespace, 2 pods in oran",
+               namespace:   "oran",
+               objs:        []runtime.Object{pod("oran", "POD_Test_1"), pod("oran", "POD_Test_2"), pod("some-namespace", "POD_Test_1")},
+       }
+
+       kubernetesManager := initKubernetesManagerTest(t)
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := kubernetesManager.DeletePod("POD_Test_1")
+               assert.Nil(t, err)
+       })
+}
+
+func TestDelete_NoPodInNamespace(t *testing.T) {
+       test := TestStruct{
+               description: "2 namespace, 2 pods in oran",
+               namespace:   "oran",
+               objs:        []runtime.Object{pod("oran", "POD_Test_1"), pod("oran", "POD_Test_2"), pod("some-namespace", "POD_Test")},
+       }
+
+       kubernetesManager := initKubernetesManagerTest(t)
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := kubernetesManager.DeletePod("POD_Test")
+               assert.NotNil(t, err)
+       })
+}
+
+func TestDelete_NoNamespace(t *testing.T) {
+       test := TestStruct{
+               description: "No oran namespace",
+               namespace:   "oran",
+               objs:        []runtime.Object{pod("some-namespace", "POD_Test_1"), pod("some-namespace", "POD_Test_2"), pod("some-namespace", "POD_Test")},
+       }
+
+       kubernetesManager := initKubernetesManagerTest(t)
+
+       t.Run(test.description, func(t *testing.T) {
+               kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
+
+               err := kubernetesManager.DeletePod("POD_Test")
+               assert.NotNil(t, err)
+       })
+}
+
+func pod(namespace, image string) *v1.Pod {
+
+       return &v1.Pod{
+               ObjectMeta: metaV1.ObjectMeta{
+                       Name:        image,
+                       Namespace:   namespace,
+                       Annotations: map[string]string{},
+               },
+       }
+}
index 0c6cefe..c81137f 100644 (file)
@@ -35,8 +35,8 @@ func (m *E2TInstancesManagerMock) GetE2TInstance(e2tAddress string) (*entities.E
        return args.Get(0).(*entities.E2TInstance), args.Error(1)
 }
 
-func (m *E2TInstancesManagerMock) AddE2TInstance(e2tInstanceAddress string) error {
-       args := m.Called(e2tInstanceAddress)
+func (m *E2TInstancesManagerMock) AddE2TInstance(e2tInstanceAddress string, podName string) error {
+       args := m.Called(e2tInstanceAddress, podName)
        return args.Error(0)
 }
 
index 80b9a3a..a1b5616 100644 (file)
@@ -21,6 +21,7 @@
 package models
 
 type E2TermInitPayload struct {
-       Address string     `json:"address"`
-       Fqdn string     `json:"fqdn"`
-}
\ No newline at end of file
+       Address string `json:"address"`
+       Fqdn    string `json:"fqdn"`
+       PodName string `json:"pod_name"`
+}
index 6c8743e..d38d0fe 100644 (file)
@@ -495,7 +495,7 @@ func TestSaveE2TInstanceSuccess(t *testing.T) {
 func TestSaveE2TInstanceNullE2tInstanceFailure(t *testing.T) {
        w, _ := initSdlInstanceMock(namespace)
        var address string
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, "test")
        err := w.SaveE2TInstance(e2tInstance)
        assert.NotNil(t, err)
        assert.IsType(t, &common.ValidationError{}, err)
@@ -529,7 +529,7 @@ func TestSaveE2TInstanceSdlFailure(t *testing.T) {
 }
 
 func generateE2tInstance(address string) *entities.E2TInstance {
-       e2tInstance := entities.NewE2TInstance(address)
+       e2tInstance := entities.NewE2TInstance(address, "pod test")
 
        e2tInstance.AssociatedRanList = []string{"test1", "test2"}
 
index 20805eb..a7cfcd3 100644 (file)
@@ -18,3 +18,6 @@ e2tInstanceDeletionTimeoutMs: 15000
 globalRicId:
   plmnId: 131014
   ricNearRtId: 556670
+kubernetes:
+  configPath: ./kub_config.yml
+  namespace: ricplt
\ No newline at end of file
diff --git a/E2Manager/router_test.txt b/E2Manager/router_test.txt
deleted file mode 100644 (file)
index 2315519..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-newrt|start
-rte|1|127.0.0.1:3801
-newrt|end
index 935cfed..0fb2724 100644 (file)
@@ -211,7 +211,7 @@ func (w *rNibDataService) GetE2TAddressesNoLogs() ([]string, error) {
 }
 
 func (w *rNibDataService) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
-       w.logger.Infof("#RnibDataService.SaveE2TInstance - E2T instance address: %s, state: %s, associated RANs count: %d, keep Alive ts: %d", e2tInstance.Address, e2tInstance.State, len(e2tInstance.AssociatedRanList), e2tInstance.KeepAliveTimestamp)
+       w.logger.Infof("#RnibDataService.SaveE2TInstance - E2T instance address: %s, podName: %s, state: %s, associated RANs count: %d, keep Alive ts: %d", e2tInstance.Address, e2tInstance.PodName, e2tInstance.State, len(e2tInstance.AssociatedRanList), e2tInstance.KeepAliveTimestamp)
 
        return w.SaveE2TInstanceNoLogs(e2tInstance)
 }
index e5476f0..2b765a0 100644 (file)
@@ -24,28 +24,39 @@ openapi: 3.0.0
 info:
   title: E2 Manager Service
   description: E2 Manager Service APIs
-  version: 3.0.3
+  version: 4.0.0
 servers:
   - url: 'http://{apiRoot}/v1'
     variables:
       apiRoot:
         default: 'localhost:3800'
 paths:
-  /nodeb/x2-setup:
-    post:
-      summary: X2 Setup
+  '/nodeb/{ranName}':
+    put:
+      summary: Update GNB
       tags:
         - nodeb
-      operationId: x2Setup
+      operationId: UpdateGnb
+      parameters:
+        - name: ranName
+          in: path
+          required: true
+          description: Name of GNB RAN to update
+          schema:
+            type: string
       requestBody:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/SetupRequest'
+              $ref: '#/components/schemas/UpdateGnbRequest'
         required: true
       responses:
         '200':
-          description: Success
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UpdateGnbResponse'
         '400':
           description: Invalid input
           content:
@@ -58,34 +69,12 @@ paths:
             application/problem+json:
               schema:
                 $ref: '#/components/schemas/ErrorResponse'
-  /nodeb/endc-setup:
-    post:
-      tags:
-        - nodeb
-      summary: ENDC Setup
-      operationId: endcSetup
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/SetupRequest'
-        required: true
-      responses:
-        '200':
-          description: Success
-        '400':
-          description: Invalid input
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/ErrorResponse'
-        '500':
-          description: Internal Error
+        '503':
+          description: Routing Manager Unavailable
           content:
             application/problem+json:
               schema:
                 $ref: '#/components/schemas/ErrorResponse'
-  '/nodeb/{ranName}':
     get:
       tags:
         - nodeb
@@ -127,9 +116,14 @@ paths:
     put:
       tags:
         - nodeb
-      summary: >-
-        Close all connections to the RANs
+      summary: Close all connections to the RANs
       responses:
+        '200':
+          description: 'Operation succeeded internally, outbound calls failed'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RedButtonPartialSuccessResponseModel'
         '204':
           description: Successful operation
         '500':
@@ -159,48 +153,6 @@ paths:
             application/problem+json:
               schema:
                 $ref: '#/components/schemas/ErrorResponse'
-  /nodeb/{ranName}/reset:
-    put:
-      tags:
-        - nodeb
-      summary: >-
-        Upon receipt of this message, 'ranName' shall abort any other ongoing procedures over X2 between the RIC and the RAN. The RAN shall delete all the context information related to the RIC, except the application level configuration data exchanged during the X2 Setup or eNB Configuration Update procedures, and release the corresponding resource.  
-      operationId: reset
-      parameters:
-        - name: ranName
-          in: path
-          required: true
-          description: Name of RAN to return
-          schema:
-            type: string
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/ResetRequest'
-        required: false
-      responses:
-        '204':
-          description: Successful operation
-        '400':
-          description: Invalid input (invalid cause, RAN in wrong state)
-          content:
-            application/problem+json:
-              schema:
-                $ref: '#/components/schemas/ErrorResponse'
-        '404':
-          description: A RAN with the specified name was not found
-          content:
-            application/problem+json:
-              schema:
-                $ref: '#/components/schemas/ErrorResponse'
-        '500':
-          description: Internal Error
-          content:
-            application/problem+json:
-              schema:
-                $ref: '#/components/schemas/ErrorResponse'
-
   /health:
     get:
       tags:
@@ -231,92 +183,790 @@ paths:
                 $ref: '#/components/schemas/ErrorResponse'
 components:
   schemas:
-    SetupRequest:
+    UpdateGnbRequest:
       type: object
-      required:
-        - ranIp
-        - ranPort
-        - ranName
       properties:
-        ranIp:
+        gnb:
+          properties:
+            servedNrCells:
+              items:
+                properties:
+                  nrNeighbourInfos:
+                    items:
+                      properties:
+                        choiceNrMode:
+                          properties:
+                            fdd:
+                              properties:
+                                dlarFcnFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                                ularFcnFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                              additionalProperties: false
+                              type: object
+                            tdd:
+                              properties:
+                                arFcnNrFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                              additionalProperties: false
+                              type: object
+                          additionalProperties: false
+                          type: object
+                        configuredStac:
+                          type: string
+                        nrCgi:
+                          type: string
+                        nrMode:
+                          oneOf:
+                            - type: string
+                            - type: integer
+                        nrPci:
+                          type: integer
+                        stac5g:
+                          type: string
+                      additionalProperties: false
+                      type: object
+                    type: array
+                  servedNrCellInformation:
+                    properties:
+                      cellId:
+                        type: string
+                      choiceNrMode:
+                        properties:
+                          fdd:
+                            properties:
+                              dlFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              dlTransmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                              ulFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              ulTransmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                            additionalProperties: false
+                            type: object
+                          tdd:
+                            properties:
+                              nrFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              transmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                            additionalProperties: false
+                            type: object
+                        additionalProperties: false
+                        type: object
+                      configuredStac:
+                        type: string
+                      nrMode:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                      nrPci:
+                        type: integer
+                      servedPlmns:
+                        items:
+                          type: string
+                        type: array
+                      stac5g:
+                        type: string
+                    additionalProperties: false
+                    type: object
+                additionalProperties: false
+                type: object
+              type: array
+            ranFunctions:
+              items:
+                properties:
+                  ranFunctionId:
+                    type: integer
+                  ranFunctionDefinition:
+                    type: string
+                  ranFunctionRevision:
+                    type: integer
+                additionalProperties: false
+                type: object
+              type: array
+          additionalProperties: false
+          type: object
+      additionalProperties: false
+    UpdateGnbResponse:
+      properties:
+        connectionStatus:
+          oneOf:
+            - type: string
+            - type: integer
+        failureType:
+          oneOf:
+            - type: string
+            - type: integer
+        globalNbId:
+          properties:
+            nbId:
+              type: string
+            plmnId:
+              type: string
+          additionalProperties: false
+          type: object
+        gnb:
+          properties:
+            servedNrCells:
+              items:
+                properties:
+                  nrNeighbourInfos:
+                    items:
+                      properties:
+                        choiceNrMode:
+                          properties:
+                            fdd:
+                              properties:
+                                dlarFcnFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                                ularFcnFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                              additionalProperties: false
+                              type: object
+                            tdd:
+                              properties:
+                                arFcnNrFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                              additionalProperties: false
+                              type: object
+                          additionalProperties: false
+                          type: object
+                        configuredStac:
+                          type: string
+                        nrCgi:
+                          type: string
+                        nrMode:
+                          oneOf:
+                            - type: string
+                            - type: integer
+                        nrPci:
+                          type: integer
+                        stac5g:
+                          type: string
+                      additionalProperties: false
+                      type: object
+                    type: array
+                  servedNrCellInformation:
+                    properties:
+                      cellId:
+                        type: string
+                      choiceNrMode:
+                        properties:
+                          fdd:
+                            properties:
+                              dlFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              dlTransmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                              ulFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              ulTransmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                            additionalProperties: false
+                            type: object
+                          tdd:
+                            properties:
+                              nrFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              transmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                            additionalProperties: false
+                            type: object
+                        additionalProperties: false
+                        type: object
+                      configuredStac:
+                        type: string
+                      nrMode:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                      nrPci:
+                        type: integer
+                      servedPlmns:
+                        items:
+                          type: string
+                        type: array
+                      stac5g:
+                        type: string
+                    additionalProperties: false
+                    type: object
+                additionalProperties: false
+                type: object
+              type: array
+            ranFunctions:
+              items:
+                properties:
+                  ranFunctionId:
+                    type: integer
+                  ranFunctionDefinition:
+                    type: string
+                  ranFunctionRevision:
+                    type: integer
+                additionalProperties: false
+                type: object
+              type: array
+          additionalProperties: false
+          type: object
+        ip:
           type: string
-        ranPort:
+        nodeType:
+          oneOf:
+            - type: string
+            - type: integer
+        port:
           type: integer
-          format: uint16
         ranName:
           type: string
-    ResetRequest:
+        setupFailure:
+          properties:
+            criticalityDiagnostics:
+              properties:
+                informationElementCriticalityDiagnostics:
+                  items:
+                    properties:
+                      ieCriticality:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                      ieId:
+                        type: integer
+                      typeOfError:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                    additionalProperties: false
+                    type: object
+                  type: array
+                procedureCode:
+                  type: integer
+                procedureCriticality:
+                  oneOf:
+                    - type: string
+                    - type: integer
+                triggeringMessage:
+                  oneOf:
+                    - type: string
+                    - type: integer
+              additionalProperties: false
+              type: object
+            miscellaneousCause:
+              oneOf:
+                - type: string
+                - type: integer
+            networkLayerCause:
+              oneOf:
+                - type: string
+                - type: integer
+            protocolCause:
+              oneOf:
+                - type: string
+                - type: integer
+            timeToWait:
+              oneOf:
+                - type: string
+                - type: integer
+            transportLayerCause:
+              oneOf:
+                - type: string
+                - type: integer
+          additionalProperties: false
+          type: object
+      additionalProperties: false
       type: object
-      required:
-        - cause
-      properties:
-        cause:
-          type: string
-          enum: [misc:control-processing-overload,
-misc:hardware-failure,
-misc:om-intervention,
-misc:not-enough-user-plane-processing-resources,
-misc:unspecified,
-protocol:transfer-syntax-error,
-protocol:abstract-syntax-error-reject,
-protocol:abstract-syntax-error-ignore-and-notify,
-protocol:message-not-compatible-with-receiver-state,
-protocol:semantic-error,
-protocol:unspecified,
-protocol:abstract-syntax-error-falsely-constructed-message,
-transport:transport-resource-unavailable,
-transport:unspecified,
-radioNetwork:handover-desirable-for-radio-reasons,
-radioNetwork:time-critical-handover,
-radioNetwork:resource-optimisation-handover,
-radioNetwork:reduce-load-in-serving-cell,
-radioNetwork:partial-handover,
-radioNetwork:unknown-new-eNB-UE-X2AP-ID, 
-radioNetwork:unknown-old-eNB-UE-X2AP-ID, 
-radioNetwork:unknown-pair-of-UE-X2AP-ID,
-radioNetwork:ho-target-not-allowed,
-radioNetwork:tx2relocoverall-expiry,
-radioNetwork:trelocprep-expiry,
-radioNetwork:cell-not-available,
-radioNetwork:no-radio-resources-available-in-target-cell,
-radioNetwork:invalid-MME-GroupID,
-radioNetwork:unknown-MME-Code,
-radioNetwork:encryption-and-or-integrity-protection-algorithms-not-supported,
-radioNetwork:reportCharacteristicsEmpty,
-radioNetwork:noReportPeriodicity,
-radioNetwork:existingMeasurementID,
-radioNetwork:unknown-eNB-Measurement-ID,
-radioNetwork:measurement-temporarily-not-available,
-radioNetwork:unspecified,
-radioNetwork:load-balancing,
-radioNetwork:handover-optimisation,
-radioNetwork:value-out-of-allowed-range,
-radioNetwork:multiple-E-RAB-ID-instances,
-radioNetwork:switch-off-ongoing,
-radioNetwork:not-supported-QCI-value,
-radioNetwork:measurement-not-supported-for-the-object,
-radioNetwork:tDCoverall-expiry,
-radioNetwork:tDCprep-expiry,
-radioNetwork:action-desirable-for-radio-reasons,
-radioNetwork:reduce-load,
-radioNetwork:resource-optimisation,
-radioNetwork:time-critical-action,
-radioNetwork:target-not-allowed,
-radioNetwork:no-radio-resources-available,
-radioNetwork:invalid-QoS-combination,
-radioNetwork:encryption-algorithms-not-aupported,
-radioNetwork:procedure-cancelled,
-radioNetwork:rRM-purpose,
-radioNetwork:improve-user-bit-rate,
-radioNetwork:user-inactivity,
-radioNetwork:radio-connection-with-UE-lost,
-radioNetwork:failure-in-the-radio-interface-procedure,
-radioNetwork:bearer-option-not-supported,
-radioNetwork:mCG-Mobility,
-radioNetwork:sCG-Mobility,
-radioNetwork:count-reaches-max-value,
-radioNetwork:unknown-old-en-gNB-UE-X2AP-ID,
-radioNetwork:pDCP-Overload]
     NodebIdentity:
       properties:
         globalNbId:
@@ -863,6 +1513,18 @@ radioNetwork:pDCP-Overload]
                 additionalProperties: false
                 type: object
               type: array
+            ranFunctions:
+              items:
+                properties:
+                  ranFunctionId:
+                    type: integer
+                  ranFunctionDefinition:
+                    type: string
+                  ranFunctionRevision:
+                    type: integer
+                additionalProperties: false
+                type: object
+              type: array
           additionalProperties: false
           type: object
         ip:
@@ -939,10 +1601,21 @@ radioNetwork:pDCP-Overload]
       properties:
         errorCode:
           type: string
-          description: '401 - corrupted json, 402 - validation error, 403 - RAN in wrong state, 404 - resource not found, 500 - RNIB error, 501 - internal problem, 502 - RMR error'
+          description: >-
+            401 - corrupted json, 402 - validation error, 403 - RAN in wrong
+            state, 404 - resource not found, 500 - RNIB error, 501 - internal
+            problem, 502 - RMR error, 503 - Routing Manager Unavailable
         errorMessage:
           type: string
           description: Human readable text
+    RedButtonPartialSuccessResponseModel:
+      type: object
+      required:
+        - message
+      properties:
+        message:
+          type: string
+          description: Partial success reason
     E2tIdentity:
       type: object
       required:
@@ -966,4 +1639,4 @@ radioNetwork:pDCP-Overload]
           description: '500 - RNIB error, 501 - internal problem'
         errorMessage:
           type: string
-          description: Human readable text
\ No newline at end of file
+          description: Human readable text
diff --git a/tools/KubernetesSimulator/Dockerfile b/tools/KubernetesSimulator/Dockerfile
new file mode 100644 (file)
index 0000000..0d5073b
--- /dev/null
@@ -0,0 +1,33 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:2-u16.04-nng as ubuntu
+
+WORKDIR /opt/kubsimulator
+COPY . . 
+ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
+
+RUN go build main.go
+
+
+FROM ubuntu:16.04
+COPY --from=ubuntu /opt/kubsimulator/main /opt/kubsimulator/main
+COPY --from=ubuntu /opt/kubsimulator/resources /opt/kubsimulator/resources
+
+WORKDIR /opt/kubsimulator
+CMD exec ./main
diff --git a/tools/KubernetesSimulator/api/swagger.yaml b/tools/KubernetesSimulator/api/swagger.yaml
new file mode 100755 (executable)
index 0000000..2af6699
--- /dev/null
@@ -0,0 +1,54 @@
+# ========================LICENSE_START=================================
+# O-RAN-SC
+#
+# Copyright (C) 2019 AT&T Intellectual Property and Nokia
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ========================LICENSE_END===================================
+
+# This source code is part of the near-RT RIC (RAN Intelligent Controller)
+# platform project (RICP).
+
+
+openapi: 3.0.0
+info:
+  title: Kubernetes Simulator
+  description: Kubernetes Simulator APIs
+  version: 0.0.1
+servers:
+  - url: 'http://{apiRoot}/api/v1'
+    variables:
+      apiRoot:
+        default: 'localhost:59009'
+paths:
+  '/namespaces/{namespace}/pods/{pod}':
+    delete:
+      summary: Delete Pod
+      tags:
+        - Delete Pod
+      operationId: DeletePod
+      parameters:
+        - name: namespace
+          in: path
+          required: true
+          schema:
+            type: string
+        - name: pod
+          in: path
+          required: true
+          description: pod to delete
+          schema:
+            type: string
+      responses:
+        '200':
+          description: Successful operation
diff --git a/tools/KubernetesSimulator/configuration/configuration.go b/tools/KubernetesSimulator/configuration/configuration.go
new file mode 100644 (file)
index 0000000..ffb8913
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package configuration
+
+import (
+       "fmt"
+       "github.com/spf13/viper"
+)
+
+type Configuration struct {
+       Http struct {
+               Port int
+       }
+
+}
+
+func ParseConfiguration() *Configuration{
+       viper.SetConfigType("yaml")
+       viper.SetConfigName("configuration")
+       viper.AddConfigPath("KubernetesSimulator/resources/")
+       viper.AddConfigPath("./resources/")  //For production
+       viper.AddConfigPath("../resources/") //For test under Docker
+       viper.AddConfigPath("../../resources/") //For test under Docker
+       err := viper.ReadInConfig()
+       if err != nil {
+               panic(fmt.Sprintf("#configuration.ParseConfiguration - failed to read configuration file: %s\n", err))
+       }
+
+       config := Configuration{}
+       config.fillHttpConfig(viper.Sub("http"))
+       return &config
+}
+
+func (c *Configuration)fillHttpConfig(httpConfig *viper.Viper) {
+       if httpConfig == nil {
+               panic(fmt.Sprintf("#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n"))
+       }
+       c.Http.Port = httpConfig.GetInt("port")
+}
diff --git a/tools/KubernetesSimulator/configuration/configuration_test.go b/tools/KubernetesSimulator/configuration/configuration_test.go
new file mode 100644 (file)
index 0000000..8510699
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package configuration
+
+import (
+       "github.com/stretchr/testify/assert"
+       "gopkg.in/yaml.v2"
+       "io/ioutil"
+       "os"
+       "testing"
+)
+
+func TestParseConfigurationSuccess(t *testing.T) {
+       config := ParseConfiguration()
+       assert.Equal(t, 59009, config.Http.Port)
+}
+
+func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       assert.Panics(t, func() { ParseConfiguration() })
+}
+
+func TestHttpConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{}
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n",
+               func() { ParseConfiguration() })
+}
diff --git a/tools/KubernetesSimulator/go.mod b/tools/KubernetesSimulator/go.mod
new file mode 100644 (file)
index 0000000..5bfe420
--- /dev/null
@@ -0,0 +1,13 @@
+module kubsimulator
+
+go 1.12
+
+require (
+       github.com/gorilla/mux v1.7.0
+       github.com/pkg/errors v0.8.1
+       github.com/spf13/viper v1.6.1
+       github.com/stretchr/testify v1.4.0
+       go.uber.org/atomic v1.5.0
+       go.uber.org/zap v1.13.0
+       gopkg.in/yaml.v2 v2.2.4
+)
diff --git a/tools/KubernetesSimulator/go.sum b/tools/KubernetesSimulator/go.sum
new file mode 100644 (file)
index 0000000..0d7ed5a
--- /dev/null
@@ -0,0 +1,174 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
+github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk=
+github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
+github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
+gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/tools/KubernetesSimulator/go/controller.go b/tools/KubernetesSimulator/go/controller.go
new file mode 100755 (executable)
index 0000000..212b5c3
--- /dev/null
@@ -0,0 +1,30 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package kubernetes
+
+import (
+       "net/http"
+)
+
+func DeletePod(writer http.ResponseWriter, r *http.Request) {
+       writer.Header().Set("Content-Type", "application/json; charset=UTF-8")
+       writer.WriteHeader(http.StatusOK)
+}
\ No newline at end of file
diff --git a/tools/KubernetesSimulator/go/logger.go b/tools/KubernetesSimulator/go/logger.go
new file mode 100755 (executable)
index 0000000..898e021
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package kubernetes
+
+import (
+       "bytes"
+       "encoding/json"
+       "io/ioutil"
+       "log"
+       "net/http"
+       "time"
+)
+
+func Logger(inner http.Handler, name string) http.Handler {
+       return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               start := time.Now()
+
+               inner.ServeHTTP(w, r)
+
+               body, err := ioutil.ReadAll(r.Body)
+               if err != nil {
+                       log.Printf("Error reading body: %v", err)
+                       http.Error(w, "can't read body", http.StatusBadRequest)
+                       return
+               }
+
+               buffer := new(bytes.Buffer)
+               _ =json.Compact(buffer, body)
+
+               log.Printf(
+                       "%s %s  body: %s elapsed: %s",
+                       r.Method,
+                       r.RequestURI,
+                       buffer,
+                       time.Since(start),
+               )
+       })
+}
diff --git a/tools/KubernetesSimulator/go/request.go b/tools/KubernetesSimulator/go/request.go
new file mode 100755 (executable)
index 0000000..d123a5d
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package kubernetes
+
+type Request struct {
+
+       Kind string `json:"kind"`
+
+       ApiVersion string `json:"apiVersion"`
+}
diff --git a/tools/KubernetesSimulator/go/routers.go b/tools/KubernetesSimulator/go/routers.go
new file mode 100755 (executable)
index 0000000..16b2d5a
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package kubernetes
+
+import (
+       //"fmt"
+       "net/http"
+       "strings"
+
+       "github.com/gorilla/mux"
+)
+
+type Route struct {
+       Name        string
+       Method      string
+       Pattern     string
+       HandlerFunc http.HandlerFunc
+}
+
+type Routes []Route
+
+func NewRouter() *mux.Router {
+       router := mux.NewRouter().StrictSlash(true)
+       for _, route := range routes {
+               var handler http.Handler
+               handler = route.HandlerFunc
+               handler = Logger(handler, route.Name)
+
+               router.
+                       Methods(route.Method).
+                       Path(route.Pattern).
+                       Name(route.Name).
+                       Handler(handler)
+       }
+
+       return router
+}
+
+var routes = Routes{
+       Route{
+               "DeletePod",
+               strings.ToUpper("Delete"),
+               "/api/v1/namespaces/{namespace}/pods/{pod}",
+               DeletePod,
+       },
+}
diff --git a/tools/KubernetesSimulator/main.go b/tools/KubernetesSimulator/main.go
new file mode 100755 (executable)
index 0000000..9ea5f23
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package main
+
+import (
+       "fmt"
+       "kubsimulator/configuration"
+       "kubsimulator/go"
+       "log"
+       "net/http"
+)
+
+func main() {
+       config := configuration.ParseConfiguration()
+       port := config.Http.Port
+
+       log.Printf("Server started on port %d", port)
+
+       router := kubernetes.NewRouter()
+
+       log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), router))
+}
diff --git a/tools/KubernetesSimulator/resources/configuration.yaml b/tools/KubernetesSimulator/resources/configuration.yaml
new file mode 100644 (file)
index 0000000..f794b0c
--- /dev/null
@@ -0,0 +1,2 @@
+http:
+  port: 59009
index 2510d78..505edbb 100755 (executable)
@@ -1,4 +1,25 @@
----
+# ========================LICENSE_START=================================
+# O-RAN-SC
+#
+# Copyright (C) 2019 AT&T Intellectual Property and Nokia
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ========================LICENSE_END===================================
+
+# This source code is part of the near-RT RIC (RAN Intelligent Controller)
+# platform project (RICP).
+
+
 swagger: "2.0"
 info:
   description: "This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound\