<commit_before>package etcdstore

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	//	"time"

	log "github.com/Sirupsen/logrus"
	etcdclient "github.com/coreos/etcd/client"
	engineapi "github.com/docker/docker/client"
	"github.com/docker/go-connections/tlsconfig"
	"gitlab.ricebook.net/platform/core/types"
	"gitlab.ricebook.net/platform/core/utils"
	"golang.org/x/net/context"
)

const GIGABYTE = 1073741824

// cache connections
// otherwise they'll leak
type cache struct {
	sync.Mutex
	clients map[string]*engineapi.Client
}

func (c *cache) set(host string, client *engineapi.Client) {
	c.Lock()
	defer c.Unlock()

	c.clients[host] = client
}

func (c *cache) get(host string) *engineapi.Client {
	c.Lock()
	defer c.Unlock()
	return c.clients[host]
}

func (c *cache) delete(host string) {
	c.Lock()
	defer c.Unlock()
	delete(c.clients, host)
}

var _cache = &cache{clients: make(map[string]*engineapi.Client)}

// get a node from etcd
// and construct it's docker client
// a node must belong to a pod
// and since node is not the smallest unit to user, to get a node we must specify the corresponding pod
// storage path in etcd is `/eru-core/pod/:podname/node/:nodename/info`
func (k *krypton) GetNode(podname, nodename string) (*types.Node, error) {
	key := fmt.Sprintf(nodeInfoKey, podname, nodename)
	resp, err := k.etcd.Get(context.Background(), key, nil)
	if err != nil {
		return nil, err
	}
	if resp.Node.Dir {
		return nil, fmt.Errorf("Node storage path %q in etcd is a directory", key)
	}

	node := &types.Node{}
	if err := json.Unmarshal([]byte(resp.Node.Value), node); err != nil {
		return nil, err
	}

	engine, err := k.makeDockerClient(podname, nodename, node.Endpoint, false)
	if err != nil {
		return nil, err
	}

	node.Engine = engine
	return node, nil
}

// add a node
// save it to etcd
// storage path in etcd is `/eru-core/pod/:podname/node/:nodename/info`
func (k *krypton) AddNode(name, endpoint, podname, cafile, certfile, keyfile string, public bool) (*types.Node, error) {
	if !strings.HasPrefix(endpoint, "tcp://") {
		return nil, fmt.Errorf("Endpoint must starts with tcp:// %q", endpoint)
	}

	_, err := k.GetPod(podname)
	if err != nil {
		return nil, err
	}

	key := fmt.Sprintf(nodeInfoKey, podname, name)
	if _, err := k.etcd.Get(context.Background(), key, nil); err == nil {
		return nil, fmt.Errorf("Node (%s, %s) already exists", podname, name)
	}

	// 如果有tls的证书需要保存就保存一下
	if cafile != "" && certfile != "" && keyfile != "" {
		_, err = k.etcd.Set(context.Background(), fmt.Sprintf(nodeCaKey, podname, name), cafile, nil)
		if err != nil {
			return nil, err
		}
		_, err = k.etcd.Set(context.Background(), fmt.Sprintf(nodeCertKey, podname, name), certfile, nil)
		if err != nil {
			return nil, err<commit_msg>[skip ci] 注册 node 的时候允许覆盖<commit_after>package etcdstore

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	//	"time"

	log "github.com/Sirupsen/logrus"
	etcdclient "github.com/coreos/etcd/client"
	engineapi "github.com/docker/docker/client"
	"github.com/docker/go-connections/tlsconfig"
	"gitlab.ricebook.net/platform/core/types"
	"gitlab.ricebook.net/platform/core/utils"
	"golang.org/x/net/context"
)

const GIGABYTE = 1073741824

// cache connections
// otherwise they'll leak
type cache struct {
	sync.Mutex
	clients map[string]*engineapi.Client
}

func (c *cache) set(host string, client *engineapi.Client) {
	c.Lock()
	defer c.Unlock()

	c.clients[host] = client
}

func (c *cache) get(host string) *engineapi.Client {
	c.Lock()
	defer c.Unlock()
	return c.clients[host]
}

func (c *cache) delete(host string) {
	c.Lock()
	defer c.Unlock()
	delete(c.clients, host)
}

var _cache = &cache{clients: make(map[string]*engineapi.Client)}

// get a node from etcd
// and construct it's docker client
// a node must belong to a pod
// and since node is not the smallest unit to user, to get a node we must specify the corresponding pod
// storage path in etcd is `/eru-core/pod/:podname/node/:nodename/info`
func (k *krypton) GetNode(podname, nodename string) (*types.Node, error) {
	key := fmt.Sprintf(nodeInfoKey, podname, nodename)
	resp, err := k.etcd.Get(context.Background(), key, nil)
	if err != nil {
		return nil, err
	}
	if resp.Node.Dir {
		return nil, fmt.Errorf("Node storage path %q in etcd is a directory", key)
	}

	node := &types.Node{}
	if err := json.Unmarshal([]byte(resp.Node.Value), node); err != nil {
		return nil, err
	}

	engine, err := k.makeDockerClient(podname, nodename, node.Endpoint, false)
	if err != nil {
		return nil, err
	}

	node.Engine = engine
	return node, nil
}

// add a node
// save it to etcd
// storage path in etcd is `/eru-core/pod/:podname/node/:nodename/info`
func (k *krypton) AddNode(name, endpoint, podname, cafile, certfile, keyfile string, public bool) (*types.Node, error) {
	if !strings.HasPrefix(endpoint, "tcp://") {
		return nil, fmt.Errorf("Endpoint must starts with tcp:// %q", endpoint)
	}

	_, err := k.GetPod(podname)
	if err != nil {
		return nil, err
	}

	key := fmt.Sprintf(nodeInfoKey, podname, name)

	// 如果有tls的证书需要保存就保存一下
	if cafile != "" && certfile != "" && keyfile != "" {
		_, err = k.etcd.Set(context.Background(), fmt.Sprintf(nodeCaKey, podname, name), cafile, nil)
		if err != nil {
			return nil, err
		}
		_, err = k.etcd.Set(context.Background(), fmt.Sprintf(nodeCertKey, podname, name), certfile, nil)
		if err != nil {
			return nil, err
{'fraction_non_alphanumeric': 0.15353901996370237, 'fraction_numerical': 0.003629764065335753, 'mean_word_length': 3.868374558303887, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2713239', 'n_tokens_mistral': 2127, 'n_tokens_neox': 2058, 'n_words': 549}