<commit_before>package connector

import (
	"fmt"
	"net"
	"os"
	"path"

	"time"

	"strings"

	humanize "github.com/dustin/go-humanize"
	"github.com/ellcrys/crypto"
	"github.com/ellcrys/util"
	"github.com/goware/urlx"
	"github.com/kr/pretty"
	cutil "github.com/ncodes/cocoon-util"
	"github.com/ncodes/cocoon/core/api/api"
	"github.com/ncodes/cocoon/core/config"
	"github.com/ncodes/cocoon/core/connector/monitor"
	"github.com/ncodes/cocoon/core/connector/router"
	"github.com/ncodes/cocoon/core/orderer/orderer"
	"github.com/ncodes/cocoon/core/platform"
	"github.com/ncodes/cocoon/core/types"
	docker "github.com/ncodes/go-dockerclient"
	logging "github.com/op/go-logging"
	context "golang.org/x/net/context"
)

var log *logging.Logger
var buildLog *logging.Logger
var runLog *logging.Logger
var configLog *logging.Logger
var ccodeLog *logging.Logger
var fetchLog *logging.Logger
var logHealthChecker *logging.Logger
var dckClient *docker.Client

var bridgeName = os.Getenv("BRIDGE_NAME")

func init() {
}

// Connector defines a structure for starting and managing a cocoon (coode)
type Connector struct {
	waitCh            chan bool
	req               *Request
	connectorRPCAddr  string
	cocoonCodeRPCAddr string
	languages         []Language
	container         *docker.APIContainers
	containerRunning  bool
	routerHelper      *router.Helper
	monitor           *monitor.Monitor
	healthCheck       *HealthChecker
	ordererDiscovery  *orderer.Discovery
	cocoon            *types.Cocoon
	release           *types.Release
	Platform          *platform.Transactions
}

// NewConnector creates a new connector
func NewConnector(req *Request, waitCh chan bool) (*Connector, error) {
	ordererDiscovery, err := orderer.NewDiscovery()
	if err != nil {
		return nil, err
	}
	platform, err := platform.NewTransactions()
	if err != nil {
		return nil, err
	}
	return &Connector{
		req:              req,
		waitCh:           waitCh,
		monitor:          monitor.NewMonitor(req.ID),
		ordererDiscovery: ordererDiscovery,
		Platform:         platform,
	}, nil
}

// Launch starts a cocoon code
func (cn *Connector) Launch(connectorRPCAddr, cocoonCodeRPCAddr string) {

	log = config.MakeLogger("connector", fmt.Sprintf("cocoon.%s", cn.req.ID))
	buildLog = config.MakeLogger("ccode.build", fmt.Sprintf("cocoon.%s", cn.req.ID))
	runLog = config.MakeLoggerMessageOnly("ccode.run", fmt.Sprintf("cocoon.%s", cn.req.ID))
	configLog = config.MakeLogger("ccode.config", fmt.Sprintf("cocoon.%s", cn.req.ID))
	ccodeLog = config.MakeLogger("ccode.main", fmt.Sprintf("cocoon.%s", cn.req.ID))
	fetchLog = config.MakeLogger("ccode.fetch", fmt.Sprintf("cocoon.%s", cn.req.ID))
	logHealthChecker = config.MakeLogger("connector.health_checker", fmt.Sprintf("cocoon.%s", cn.req.ID))

	endpoint := "unix:///var/run/docker.sock"
	client, err := docker.NewClient(endpoint)
	if err != nil {
		log.Errorf("failed to create docker client. Is dockerd running locally?. %s", err)
		cn.Stop(true)
		return
	}

	dckClient = client
	cn.monitor.SetDockerClient(dckClient)
	cn.healthCheck = NewHealthChecker(cn.cocoonCodeRPCAddr, cn.cocoonUnresponsive)
	go cn.ordererDiscovery.Discover()

	// No need downloading, building and starting a cocoon code
	// if DEV_ADDR_COCOON_CODE_RPC has been specified. This means a dev cocoon code
	// is running at that address.
	if devCocoonCodeRPCAddr := os.Getenv("DEV_ADDR_COCOON_CODE_RPC"); len(devCocoonCodeRPCAddr) > 0 {
		cn.cocoonCodeRPCAddr = devCocoonCodeRPCAddr
		log.Infof("[Dev] Will interact with cocoon code at %s", devCocoonCodeRPCAddr)
		cn.healthCheck.Start()
		fmt.Println("failed")
		return
	}

	log.Info("Ready to install cocoon code")
	log.Debugf("Found ccode url=%s and lang=%s", cn.req.URL, cn.req.Lang)

	lang := cn.GetLanguage(cn.req.Lang)
	if lang == nil {
		log.Errorf("cocoon code language (%s) not supported", cn.req.Lang)
		cn.Stop(true)
		return
	}

	cocoonCodeContainer, err := cn.prepareContainer(lang)
	if err != nil {
		log.Error(err.Error())
		cn.Stop(true)
		return
	}

	ctx, cc := context.WithTimeout(context.Background(), 1*time.Minute)
	defer cc()
	cn.cocoon, cn.release, err = cn.Platform.GetCocoonAndLastRelease(ctx, cn.req.ID, true, false)
	if err != nil {
		log.Errorf("Failed to fetch cocoon [%s] information", cn.req.ID)
		return
	}

	log.Info("Preparing cocoon code environment variables")

	var env = map[string]string{
		"COCOON_ID":           cn.req.ID,
		"CONNECTOR_RPC_ADDR":  cn.connectorRPCAddr,
		"COCOON_RPC_ADDR":     cn.cocoonCodeRPCAddr, // cocoon code server will bind to the port of this addråess
		"COCOON_LINK":         cn.req.Link,          // the cocoon code id to link to natively
		"COCOON_CODE_VERSION": cn.req.Version,
	}

	// include the environment variable of the release
	pretty.Println(cn.release.Env)
	cocoonEnv := cn.release.Env.ProcessAsOne(false)
	pretty.Println(cocoonEnv)
	for k, v := range cocoonEnv {
		env[k] = v
	}

	lang.SetRunEnv(env)
	go cn.monitor.Monitor()

	go func() {
		if err = cn.run(cocoonCodeContainer, lang); err != nil {
			log.Error(err.Error())
			cn.Stop(true)
			return
		}
	}()
}

// SetRouterHelper sets the router helpder
func (cn *Connector) SetRouterHelper(rh *router.Helper) {
	cn.routerHelper = rh
}

// GetOrdererDiscoverer returns the orderer discovery instance
func (cn *Connector) GetOrdererDiscoverer() *orderer.Discovery {
	return cn.ordererDiscovery
}

// cocoonUnresponsive is called when the cocoon code failed health check
func (cn *Connector) cocoonUnresponsive() {
	log.Info("Cocoon code has failed health check. Stopping cocoon code.")
	cn.Stop(true)
}<commit_msg>Enabled the inclusion of private cocoon data. Fixes the issue of not having private env vars returned<commit_after>package connector

import (
	"fmt"
	"net"
	"os"
	"path"

	"time"

	"strings"

	humanize "github.com/dustin/go-humanize"
	"github.com/ellcrys/crypto"
	"github.com/ellcrys/util"
	"github.com/goware/urlx"
	cutil "github.com/ncodes/cocoon-util"
	"github.com/ncodes/cocoon/core/api/api"
	"github.com/ncodes/cocoon/core/config"
	"github.com/ncodes/cocoon/core/connector/monitor"
	"github.com/ncodes/cocoon/core/connector/router"
	"github.com/ncodes/cocoon/core/orderer/orderer"
	"github.com/ncodes/cocoon/core/platform"
	"github.com/ncodes/cocoon/core/types"
	docker "github.com/ncodes/go-dockerclient"
	logging "github.com/op/go-logging"
	context "golang.org/x/net/context"
)

var log *logging.Logger
var buildLog *logging.Logger
var runLog *logging.Logger
var configLog *logging.Logger
var ccodeLog *logging.Logger
var fetchLog *logging.Logger
var logHealthChecker *logging.Logger
var dckClient *docker.Client

var bridgeName = os.Getenv("BRIDGE_NAME")

func init() {
}

// Connector defines a structure for starting and managing a cocoon (coode)
type Connector struct {
	waitCh            chan bool
	req               *Request
	connectorRPCAddr  string
	cocoonCodeRPCAddr string
	languages         []Language
	container         *docker.APIContainers
	containerRunning  bool
	routerHelper      *router.Helper
	monitor           *monitor.Monitor
	healthCheck       *HealthChecker
	ordererDiscovery  *orderer.Discovery
	cocoon            *types.Cocoon
	release           *types.Release
	Platform          *platform.Transactions
}

// NewConnector creates a new connector
func NewConnector(req *Request, waitCh chan bool) (*Connector, error) {
	ordererDiscovery, err := orderer.NewDiscovery()
	if err != nil {
		return nil, err
	}
	platform, err := platform.NewTransactions()
	if err != nil {
		return nil, err
	}
	return &Connector{
		req:              req,
		waitCh:           waitCh,
		monitor:          monitor.NewMonitor(req.ID),
		ordererDiscovery: ordererDiscovery,
		Platform:         platform,
	}, nil
}

// Launch starts a cocoon code
func (cn *Connector) Launch(connectorRPCAddr, cocoonCodeRPCAddr string) {

	log = config.MakeLogger("connector", fmt.Sprintf("cocoon.%s", cn.req.ID))
	buildLog = config.MakeLogger("ccode.build", fmt.Sprintf("cocoon.%s", cn.req.ID))
	runLog = config.MakeLoggerMessageOnly("ccode.run", fmt.Sprintf("cocoon.%s", cn.req.ID))
	configLog = config.MakeLogger("ccode.config", fmt.Sprintf("cocoon.%s", cn.req.ID))
	ccodeLog = config.MakeLogger("ccode.main", fmt.Sprintf("cocoon.%s", cn.req.ID))
	fetchLog = config.MakeLogger("ccode.fetch", fmt.Sprintf("cocoon.%s", cn.req.ID))
	logHealthChecker = config.MakeLogger("connector.health_checker", fmt.Sprintf("cocoon.%s", cn.req.ID))

	endpoint := "unix:///var/run/docker.sock"
	client, err := docker.NewClient(endpoint)
	if err != nil {
		log.Errorf("failed to create docker client. Is dockerd running locally?. %s", err)
		cn.Stop(true)
		return
	}

	dckClient = client
	cn.monitor.SetDockerClient(dckClient)
	cn.healthCheck = NewHealthChecker(cn.cocoonCodeRPCAddr, cn.cocoonUnresponsive)
	go cn.ordererDiscovery.Discover()

	// No need downloading, building and starting a cocoon code
	// if DEV_ADDR_COCOON_CODE_RPC has been specified. This means a dev cocoon code
	// is running at that address.
	if devCocoonCodeRPCAddr := os.Getenv("DEV_ADDR_COCOON_CODE_RPC"); len(devCocoonCodeRPCAddr) > 0 {
		cn.cocoonCodeRPCAddr = devCocoonCodeRPCAddr
		log.Infof("[Dev] Will interact with cocoon code at %s", devCocoonCodeRPCAddr)
		cn.healthCheck.Start()
		fmt.Println("failed")
		return
	}

	log.Info("Ready to install cocoon code")
	log.Debugf("Found ccode url=%s and lang=%s", cn.req.URL, cn.req.Lang)

	lang := cn.GetLanguage(cn.req.Lang)
	if lang == nil {
		log.Errorf("cocoon code language (%s) not supported", cn.req.Lang)
		cn.Stop(true)
		return
	}

	cocoonCodeContainer, err := cn.prepareContainer(lang)
	if err != nil {
		log.Error(err.Error())
		cn.Stop(true)
		return
	}

	ctx, cc := context.WithTimeout(context.Background(), 1*time.Minute)
	defer cc()
	cn.cocoon, cn.release, err = cn.Platform.GetCocoonAndLastRelease(ctx, cn.req.ID, true, true)
	if err != nil {
		log.Errorf("Failed to fetch cocoon [%s] information", cn.req.ID)
		return
	}

	log.Info("Preparing cocoon code environment variables")

	var env = map[string]string{
		"COCOON_ID":           cn.req.ID,
		"CONNECTOR_RPC_ADDR":  cn.connectorRPCAddr,
		"COCOON_RPC_ADDR":     cn.cocoonCodeRPCAddr, // cocoon code server will bind to the port of this addråess
		"COCOON_LINK":         cn.req.Link,          // the cocoon code id to link to natively
		"COCOON_CODE_VERSION": cn.req.Version,
	}

	// include the environment variable of the release
	cocoonEnv := cn.release.Env.ProcessAsOne(false)
	for k, v := range cocoonEnv {
		env[k] = v
	}

	lang.SetRunEnv(env)
	go cn.monitor.Monitor()

	go func() {
		if err = cn.run(cocoonCodeContainer, lang); err != nil {
			log.Error(err.Error())
			cn.Stop(true)
			return
		}
	}()
}

// SetRouterHelper sets the router helpder
func (cn *Connector) SetRouterHelper(rh *router.Helper) {
	cn.routerHelper = rh
}

// GetOrdererDiscoverer returns the orderer discovery instance
func (cn *Connector) GetOrdererDiscoverer() *orderer.Discovery {
	return cn.ordererDiscovery
}

// cocoonUnresponsive is called when the cocoon code failed health check
func (cn *Connector) cocoonUnresponsive() {
	log.Info("Cocoon code has failed health check. Stopping cocoon code.")
	cn.Stop(true)
}
{'fraction_non_alphanumeric': 0.12428263988522238, 'fraction_numerical': 0.0003586800573888092, 'mean_word_length': 3.976796073181615, 'pattern_counts': {'":': 10, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5815108', 'n_tokens_mistral': 4083, 'n_tokens_neox': 3939, 'n_words': 883}