From d6b4c825bcafccb2495566332090778ef922b634 Mon Sep 17 00:00:00 2001 From: Kiran Kamineni Date: Fri, 23 Aug 2019 12:33:06 -0700 Subject: Add a namegenerator package Adds a namegenerator package which generates readable names for instances. This will go with a small change in the API where we expect instance names and will generate the names if they are not provided. Issue-ID: MULTICLOUD-716 Change-Id: I69d8b7fb62667b8b60f3e02eb26dc937961d26d2 Signed-off-by: Kiran Kamineni --- src/k8splugin/go.mod | 3 +- src/k8splugin/go.sum | 5 + src/k8splugin/internal/app/instance.go | 13 +- .../internal/namegenerator/namegenerator.go | 148 +++++++++++++++++++++ 4 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 src/k8splugin/internal/namegenerator/namegenerator.go (limited to 'src/k8splugin') diff --git a/src/k8splugin/go.mod b/src/k8splugin/go.mod index f75588b6..cc9496a8 100644 --- a/src/k8splugin/go.mod +++ b/src/k8splugin/go.mod @@ -11,7 +11,7 @@ require ( github.com/coreos/etcd v3.3.12+incompatible // indirect github.com/cyphar/filepath-securejoin v0.2.2 // indirect github.com/docker/distribution v2.7.0+incompatible // indirect - github.com/docker/docker v0.7.3-0.20190312165151-258edd715d46 // indirect + github.com/docker/docker v1.13.1 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.3.3 // indirect github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect @@ -50,6 +50,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/moby/moby v1.13.1 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v0.0.0-20180228065516-1df9eeb2bb81 // indirect github.com/mongodb/mongo-go-driver v1.0.0 diff --git a/src/k8splugin/go.sum b/src/k8splugin/go.sum index 0047e332..9fb9af2c 100644 --- a/src/k8splugin/go.sum +++ b/src/k8splugin/go.sum @@ -29,6 +29,8 @@ github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtf github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190312165151-258edd715d46 h1:nxT2VWYpy5So0xPokgtf+AMyNaU2Cvb1JU1A2anxNww= github.com/docker/docker v0.7.3-0.20190312165151-258edd715d46/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= +github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= @@ -116,11 +118,14 @@ github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9 github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/moby v1.13.1 h1:mC5WwQwCXt/dYxZ1cIrRsnJAWw7VdtcTZUIGr4tXzOM= +github.com/moby/moby v1.13.1/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= 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-20180228065516-1df9eeb2bb81 h1:ImOHKpmdLPXWX5KSYquUWXKaopEPuY7TPPUo18u9aOI= github.com/modern-go/reflect2 v0.0.0-20180228065516-1df9eeb2bb81/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mongodb/mongo-go-driver v1.0.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU= +github.com/onap/multicloud-k8s v0.0.0-20190808131943-845cdd2aa5d7 h1:bv8KHubfyTjUB6/z8idoCholYktjSUmzjXQxjx5H0wQ= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= diff --git a/src/k8splugin/internal/app/instance.go b/src/k8splugin/internal/app/instance.go index cf96d50c..47cea972 100644 --- a/src/k8splugin/internal/app/instance.go +++ b/src/k8splugin/internal/app/instance.go @@ -17,13 +17,12 @@ package app import ( - "encoding/base64" "encoding/json" "log" - "math/rand" "github.com/onap/multicloud-k8s/src/k8splugin/internal/db" "github.com/onap/multicloud-k8s/src/k8splugin/internal/helm" + "github.com/onap/multicloud-k8s/src/k8splugin/internal/namegenerator" "github.com/onap/multicloud-k8s/src/k8splugin/internal/rb" pkgerrors "github.com/pkg/errors" @@ -88,13 +87,6 @@ type InstanceClient struct { tagInst string } -// Using 6 bytes of randomness to generate an 8 character string -func generateInstanceID() string { - b := make([]byte, 6) - rand.Read(b) - return base64.URLEncoding.EncodeToString(b) -} - // NewInstanceClient returns an instance of the InstanceClient // which implements the InstanceManager func NewInstanceClient() *InstanceClient { @@ -127,7 +119,8 @@ func (v *InstanceClient) Create(i InstanceRequest) (InstanceResponse, error) { return InstanceResponse{}, pkgerrors.Wrap(err, "Error resolving helm charts") } - id := generateInstanceID() + // TODO: Only generate if id is not provided + id := namegenerator.Generate() k8sClient := KubernetesClient{} err = k8sClient.init(i.CloudRegion, id) diff --git a/src/k8splugin/internal/namegenerator/namegenerator.go b/src/k8splugin/internal/namegenerator/namegenerator.go new file mode 100644 index 00000000..1980944f --- /dev/null +++ b/src/k8splugin/internal/namegenerator/namegenerator.go @@ -0,0 +1,148 @@ +/* + * Copyright 2019 Intel Corporation, Inc + * + * 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. + */ + +package namegenerator + +import ( + "encoding/json" + "log" + "strings" + "sync" + + "github.com/onap/multicloud-k8s/src/k8splugin/internal/db" + + "github.com/moby/moby/pkg/namesgenerator" + pkgerrors "github.com/pkg/errors" +) + +const ( + storeName = "instanceNames" + tag = "names" +) + +var ( + nameCache = &cache{} + cacheKeyGlobal = cacheKey{"k8sPluginCacheKey"} +) + +type cache struct { + cache map[string]bool + mux sync.Mutex +} + +type cacheKey struct { + Key string `json:"key"` +} + +func (c cacheKey) String() string { + + out, err := json.Marshal(c) + if err != nil { + return "" + } + + return string(out) +} + +func (c *cache) init() { + + // We have either restarted or this is the first time + // that a name is being requested since the service came + // up. + if c.cache == nil { + c.cache = make(map[string]bool) + err := c.readCacheFromDB() + if err != nil { + log.Println("Error Reading from DB: ", err.Error()) + return + } + } +} + +func (c *cache) isAlreadyUsed(name string) bool { + + if _, ok := c.cache[name]; ok { + return true + } + return false +} + +func (c *cache) readCacheFromDB() error { + + // Read the latest from cache + data, err := db.DBconn.Read(storeName, cacheKeyGlobal, tag) + if err != nil { + log.Println("Error reading name cache from Database: ", err) + return pkgerrors.Wrap(err, "Reading cache from DB") + } + + err = db.DBconn.Unmarshal(data, &c.cache) + if err != nil { + log.Println("Error unmarshaling data into cache: ", err) + return pkgerrors.Wrap(err, "Unmarshaling cache from DB") + } + + return nil +} + +// writeCacheToDB will update the DB with the updated cache +func (c *cache) writeCacheToDB() { + + //Update the database as well + err := db.DBconn.Update(storeName, cacheKeyGlobal, tag, c.cache) + if err != nil { + // TODO: Replace with DBconn variable + if strings.Contains(err.Error(), "Error finding master table") { + err = db.DBconn.Create(storeName, cacheKeyGlobal, tag, c.cache) + if err != nil { + log.Println("Error creating the entry in DB. Will try later...") + return + } + } else { + log.Println("Error updating DB: ", err.Error()) + return + } + } +} + +func (c *cache) generateName() string { + c.mux.Lock() + defer c.mux.Unlock() + + c.init() + + for { + //Call moby package here to generate name + name := namesgenerator.GetRandomName(0) + if c.isAlreadyUsed(name) { + // Generate another name + log.Printf("Name %s already used", name) + continue + } + + c.cache[name] = true + + // Update the cache and db + c.writeCacheToDB() + return name + } +} + +// Generate returns an autogenerated name +func Generate() string { + + return nameCache.generateName() +} -- cgit 1.2.3-korg