<commit_before>// In this example we will place the following event into HepMC "by hand"
//
//     name status pdg_id  parent Px       Py    Pz       Energy      Mass
//  1  !p+!    3   2212    0,0    0.000    0.000 7000.000 7000.000    0.938
//  2  !p+!    3   2212    0,0    0.000    0.000-7000.000 7000.000    0.938
//=========================================================================
//  3  !d!     3      1    1,1    0.750   -1.569   32.191   32.238    0.000
//  4  !u~!    3     -2    2,2   -3.047  -19.000  -54.629   57.920    0.000
//  5  !W-!    3    -24    1,2    1.517   -20.68  -20.605   85.925   80.799
//  6  !gamma! 1     22    1,2   -3.813    0.113   -1.833    4.233    0.000
//  7  !d!     1      1    5,5   -2.445   28.816    6.082   29.552    0.010
//  8  !u~!    1     -2    5,5    3.962  -49.498  -26.687   56.373    0.006

// now we build the graph, which will look like
//                       p7                         #
// p1                   /                           #
//   \v1__p3      p5---v4                           #
//         \_v3_/       \                           #
//         /    \        p8                         #
//    v2__p4     \                                  #
//   /            p6                                #
// p2                                               #
//                                                  #
package main

import (
	"github.com/go-hep/hepmc"
)

func handle_err(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	var err error

	// first create the event container, with signal process 20, event number 1
	evt := hepmc.Event{
		SignalProcessId: 20,
		EventNumber:     1,
		Particles:       make(map[int]*hepmc.Particle),
		Vertices:        make(map[int]*hepmc.Vertex),
	}
	defer hepmc.Delete(&evt)

	// define the units
	evt.MomentumUnit = hepmc.GEV
	evt.LengthUnit = hepmc.MM

	// create vertex 1 and 2, together with their in-particles
	v1 := &hepmc.Vertex{Barcode: -1}
	err = evt.AddVertex(v1)
	handle_err(err)

	err = v1.AddParticleIn(&hepmc.Particle{
		Momentum: hepmc.FourVector{0, 0, 7000, 7000},
		PdgId:    2212,
		Status:   3,
		Barcode:  1,
	})
	handle_err(err)

	v2 := &hepmc.Vertex{Barcode: -2}
	err = evt.AddVertex(v2)
	handle_err(err)

	err = v2.AddParticleIn(&hepmc.Particle{
		Momentum: hepmc.FourVector{0, 0, -7000, 7000},
		PdgId:    2212,
		Status:   3,
		Barcode:  2,
	})
	handle_err(err)

}

// EOF
<commit_msg>examples: use barcode-suggestions<commit_after>// In this example we will place the following event into HepMC "by hand"
//
//     name status pdg_id  parent Px       Py    Pz       Energy      Mass
//  1  !p+!    3   2212    0,0    0.000    0.000 7000.000 7000.000    0.938
//  2  !p+!    3   2212    0,0    0.000    0.000-7000.000 7000.000    0.938
//=========================================================================
//  3  !d!     3      1    1,1    0.750   -1.569   32.191   32.238    0.000
//  4  !u~!    3     -2    2,2   -3.047  -19.000  -54.629   57.920    0.000
//  5  !W-!    3    -24    1,2    1.517   -20.68  -20.605   85.925   80.799
//  6  !gamma! 1     22    1,2   -3.813    0.113   -1.833    4.233    0.000
//  7  !d!     1      1    5,5   -2.445   28.816    6.082   29.552    0.010
//  8  !u~!    1     -2    5,5    3.962  -49.498  -26.687   56.373    0.006
//
// now we build the graph, which will look like
//  #                       p7                         #
//  # p1                   /                           #
//  #   \v1__p3      p5---v4                           #
//  #         \_v3_/       \                           #
//  #         /    \        p8                         #
//  #    v2__p4     \                                  #
//  #   /            p6                                #
//  # p2                                               #
//  #                                                  #
//
package main

import (
	"os"

	"github.com/go-hep/hepmc"
)

func handle_err(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	var err error

	// first create the event container, with signal process 20, event number 1
	evt := hepmc.Event{
		SignalProcessId: 20,
		EventNumber:     1,
		Particles:       make(map[int]*hepmc.Particle),
		Vertices:        make(map[int]*hepmc.Vertex),
	}
	defer hepmc.Delete(&evt)

	// define the units
	evt.MomentumUnit = hepmc.GEV
	evt.LengthUnit = hepmc.MM

	// create vertex 1 and 2, together with their in-particles
	v1 := &hepmc.Vertex{}
	err = evt.AddVertex(v1)
	handle_err(err)

	err = v1.AddParticleIn(&hepmc.Particle{
		Momentum: hepmc.FourVector{0, 0, 7000, 7000},
		PdgId:    2212,
		Status:   3,
	})
	handle_err(err)

	v2 := &hepmc.Vertex{}
	err = evt.AddVertex(v2)
	handle_err(err)

	err = v2.AddParticleIn(&hepmc.Particle{
		Momentum: hepmc.FourVector{0, 0, -7000, 7000},
		PdgId:    2212,
		Status:   3,
		//Barcode:  2,
	})
	handle_err(err)

	// create the outgoing particles of v1 and v2
	p3 := &hepmc.Particle{
		Momentum: hepmc.FourVector{.750, -1.569, 32.191, 32.238},
		PdgId:    1,
		Status:   3,
		// Barcode: 3,
	}
	err = v1.AddParticleOut(p3)
	handle_err(err)

	p4 := &hepmc.Particle{
		Momentum: hepmc.FourVector{-3.047, -19., -54.629, 57.920},
		PdgId:    -2,
		Status:   3,
		// Barcode: 4,
	}
	err = v2.AddParticleOut(p4)
	handle_err(err)

	// create v3
	v3 := &hepmc.Vertex{}
	err = evt.AddVertex(v3)
	handle_err(err)

	err = v3.AddParticleIn(p3)
	handle_err(err)

	err = v3.AddParticleIn(p4)
	handle_err(err)

	err = v3.AddParticleOut(&hepmc.Particle{
		Momentum: hepmc.FourVector{-3.813, 0.113, -1.833, 4.233},
		PdgId:    22,
		Status:   1,
	})
	handle_err(err)

	p5 := &hepmc.Particle{
		Momentum: hepmc.FourVector{1.517, -20.68, -20.605, 85.925},
		PdgId:    -24,
		Status:   3,
	}
	err = v3.AddParticleOut(p5)
	handle_err(err)

	// create v4
	v4 := &hepmc.Vertex{
		Position: hepmc.FourVector{0.12, -0.3, 0.05, 0.004},
	}
	err = evt.AddVertex(v4)
	handle_err(err)

	err = v4.AddParticleIn(p5)
	handle_err(err)

	err = v4.AddParticleOut(&hepmc.Particle{
		Momentum: hepmc.FourVector{-2.445, 28.816, 6.082, 29.552},
		PdgId:    1,
		Status:   1,
	})
	handle_err(err)

	err = v4.AddParticleOut(&hepmc.Particle{
		Momentum: hepmc.FourVector{3.962, -49.498, -26.687, 56.373},
		PdgId:    -2,
		Status:   1,
	})
	handle_err(err)

	evt.SignalVertex = v3

	err = evt.Print(os.Stdout)
	handle_err(err)

	if len(os.Args) > 1 {
		fname := os.Args[1]
		out, err := os.Create(fname)
		handle_err(err)
		defer out.Close()

		enc := hepmc.NewEncoder(out)
		err = enc.Encode(&evt)
		handle_err(err)

		err = enc.Close()
		handle_err(err)

		err = out.Close()
		handle_err(err)
	}
}

// EOF
<|endoftext|>


<commit_before>// +build darwin freebsd

package server

import "os/exec"

func installEc2EndpointNetworkAlias() ([]byte, error) {
	return exec.Command("ifconfig", "lo0", "alias", "169.254.169.254").CombinedOutput()
}

func removeEc2EndpointNetworkAlias() ([]byte, error) {
	return exec.Command("ifconfig", "lo0", "-alias", "169.254.169.254").CombinedOutput()
}
<commit_msg>build for openbsd<commit_after>// +build darwin freebsd openbsd

package server

import "os/exec"

func installEc2EndpointNetworkAlias() ([]byte, error) {
	return exec.Command("ifconfig", "lo0", "alias", "169.254.169.254").CombinedOutput()
}

func removeEc2EndpointNetworkAlias() ([]byte, error) {
	return exec.Command("ifconfig", "lo0", "-alias", "169.254.169.254").CombinedOutput()
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 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 httphandlers

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/pufferpanel/pufferd/config"
	"github.com/pufferpanel/pufferd/logging"
	"fmt"
	"time"
)

type oauthCache struct {
	oauthToken string
	serverId string
	scopes []string
	expireTime int64
}

var cache = make([]*oauthCache, 20)

func OAuth2Handler(gin *gin.Context) {
	authHeader := gin.Request.Header.Get("Authorization")
	var authToken string;
	if authHeader == "" {
		authToken = gin.Query("accessToken")
		if authToken == "" {
			gin.AbortWithStatus(401)
			return
		}
	} else {
		authArr := strings.SplitN(authHeader, " ", 2)
		if len(authArr) < 2 || authArr[0] != "Bearer" {
			gin.AbortWithStatus(400)
			return
		}
		authToken = authArr[1];
	}

	if isCachedRequest(authToken) {
		return
	}

	validateToken(authToken, gin)
}

func validateToken(accessToken string, gin *gin.Context) {
	authUrl := config.Get("infoserver")
	token := config.Get("authtoken")
	client := &http.Client{}
	data := url.Values{}
	data.Set("token", accessToken)
	request, _ := http.NewRequest("POST", authUrl, bytes.NewBufferString(data.Encode()))
	request.Header.Add("Authorization", "Bearer "+token)
	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
	response, err := client.Do(request)
	if err != nil {
		logging.Error("Error talking to auth server", err)
		errMsg := make(map[string]string)
		errMsg["error"] = err.Error();
		gin.JSON(500, errMsg);
		return
	}
	if response.StatusCode != 200 {
		logging.Error("Unexpected response code from auth server", response.StatusCode)
		errMsg := make(map[string]string)
		errMsg["error"] = fmt.Sprintf("Receieved response %i", response.StatusCode);
		gin.JSON(500, errMsg);
		return
	}
	var respArr map[string]interface{}
	json.NewDecoder(response.Body).Decode(&respArr)
	if respArr["error"] != nil {
		logging.Error("Error parsing response from auth server", err)
		errMsg := make(map[string]string)
		errMsg["error"] = "Failed to parse auth server response";
		gin.JSON(500, errMsg);
		return
	}
	if respArr["active"].(bool) == false {
		gin.AbortWithStatus(401)
		return
	}

	serverId := respArr["server_id"].(string)
	scopes := strings.Split(respArr["scope"].(string), " ")

	cache := &oauthCache{
		oauthToken: accessToken,
		serverId: serverId,
		scopes: scopes,
	}
	cacheRequest(cache)

	gin.Set("server_id", serverId)
	gin.Set("scopes", scopes)
}

func isCachedRequest(accessToken string) bool {
	currentTime := time.Now().Unix()
	for k, v := range cache {
		if v.oauthToken == accessToken {
			if v.expireTime < currentTime {
				return true
			}
			copy(cache[k:], cache[k+1:])
			cache[len(cache)-1] = nil
			cache = cache[:len(cache)-1]
			return false
		}
	}
	return false
}

func cacheRequest(request *oauthCache) {
	currentTime := time.Now().Unix()
	request.expireTime = time.Now().Add(time.Minute * 2).Unix()
	for k, v := range cache {
		if v == nil || v.expireTime > currentTime {
			cache[k] = request
			return
		}
	}
}<commit_msg>Fix cached token usage Fixes #24<commit_after>/*
 Copyright 2016 Padduck, LLC

 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 httphandlers

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/pufferpanel/pufferd/config"
	"github.com/pufferpanel/pufferd/logging"
	"fmt"
	"time"
)

type oauthCache struct {
	oauthToken string
	serverId string
	scopes []string
	expireTime int64
}

var cache = make([]*oauthCache, 20)

func OAuth2Handler(gin *gin.Context) {
	authHeader := gin.Request.Header.Get("Authorization")
	var authToken string;
	if authHeader == "" {
		authToken = gin.Query("accessToken")
		if authToken == "" {
			gin.AbortWithStatus(401)
			return
		}
	} else {
		authArr := strings.SplitN(authHeader, " ", 2)
		if len(authArr) < 2 || authArr[0] != "Bearer" {
			gin.AbortWithStatus(400)
			return
		}
		authToken = authArr[1];
	}

	cached := isCachedRequest(authToken)

	if cached != nil {
		gin.Set("server_id", cached.serverId)
		gin.Set("scopes", cached.scopes)
		return
	} else {
		validateToken(authToken, gin)
	}
}

func validateToken(accessToken string, gin *gin.Context) {
	authUrl := config.Get("infoserver")
	token := config.Get("authtoken")
	client := &http.Client{}
	data := url.Values{}
	data.Set("token", accessToken)
	request, _ := http.NewRequest("POST", authUrl, bytes.NewBufferString(data.Encode()))
	request.Header.Add("Authorization", "Bearer "+token)
	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
	response, err := client.Do(request)
	if err != nil {
		logging.Error("Error talking to auth server", err)
		errMsg := make(map[string]string)
		errMsg["error"] = err.Error();
		gin.JSON(500, errMsg);
		return
	}
	if response.StatusCode != 200 {
		logging.Error("Unexpected response code from auth server", response.StatusCode)
		errMsg := make(map[string]string)
		errMsg["error"] = fmt.Sprintf("Receieved response %i", response.StatusCode);
		gin.JSON(500, errMsg);
		return
	}
	var respArr map[string]interface{}
	json.NewDecoder(response.Body).Decode(&respArr)
	if respArr["error"] != nil {
		logging.Error("Error parsing response from auth server", err)
		errMsg := make(map[string]string)
		errMsg["error"] = "Failed to parse auth server response";
		gin.JSON(500, errMsg);
		return
	}
	if respArr["active"].(bool) == false {
		gin.AbortWithStatus(401)
		return
	}

	serverId := respArr["server_id"].(string)
	scopes := strings.Split(respArr["scope"].(string), " ")

	cache := &oauthCache{
		oauthToken: accessToken,
		serverId: serverId,
		scopes: scopes,
	}
	cacheRequest(cache)

	gin.Set("server_id", serverId)
	gin.Set("scopes", scopes)
}

func isCachedRequest(accessToken string) *oauthCache {
	currentTime := time.Now().Unix()
	for k, v := range cache {
		if v.oauthToken == accessToken {
			if v.expireTime < currentTime {
				return v
			}
			copy(cache[k:], cache[k+1:])
			cache[len(cache)-1] = nil
			cache = cache[:len(cache)-1]
			return nil
		}
	}
	return nil
}

func cacheRequest(request *oauthCache) {
	currentTime := time.Now().Unix()
	request.expireTime = time.Now().Add(time.Minute * 2).Unix()
	for k, v := range cache {
		if v == nil || v.expireTime > currentTime {
			cache[k] = request
			return
		}
	}
}<|endoftext|>


<commit_before>package provision

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"

	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/engine"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcndockerclient"
	"github.com/docker/machine/libmachine/swarm"
	"github.com/samalba/dockerclient"
)

func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth.Options) error {
	if !swarmOptions.IsSwarm {
		return nil
	}

	log.Info("Configuring swarm...")

	ip, err := p.GetDriver().GetIP()
	if err != nil {
		return err
	}

	u, err := url.Parse(swarmOptions.Host)
	if err != nil {
		return err
	}

	enginePort := engine.DefaultPort
	engineURL, err := p.GetDriver().GetURL()
	if err != nil {
		return err
	}

	parts := strings.Split(engineURL, ":")
	if len(parts) == 3 {
		dPort, err := strconv.Atoi(parts[2])
		if err != nil {
			return err
		}
		enginePort = dPort
	}

	parts = strings.Split(u.Host, ":")
	port := parts[1]

	dockerDir := p.GetDockerOptionsDir()
	dockerHost := &mcndockerclient.RemoteDocker{
		HostURL:    fmt.Sprintf("tcp://%s:%d", ip, enginePort),
		AuthOption: &authOptions,
	}
	advertiseInfo := fmt.Sprintf("%s:%d", ip, enginePort)

	if swarmOptions.Master {
		advertiseMasterInfo := fmt.Sprintf("%s:%s", ip, "3376")
		cmd := fmt.Sprintf("manage --tlsverify --tlscacert=%s --tlscert=%s --tlskey=%s -H %s --strategy %s --advertise %s",
			authOptions.CaCertRemotePath,
			authOptions.ServerCertRemotePath,
			authOptions.ServerKeyRemotePath,
			swarmOptions.Host,
			swarmOptions.Strategy,
			advertiseMasterInfo,
		)
		if swarmOptions.IsExperimental {
			cmd = "--experimental " + cmd
		}

		cmdMaster := strings.Fields(cmd)
		for _, option := range swarmOptions.ArbitraryFlags {
			cmdMaster = append(cmdMaster, "--"+option)
		}

		//Discovery must be at end of command
		cmdMaster = append(cmdMaster, swarmOptions.Discovery)

		hostBind := fmt.Sprintf("%s:%s", dockerDir, dockerDir)
		masterHostConfig := dockerclient.HostConfig{
			RestartPolicy: dockerclient.RestartPolicy{
				Name:              "always",
				MaximumRetryCount: 0,
			},
			Binds: []string{hostBind},
			PortBindings: map[string][]dockerclient.PortBinding{
				"3376/tcp": {
					{
						HostIp:   "0.0.0.0",
						HostPort: port,
					},
				},
			},
			NetworkMode: "host",
		}

		swarmMasterConfig := &dockerclient.ContainerConfig{
			Image: swarmOptions.Image,
			Env:   swarmOptions.Env,
			ExposedPorts: map[string]struct{}{
				"2375/tcp": {},
				"3376/tcp": {},
			},
			Cmd:        cmdMaster,
			HostConfig: masterHostConfig,
		}

		err = mcndockerclient.CreateContainer(dockerHost, swarmMasterConfig, "swarm-agent-master")
		if err != nil {
			return err
		}
	}

	workerHostConfig := dockerclient.HostConfig{
		RestartPolicy: dockerclient.RestartPolicy{
			Name:              "always",
			MaximumRetryCount: 0,
		},
		NetworkMode: "host",
	}

	swarmWorkerConfig := &dockerclient.ContainerConfig{
		Image: swarmOptions.Image,
		Env:   swarmOptions.Env,
		Cmd: []string{
			"join",
			"--advertise",
			advertiseInfo,
			swarmOptions.Discovery,
		},
		HostConfig: workerHostConfig,
	}
	if swarmOptions.IsExperimental {
		swarmWorkerConfig.Cmd = append([]string{"--experimental"}, swarmWorkerConfig.Cmd...)
	}

	return mcndockerclient.CreateContainer(dockerHost, swarmWorkerConfig, "swarm-agent")
}
<commit_msg>Run Swarm containers without --net host<commit_after>package provision

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"

	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/engine"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcndockerclient"
	"github.com/docker/machine/libmachine/swarm"
	"github.com/samalba/dockerclient"
)

func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth.Options) error {
	if !swarmOptions.IsSwarm {
		return nil
	}

	log.Info("Configuring swarm...")

	ip, err := p.GetDriver().GetIP()
	if err != nil {
		return err
	}

	u, err := url.Parse(swarmOptions.Host)
	if err != nil {
		return err
	}

	enginePort := engine.DefaultPort
	engineURL, err := p.GetDriver().GetURL()
	if err != nil {
		return err
	}

	parts := strings.Split(engineURL, ":")
	if len(parts) == 3 {
		dPort, err := strconv.Atoi(parts[2])
		if err != nil {
			return err
		}
		enginePort = dPort
	}

	parts = strings.Split(u.Host, ":")
	port := parts[1]

	dockerDir := p.GetDockerOptionsDir()
	dockerHost := &mcndockerclient.RemoteDocker{
		HostURL:    fmt.Sprintf("tcp://%s:%d", ip, enginePort),
		AuthOption: &authOptions,
	}
	advertiseInfo := fmt.Sprintf("%s:%d", ip, enginePort)

	if swarmOptions.Master {
		advertiseMasterInfo := fmt.Sprintf("%s:%s", ip, "3376")
		cmd := fmt.Sprintf("manage --tlsverify --tlscacert=%s --tlscert=%s --tlskey=%s -H %s --strategy %s --advertise %s",
			authOptions.CaCertRemotePath,
			authOptions.ServerCertRemotePath,
			authOptions.ServerKeyRemotePath,
			swarmOptions.Host,
			swarmOptions.Strategy,
			advertiseMasterInfo,
		)
		if swarmOptions.IsExperimental {
			cmd = "--experimental " + cmd
		}

		cmdMaster := strings.Fields(cmd)
		for _, option := range swarmOptions.ArbitraryFlags {
			cmdMaster = append(cmdMaster, "--"+option)
		}

		//Discovery must be at end of command
		cmdMaster = append(cmdMaster, swarmOptions.Discovery)

		hostBind := fmt.Sprintf("%s:%s", dockerDir, dockerDir)
		masterHostConfig := dockerclient.HostConfig{
			RestartPolicy: dockerclient.RestartPolicy{
				Name:              "always",
				MaximumRetryCount: 0,
			},
			Binds: []string{hostBind},
			PortBindings: map[string][]dockerclient.PortBinding{
				"3376/tcp": {
					{
						HostIp:   "0.0.0.0",
						HostPort: port,
					},
				},
			},
		}

		swarmMasterConfig := &dockerclient.ContainerConfig{
			Image: swarmOptions.Image,
			Env:   swarmOptions.Env,
			ExposedPorts: map[string]struct{}{
				"2375/tcp": {},
				"3376/tcp": {},
			},
			Cmd:        cmdMaster,
			HostConfig: masterHostConfig,
		}

		err = mcndockerclient.CreateContainer(dockerHost, swarmMasterConfig, "swarm-agent-master")
		if err != nil {
			return err
		}
	}

	workerHostConfig := dockerclient.HostConfig{
		RestartPolicy: dockerclient.RestartPolicy{
			Name:              "always",
			MaximumRetryCount: 0,
		},
	}

	swarmWorkerConfig := &dockerclient.ContainerConfig{
		Image: swarmOptions.Image,
		Env:   swarmOptions.Env,
		Cmd: []string{
			"join",
			"--advertise",
			advertiseInfo,
			swarmOptions.Discovery,
		},
		HostConfig: workerHostConfig,
	}
	if swarmOptions.IsExperimental {
		swarmWorkerConfig.Cmd = append([]string{"--experimental"}, swarmWorkerConfig.Cmd...)
	}

	return mcndockerclient.CreateContainer(dockerHost, swarmWorkerConfig, "swarm-agent")
}
<|endoftext|>


<commit_before>package server

import (
	"crypto/tls"
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"sync"
	"time"

	"github.com/goware/urlx"
	"github.com/rcrowley/go-metrics"
)

var (
	DefaultHttpFetcherReqTimeout     = time.Second * 20
	DefaultHttpFetcherReqNumAttempts = 2
)

type HttpFetcher struct {
	Client *http.Client

	ReqTimeout     time.Duration
	ReqNumAttempts int
	HostKeepAlive  time.Duration

	// TODO: lru cache of responses.. like a reverse cache.. including bad urls.. 404s, etc...
}

type HttpFetcherResponse struct {
	URL    *url.URL
	Status int
	Data   []byte
	Err    error
}

func NewHttpFetcher() *HttpFetcher {
	hf := &HttpFetcher{}
	hf.ReqTimeout = DefaultHttpFetcherReqTimeout
	hf.ReqNumAttempts = DefaultHttpFetcherReqNumAttempts
	hf.HostKeepAlive = 60 * time.Second
	return hf
}

func (hf HttpFetcher) client() *http.Client {
	if hf.Client != nil {
		return hf.Client
	}
	hf.Client = &http.Client{
		Timeout: hf.ReqTimeout,
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   hf.ReqTimeout,
				KeepAlive: hf.HostKeepAlive,
			}).Dial,
			TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
			TLSHandshakeTimeout: 5 * time.Second,
			MaxIdleConnsPerHost: 5,
			DisableCompression:  true,
			DisableKeepAlives:   false, // HMM.. keep alives..?
		},
	}
	return hf.Client
}

func (hf HttpFetcher) Get(url string) (*HttpFetcherResponse, error) {
	resps, err := hf.GetAll([]string{url})
	if err != nil {
		return nil, err
	}
	if len(resps) == 0 {
		return nil, errors.New("httpfetcher: no response")
	}
	resp := resps[0]
	if resp.Err != nil {
		return resp, resp.Err
	}
	return resp, nil
}

func (hf HttpFetcher) GetAll(urls []string) ([]*HttpFetcherResponse, error) {
	m := metrics.GetOrRegisterTimer("fn.FetchRemoteData", nil) // TODO: update metric name
	defer m.UpdateSince(time.Now())

	resps := make([]*HttpFetcherResponse, len(urls))

	var wg sync.WaitGroup
	wg.Add(len(urls))

	// TODO: add thruput here..

	for i, urlStr := range urls {
		resps[i] = &HttpFetcherResponse{}

		go func(resp *HttpFetcherResponse) {
			defer wg.Done()

			url, err := urlx.Parse(urlStr)
			if err != nil {
				resp.Err = err
				return
			}
			resp.URL = url

			lg.Info("Fetching %s", url.String())

			fetch, err := hf.client().Get(url.String())
			if err != nil {
				lg.Warning("Error fetching %s because %s", url.String(), err)
				resp.Err = err
				return
			}
			defer fetch.Body.Close()

			resp.Status = fetch.StatusCode

			body, err := ioutil.ReadAll(fetch.Body)
			if err != nil {
				resp.Err = err
				return
			}
			resp.Data = body
			resp.Err = nil

		}(resps[i])
	}

	wg.Wait()
	return resps, nil
}
<commit_msg>HttpFetcher, adjust transport<commit_after>package server

import (
	"crypto/tls"
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"sync"
	"time"

	"github.com/goware/urlx"
	"github.com/rcrowley/go-metrics"
)

var (
	DefaultHttpFetcherReqTimeout     = time.Second * 20
	DefaultHttpFetcherReqNumAttempts = 2
)

type HttpFetcher struct {
	Client *http.Client

	ReqTimeout     time.Duration
	ReqNumAttempts int
	HostKeepAlive  time.Duration

	// TODO: lru cache of responses.. like a reverse cache.. including bad urls.. 404s, etc...
}

type HttpFetcherResponse struct {
	URL    *url.URL
	Status int
	Data   []byte
	Err    error
}

func NewHttpFetcher() *HttpFetcher {
	hf := &HttpFetcher{}
	hf.ReqTimeout = DefaultHttpFetcherReqTimeout
	hf.ReqNumAttempts = DefaultHttpFetcherReqNumAttempts
	hf.HostKeepAlive = 60 * time.Second
	return hf
}

func (hf HttpFetcher) client() *http.Client {
	if hf.Client != nil {
		return hf.Client
	}
	hf.Client = &http.Client{
		Timeout: hf.ReqTimeout,
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   hf.ReqTimeout,
				KeepAlive: hf.HostKeepAlive,
			}).Dial,
			TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
			TLSHandshakeTimeout: 5 * time.Second,
			MaxIdleConnsPerHost: 2,
			DisableCompression:  true,
			DisableKeepAlives:   false,
			ResponseHeaderTimeout: hf.ReqTimeout,
		},
	}
	return hf.Client
}

func (hf HttpFetcher) Get(url string) (*HttpFetcherResponse, error) {
	resps, err := hf.GetAll([]string{url})
	if err != nil {
		return nil, err
	}
	if len(resps) == 0 {
		return nil, errors.New("httpfetcher: no response")
	}
	resp := resps[0]
	if resp.Err != nil {
		return resp, resp.Err
	}
	return resp, nil
}

func (hf HttpFetcher) GetAll(urls []string) ([]*HttpFetcherResponse, error) {
	m := metrics.GetOrRegisterTimer("fn.FetchRemoteData", nil) // TODO: update metric name
	defer m.UpdateSince(time.Now())

	resps := make([]*HttpFetcherResponse, len(urls))

	var wg sync.WaitGroup
	wg.Add(len(urls))

	// TODO: add thruput here..

	for i, urlStr := range urls {
		resps[i] = &HttpFetcherResponse{}

		go func(resp *HttpFetcherResponse) {
			defer wg.Done()

			url, err := urlx.Parse(urlStr)
			if err != nil {
				resp.Err = err
				return
			}
			resp.URL = url

			lg.Info("Fetching %s", url.String())

			fetch, err := hf.client().Get(url.String())
			defer fetch.Body.Close()

			if err != nil {
				lg.Warning("Error fetching %s because %s", url.String(), err)
				resp.Err = err
				return
			}
			resp.Status = fetch.StatusCode

			body, err := ioutil.ReadAll(fetch.Body)
			if err != nil {
				resp.Err = err
				return
			}
			resp.Data = body
			resp.Err = nil

		}(resps[i])
	}

	wg.Wait()
	return resps, nil
}
<|endoftext|>


<commit_before>package transport

import (
	"errors"
	"io"
	"os"
)

// MockTransport is a mock implementation of Transport.
type MockTransport struct {
	// Channel sends connections to the "server" once the "client" has
	// connected.
	Channel chan *MockConnection
}

// Dial ignores the port, and returns a MockTransport struct.
func (t *MockTransport) Dial(_ uint32) (Connection, error) {
	csr, csw := io.Pipe()
	scr, scw := io.Pipe()
	t.Channel <- &MockConnection{
		PipeReader: csr,
		PipeWriter: scw,
	}
	return &MockConnection{
		PipeReader: scr,
		PipeWriter: csw,
	}, nil
}

// MockConnection is a mock implementation of Connection.
type MockConnection struct {
	*io.PipeReader
	*io.PipeWriter
}

// Close marks the connection as closed, and closes the read and write
// channels.
func (c *MockConnection) Close() error {
	c.PipeReader.Close()
	c.PipeWriter.Close()
	return nil
}

// CloseRead closes the read channel.
func (c *MockConnection) CloseRead() error {
	return c.PipeReader.Close()
}

// CloseWrite closes the write channel.
func (c *MockConnection) CloseWrite() error {
	return c.PipeWriter.Close()
}

// File returns a file that can be used to read/write to the connection.
func (c *MockConnection) File() (*os.File, error) {
	return nil, errors.New("not supported")
}
<commit_msg>Update string for mock<commit_after>package transport

import (
	"errors"
	"io"
	"os"
)

// MockTransport is a mock implementation of Transport.
type MockTransport struct {
	// Channel sends connections to the "server" once the "client" has
	// connected.
	Channel chan *MockConnection
}

// Dial ignores the port, and returns a MockTransport struct.
func (t *MockTransport) Dial(_ uint32) (Connection, error) {
	csr, csw := io.Pipe()
	scr, scw := io.Pipe()
	t.Channel <- &MockConnection{
		PipeReader: csr,
		PipeWriter: scw,
	}
	return &MockConnection{
		PipeReader: scr,
		PipeWriter: csw,
	}, nil
}

// MockConnection is a mock implementation of Connection.
type MockConnection struct {
	*io.PipeReader
	*io.PipeWriter
}

// Close marks the connection as closed, and closes the read and write
// channels.
func (c *MockConnection) Close() error {
	c.PipeReader.Close()
	c.PipeWriter.Close()
	return nil
}

// CloseRead closes the read channel.
func (c *MockConnection) CloseRead() error {
	return c.PipeReader.Close()
}

// CloseWrite closes the write channel.
func (c *MockConnection) CloseWrite() error {
	return c.PipeWriter.Close()
}

// File returns a file that can be used to read/write to the connection.
func (c *MockConnection) File() (*os.File, error) {
	return nil, errors.New("not implemented")
}
<|endoftext|>


<commit_before>package marathon

import (
	"encoding/json"
	"github.com/QubitProducts/bamboo/configuration"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
)

// Describes an app process running
type Task struct {
	Host  string
	Port  int
	Ports []int
}

// An app may have multiple processes
type App struct {
	Id              string
	EscapedId       string
	HealthCheckPath string
	Tasks           []Task
	ServicePort     int
	ServicePorts    []int
	Env             map[string]string
	Labels          map[string]string
}

type AppList []App

func (slice AppList) Len() int {
	return len(slice)
}

func (slice AppList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice AppList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonTaskList []marathonTask

type marathonTasks struct {
	Tasks marathonTaskList `json:tasks`
}

type marathonTask struct {
	AppId        string
	Id           string
	Host         string
	Ports        []int
	ServicePorts []int
	StartedAt    string
	StagedAt     string
	Version      string
}

func (slice marathonTaskList) Len() int {
	return len(slice)
}

func (slice marathonTaskList) Less(i, j int) bool {
	return slice[i].StagedAt < slice[j].StagedAt
}

func (slice marathonTaskList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonApps struct {
	Apps []marathonApp `json:apps`
}

type marathonApp struct {
	Id           string            `json:id`
	HealthChecks []healthCheck     `json:healthChecks`
	Ports        []int             `json:ports`
	Env          map[string]string `json:env`
	Labels       map[string]string `json:labels`
}

type healthCheck struct {
	Path     string `json:path`
	Protocol string `json:protocol`
}

func fetchMarathonApps(endpoint string) (map[string]marathonApp, error) {
	response, err := http.Get(endpoint + "/v2/apps")

	if err != nil {
		return nil, err
	}

	defer response.Body.Close()
	var appResponse marathonApps

	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &appResponse)
	if err != nil {
		return nil, err
	}

	dataById := map[string]marathonApp{}

	for _, appConfig := range appResponse.Apps {
		dataById[appConfig.Id] = appConfig
	}

	return dataById, nil
}

func fetchTasks(endpoint string) (map[string][]marathonTask, error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", endpoint+"/v2/tasks", nil)
	req.Header.Add("Accept", "application/json")
	response, err := client.Do(req)

	var tasks marathonTasks

	if err != nil {
		return nil, err
	}

	contents, err := ioutil.ReadAll(response.Body)
	defer response.Body.Close()
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &tasks)
	if err != nil {
		return nil, err
	}

	taskList := tasks.Tasks
	sort.Sort(taskList)

	tasksById := map[string][]marathonTask{}
	for _, task := range taskList {
		if tasksById[task.AppId] == nil {
			tasksById[task.AppId] = []marathonTask{}
		}
		tasksById[task.AppId] = append(tasksById[task.AppId], task)
	}

	return tasksById, nil
}

func createApps(tasksById map[string][]marathonTask, marathonApps map[string]marathonApp) AppList {

	apps := AppList{}

	for appId, tasks := range tasksById {
		simpleTasks := []Task{}

		for _, task := range tasks {
			if len(task.Ports) > 0 {
				simpleTasks = append(simpleTasks, Task{Host: task.Host, Port: task.Ports[0], Ports: task.Ports})
			}
		}

		// Try to handle old app id format without slashes
		appPath := appId
		if !strings.HasPrefix(appId, "/") {
			appPath = "/" + appId
		}

		app := App{
			// Since Marathon 0.7, apps are namespaced with path
			Id: appPath,
			// Used for template
			EscapedId:       strings.Replace(appId, "/", "::", -1),
			Tasks:           simpleTasks,
			HealthCheckPath: parseHealthCheckPath(marathonApps[appId].HealthChecks),
			Env:             marathonApps[appId].Env,
			Labels:          marathonApps[appId].Labels,
		}

		if len(marathonApps[appId].Ports) > 0 {
			app.ServicePort = marathonApps[appId].Ports[0]
			app.ServicePorts = marathonApps[appId].Ports
		}

		apps = append(apps, app)
	}
	return apps
}

func parseHealthCheckPath(checks []healthCheck) string {
	for _, check := range checks {
		if check.Protocol != "HTTP" {
			continue
		}
		return check.Path
	}
	return ""
}

/*
	Apps returns a struct that describes Marathon current app and their
	sub tasks information.

	Parameters:
		endpoint: Marathon HTTP endpoint, e.g. http://localhost:8080
*/
func FetchApps(maraconf configuration.Marathon) (AppList, error) {

	var applist AppList
	var err error

	// try all configured endpoints until one succeeds
	for _, url := range maraconf.Endpoints() {
		applist, err = _fetchApps(url)
		if err == nil {
			return applist, err
		}
	}
	// return last error
	return nil, err
}

func _fetchApps(url string) (AppList, error) {
	tasks, err := fetchTasks(url)
	if err != nil {
		return nil, err
	}

	marathonApps, err := fetchMarathonApps(url)
	if err != nil {
		return nil, err
	}

	apps := createApps(tasks, marathonApps)
	sort.Sort(apps)
	return apps, nil
}
<commit_msg>Correct json labels<commit_after>package marathon

import (
	"encoding/json"
	"github.com/QubitProducts/bamboo/configuration"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
)

// Describes an app process running
type Task struct {
	Host  string
	Port  int
	Ports []int
}

// An app may have multiple processes
type App struct {
	Id              string
	EscapedId       string
	HealthCheckPath string
	Tasks           []Task
	ServicePort     int
	ServicePorts    []int
	Env             map[string]string
	Labels          map[string]string
}

type AppList []App

func (slice AppList) Len() int {
	return len(slice)
}

func (slice AppList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice AppList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonTaskList []marathonTask

type marathonTasks struct {
	Tasks marathonTaskList `json:"tasks"`
}

type marathonTask struct {
	AppId        string
	Id           string
	Host         string
	Ports        []int
	ServicePorts []int
	StartedAt    string
	StagedAt     string
	Version      string
}

func (slice marathonTaskList) Len() int {
	return len(slice)
}

func (slice marathonTaskList) Less(i, j int) bool {
	return slice[i].StagedAt < slice[j].StagedAt
}

func (slice marathonTaskList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonApps struct {
	Apps []marathonApp `json:"apps"`
}

type marathonApp struct {
	Id           string            `json:"id"`
	HealthChecks []healthCheck     `json:"healthChecks"`
	Ports        []int             `json:"ports"`
	Env          map[string]string `json:"env"`
	Labels       map[string]string `json:"labels"`
}

type healthCheck struct {
	Path     string `json:"path"`
	Protocol string `json:"protocol"`
}

func fetchMarathonApps(endpoint string) (map[string]marathonApp, error) {
	response, err := http.Get(endpoint + "/v2/apps")

	if err != nil {
		return nil, err
	}

	defer response.Body.Close()
	var appResponse marathonApps

	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &appResponse)
	if err != nil {
		return nil, err
	}

	dataById := map[string]marathonApp{}

	for _, appConfig := range appResponse.Apps {
		dataById[appConfig.Id] = appConfig
	}

	return dataById, nil
}

func fetchTasks(endpoint string) (map[string][]marathonTask, error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", endpoint+"/v2/tasks", nil)
	req.Header.Add("Accept", "application/json")
	response, err := client.Do(req)

	var tasks marathonTasks

	if err != nil {
		return nil, err
	}

	contents, err := ioutil.ReadAll(response.Body)
	defer response.Body.Close()
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &tasks)
	if err != nil {
		return nil, err
	}

	taskList := tasks.Tasks
	sort.Sort(taskList)

	tasksById := map[string][]marathonTask{}
	for _, task := range taskList {
		if tasksById[task.AppId] == nil {
			tasksById[task.AppId] = []marathonTask{}
		}
		tasksById[task.AppId] = append(tasksById[task.AppId], task)
	}

	return tasksById, nil
}

func createApps(tasksById map[string][]marathonTask, marathonApps map[string]marathonApp) AppList {

	apps := AppList{}

	for appId, tasks := range tasksById {
		simpleTasks := []Task{}

		for _, task := range tasks {
			if len(task.Ports) > 0 {
				simpleTasks = append(simpleTasks, Task{Host: task.Host, Port: task.Ports[0], Ports: task.Ports})
			}
		}

		// Try to handle old app id format without slashes
		appPath := appId
		if !strings.HasPrefix(appId, "/") {
			appPath = "/" + appId
		}

		app := App{
			// Since Marathon 0.7, apps are namespaced with path
			Id: appPath,
			// Used for template
			EscapedId:       strings.Replace(appId, "/", "::", -1),
			Tasks:           simpleTasks,
			HealthCheckPath: parseHealthCheckPath(marathonApps[appId].HealthChecks),
			Env:             marathonApps[appId].Env,
			Labels:          marathonApps[appId].Labels,
		}

		if len(marathonApps[appId].Ports) > 0 {
			app.ServicePort = marathonApps[appId].Ports[0]
			app.ServicePorts = marathonApps[appId].Ports
		}

		apps = append(apps, app)
	}
	return apps
}

func parseHealthCheckPath(checks []healthCheck) string {
	for _, check := range checks {
		if check.Protocol != "HTTP" {
			continue
		}
		return check.Path
	}
	return ""
}

/*
	Apps returns a struct that describes Marathon current app and their
	sub tasks information.

	Parameters:
		endpoint: Marathon HTTP endpoint, e.g. http://localhost:8080
*/
func FetchApps(maraconf configuration.Marathon) (AppList, error) {

	var applist AppList
	var err error

	// try all configured endpoints until one succeeds
	for _, url := range maraconf.Endpoints() {
		applist, err = _fetchApps(url)
		if err == nil {
			return applist, err
		}
	}
	// return last error
	return nil, err
}

func _fetchApps(url string) (AppList, error) {
	tasks, err := fetchTasks(url)
	if err != nil {
		return nil, err
	}

	marathonApps, err := fetchMarathonApps(url)
	if err != nil {
		return nil, err
	}

	apps := createApps(tasks, marathonApps)
	sort.Sort(apps)
	return apps, nil
}
<|endoftext|>


<commit_before>// Copyright 2017 Authors of Cilium
//
// 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 cmd

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"os"
	"os/signal"
	"runtime"

	"github.com/cilium/cilium/pkg/bpf"
	"github.com/cilium/cilium/pkg/bpfdebug"

	"github.com/spf13/cobra"
	"golang.org/x/sys/unix"
)

// monitorCmd represents the monitor command
var monitorCmd = &cobra.Command{
	Use:   "monitor",
	Short: "Monitoring",
	Long: `The monitor displays notifications and events omitted by the BPF
programs attached to endpoints and devices. This includes:
  * Dropped packet notifications
  * Captured packet traces
  * Debugging information`,
	Run: func(cmd *cobra.Command, args []string) {
		runMonitor()
	},
}

func listEventTypes() []string {
	types := []string{}
	for k := range eventTypes {
		types = append(types, k)
	}
	return types
}

func init() {
	RootCmd.AddCommand(monitorCmd)
	monitorCmd.Flags().IntVarP(&eventConfig.NumCpus, "num-cpus", "c", runtime.NumCPU(), "Number of CPUs")
	monitorCmd.Flags().IntVarP(&eventConfig.NumPages, "num-pages", "n", 64, "Number of pages for ring buffer")
	monitorCmd.Flags().BoolVarP(&dissect, "dissect", "d", false, "Dissect packet data")
	monitorCmd.Flags().StringVarP(&eventType, "type", "t", "", fmt.Sprintf("Filter by event types %v", listEventTypes()))
	monitorCmd.Flags().Uint16Var(&fromSource, "from", 0, "Filter by source endpoint id")
	monitorCmd.Flags().Uint32Var(&toDst, "to", 0, "Filter by destination endpoint id")
	monitorCmd.Flags().Uint32Var(&related, "related-to", 0, "Filter by either source or destination endpoint id")
}

var (
	dissect     = false
	eventConfig = bpf.PerfEventConfig{
		MapName:      bpf.EventsMapName,
		Type:         bpf.PERF_TYPE_SOFTWARE,
		Config:       bpf.PERF_COUNT_SW_BPF_OUTPUT,
		SampleType:   bpf.PERF_SAMPLE_RAW,
		WakeupEvents: 1,
	}
	eventTypeIdx = -1 // for integer comparison
	eventType    = ""
	eventTypes   = map[string]int{
		"drop":    bpfdebug.MessageTypeDrop,
		"debug":   bpfdebug.MessageTypeDebug,
		"capture": bpfdebug.MessageTypeCapture,
	}
	fromSource = uint16(0)
	toDst      = uint32(0)
	related    = uint32(0)
)

func lostEvent(lost *bpf.PerfEventLost, cpu int) {
	fmt.Printf("CPU %02d: Lost %d events\n", cpu, lost.Lost)
}

// match checks if the event type, from endpoint and / or to endpoint match
// when they are supplied. The either part of from and to endpoint depends on
// related to, which can match on both.  If either one of them is less than or
// equal to zero, then it is assumed user did not use them.
func match(messageType int, src uint16, dst uint32) bool {
	if eventTypeIdx > bpfdebug.MessageTypeUnspec && messageType != eventTypeIdx {
		return false
	} else if fromSource > 0 && fromSource != src {
		return false
	} else if toDst > 0 && toDst != dst {
		return false
	} else if related > 0 && uint16(related) != src && related != dst {
		return false
	}

	return true
}

// dropEvents prints out all the received drop notifications.
func dropEvents(prefix string, data []byte) {
	dn := bpfdebug.DropNotify{}

	if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dn); err != nil {
		fmt.Printf("Error while parsing drop notification message: %s\n", err)
	}
	if match(bpfdebug.MessageTypeDrop, dn.Source, dn.DstID) {
		dn.Dump(dissect, data, prefix)
	}
}

// debugEvents prints out all the debug messages.
func debugEvents(prefix string, data []byte) {
	dm := bpfdebug.DebugMsg{}

	if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dm); err != nil {
		fmt.Printf("Error while parsing debug message: %s\n", err)
	}
	if match(bpfdebug.MessageTypeDebug, dm.Source, 0) {
		dm.Dump(data, prefix)
	}
}

// captureEvents prints out all the capture messages.
func captureEvents(prefix string, data []byte) {
	dc := bpfdebug.DebugCapture{}

	if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dc); err != nil {
		fmt.Printf("Error while parsing debug capture message: %s\n", err)
	}
	if match(bpfdebug.MessageTypeCapture, dc.Source, 0) {
		dc.Dump(dissect, data, prefix)
	}
}

// receiveEvent forwards all the per CPU events to the appropriate type function.
func receiveEvent(msg *bpf.PerfEventSample, cpu int) {
	prefix := fmt.Sprintf("CPU %02d:", cpu)
	data := msg.DataDirect()
	messageType := data[0]

	switch messageType {
	case bpfdebug.MessageTypeDrop:
		dropEvents(prefix, data)
	case bpfdebug.MessageTypeDebug:
		debugEvents(prefix, data)
	case bpfdebug.MessageTypeCapture:
		captureEvents(prefix, data)
	default:
		fmt.Printf("%s Unknonwn event: %+v\n", prefix, msg)
	}
}

// validateEventTypeFilter does some input validation to give the user feedback if they
// wrote something close that did not match for example 'srop' instead of
// 'drop'.
func validateEventTypeFilter() {
	i, err := eventTypes[eventType]
	if !err {
		err := "Unknown type (%s). Please use one of the following ones %v\n"
		fmt.Printf(err, eventType, listEventTypes())
		os.Exit(1)
	}
	eventTypeIdx = i
}

func runMonitor() {
	if os.Getuid() != 0 {
		fmt.Fprintf(os.Stderr, "Please run the monitor with root privileges.\n")
		os.Exit(1)
	}

	events, err := bpf.NewPerCpuEvents(&eventConfig)
	if err != nil {
		panic(err)
	}

	if eventType != "" {
		validateEventTypeFilter()
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	go func() {
		for range signalChan {
			fmt.Printf("\nReceived an interrupt, stopping monitor...\n\n")

			lost, unknown := events.Stats()
			if lost != 0 || unknown != 0 {
				fmt.Printf("%d events lost, %d unknown notifications\n", lost, unknown)
			}

			if err := events.CloseAll(); err != nil {
				panic(err)
			}

			os.Exit(0)
		}
	}()

	fmt.Printf("Listening for events on %d CPUs with %dx%d of shared memory\n",
		events.Cpus, events.Npages, events.Pagesize)
	fmt.Printf("Press Ctrl-C to quit\n")

	for {
		todo, err := events.Poll(5000)
		if err != nil && err != unix.EINTR {
			panic(err)
		}
		if todo > 0 {
			if err := events.ReadAll(receiveEvent, lostEvent); err != nil {
				fmt.Printf("Error received while reading from perf buffer: %s\n", err)
			}
		}
	}

}
<commit_msg>cmd/monitor: be more specific with eventType match<commit_after>// Copyright 2017 Authors of Cilium
//
// 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 cmd

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"os"
	"os/signal"
	"runtime"

	"github.com/cilium/cilium/pkg/bpf"
	"github.com/cilium/cilium/pkg/bpfdebug"

	"github.com/spf13/cobra"
	"golang.org/x/sys/unix"
)

// monitorCmd represents the monitor command
var monitorCmd = &cobra.Command{
	Use:   "monitor",
	Short: "Monitoring",
	Long: `The monitor displays notifications and events omitted by the BPF
programs attached to endpoints and devices. This includes:
  * Dropped packet notifications
  * Captured packet traces
  * Debugging information`,
	Run: func(cmd *cobra.Command, args []string) {
		runMonitor()
	},
}

func listEventTypes() []string {
	types := []string{}
	for k := range eventTypes {
		types = append(types, k)
	}
	return types
}

func init() {
	RootCmd.AddCommand(monitorCmd)
	monitorCmd.Flags().IntVarP(&eventConfig.NumCpus, "num-cpus", "c", runtime.NumCPU(), "Number of CPUs")
	monitorCmd.Flags().IntVarP(&eventConfig.NumPages, "num-pages", "n", 64, "Number of pages for ring buffer")
	monitorCmd.Flags().BoolVarP(&dissect, "dissect", "d", false, "Dissect packet data")
	monitorCmd.Flags().StringVarP(&eventType, "type", "t", "", fmt.Sprintf("Filter by event types %v", listEventTypes()))
	monitorCmd.Flags().Uint16Var(&fromSource, "from", 0, "Filter by source endpoint id")
	monitorCmd.Flags().Uint32Var(&toDst, "to", 0, "Filter by destination endpoint id")
	monitorCmd.Flags().Uint32Var(&related, "related-to", 0, "Filter by either source or destination endpoint id")
}

var (
	dissect     = false
	eventConfig = bpf.PerfEventConfig{
		MapName:      bpf.EventsMapName,
		Type:         bpf.PERF_TYPE_SOFTWARE,
		Config:       bpf.PERF_COUNT_SW_BPF_OUTPUT,
		SampleType:   bpf.PERF_SAMPLE_RAW,
		WakeupEvents: 1,
	}
	eventTypeIdx = bpfdebug.MessageTypeUnspec // for integer comparison
	eventType    = ""
	eventTypes   = map[string]int{
		"drop":    bpfdebug.MessageTypeDrop,
		"debug":   bpfdebug.MessageTypeDebug,
		"capture": bpfdebug.MessageTypeCapture,
	}
	fromSource = uint16(0)
	toDst      = uint32(0)
	related    = uint32(0)
)

func lostEvent(lost *bpf.PerfEventLost, cpu int) {
	fmt.Printf("CPU %02d: Lost %d events\n", cpu, lost.Lost)
}

// match checks if the event type, from endpoint and / or to endpoint match
// when they are supplied. The either part of from and to endpoint depends on
// related to, which can match on both.  If either one of them is less than or
// equal to zero, then it is assumed user did not use them.
func match(messageType int, src uint16, dst uint32) bool {
	if eventTypeIdx != bpfdebug.MessageTypeUnspec && messageType != eventTypeIdx {
		return false
	} else if fromSource > 0 && fromSource != src {
		return false
	} else if toDst > 0 && toDst != dst {
		return false
	} else if related > 0 && uint16(related) != src && related != dst {
		return false
	}

	return true
}

// dropEvents prints out all the received drop notifications.
func dropEvents(prefix string, data []byte) {
	dn := bpfdebug.DropNotify{}

	if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dn); err != nil {
		fmt.Printf("Error while parsing drop notification message: %s\n", err)
	}
	if match(bpfdebug.MessageTypeDrop, dn.Source, dn.DstID) {
		dn.Dump(dissect, data, prefix)
	}
}

// debugEvents prints out all the debug messages.
func debugEvents(prefix string, data []byte) {
	dm := bpfdebug.DebugMsg{}

	if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dm); err != nil {
		fmt.Printf("Error while parsing debug message: %s\n", err)
	}
	if match(bpfdebug.MessageTypeDebug, dm.Source, 0) {
		dm.Dump(data, prefix)
	}
}

// captureEvents prints out all the capture messages.
func captureEvents(prefix string, data []byte) {
	dc := bpfdebug.DebugCapture{}

	if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dc); err != nil {
		fmt.Printf("Error while parsing debug capture message: %s\n", err)
	}
	if match(bpfdebug.MessageTypeCapture, dc.Source, 0) {
		dc.Dump(dissect, data, prefix)
	}
}

// receiveEvent forwards all the per CPU events to the appropriate type function.
func receiveEvent(msg *bpf.PerfEventSample, cpu int) {
	prefix := fmt.Sprintf("CPU %02d:", cpu)
	data := msg.DataDirect()
	messageType := data[0]

	switch messageType {
	case bpfdebug.MessageTypeDrop:
		dropEvents(prefix, data)
	case bpfdebug.MessageTypeDebug:
		debugEvents(prefix, data)
	case bpfdebug.MessageTypeCapture:
		captureEvents(prefix, data)
	default:
		fmt.Printf("%s Unknonwn event: %+v\n", prefix, msg)
	}
}

// validateEventTypeFilter does some input validation to give the user feedback if they
// wrote something close that did not match for example 'srop' instead of
// 'drop'.
func validateEventTypeFilter() {
	i, err := eventTypes[eventType]
	if !err {
		err := "Unknown type (%s). Please use one of the following ones %v\n"
		fmt.Printf(err, eventType, listEventTypes())
		os.Exit(1)
	}
	eventTypeIdx = i
}

func runMonitor() {
	if os.Getuid() != 0 {
		fmt.Fprintf(os.Stderr, "Please run the monitor with root privileges.\n")
		os.Exit(1)
	}

	events, err := bpf.NewPerCpuEvents(&eventConfig)
	if err != nil {
		panic(err)
	}

	if eventType != "" {
		validateEventTypeFilter()
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	go func() {
		for range signalChan {
			fmt.Printf("\nReceived an interrupt, stopping monitor...\n\n")

			lost, unknown := events.Stats()
			if lost != 0 || unknown != 0 {
				fmt.Printf("%d events lost, %d unknown notifications\n", lost, unknown)
			}

			if err := events.CloseAll(); err != nil {
				panic(err)
			}

			os.Exit(0)
		}
	}()

	fmt.Printf("Listening for events on %d CPUs with %dx%d of shared memory\n",
		events.Cpus, events.Npages, events.Pagesize)
	fmt.Printf("Press Ctrl-C to quit\n")

	for {
		todo, err := events.Poll(5000)
		if err != nil && err != unix.EINTR {
			panic(err)
		}
		if todo > 0 {
			if err := events.ReadAll(receiveEvent, lostEvent); err != nil {
				fmt.Printf("Error received while reading from perf buffer: %s\n", err)
			}
		}
	}

}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 parser

import (
	"fmt"
	"io"
	"sync"

	"github.com/googlecodelabs/tools/claat/types"
)

// Parser parses a codelab in specific resource format.
// Each parser needs to call Register to become a known parser.
type Parser interface {
	// Parse parses source r into a Codelab for the specified environment env.
	Parse(r io.Reader, opts Options) (*types.Codelab, error)

	// ParseFragment is similar to Parse except it doesn't parse codelab metadata.
	ParseFragment(r io.Reader) ([]types.Node, error)
}

// Container for parsing options.
type Options struct {
	PassMetadata map[string]bool
}

func NewOptions() *Options {
	return &Options{
		PassMetadata: map[string]bool{},
	}
}

var (
	parsersMu sync.Mutex // guards parsers
	parsers   = map[string]Parser{}
)

// Register registers a new parser f under specified name.
// It panics if another parser is already registered under the same name.
func Register(name string, p Parser) {
	parsersMu.Lock()
	defer parsersMu.Unlock()
	if _, exists := parsers[name]; exists {
		panic(fmt.Sprintf("parser %q already registered", name))
	}
	parsers[name] = p
}

// Parsers returns a slice of all registered parser names.
func Parsers() []string {
	parsersMu.Lock()
	defer parsersMu.Unlock()
	p := make([]string, 0, len(parsers))
	for k := range parsers {
		p = append(p, k)
	}
	return p
}

// Parse parses source r into a Codelab using a parser registered with
// the specified name.
func Parse(name string, r io.Reader, opts Options) (*types.Codelab, error) {
	parsersMu.Lock()
	p, ok := parsers[name]
	parsersMu.Unlock()
	if !ok {
		return nil, fmt.Errorf("no parser named %q", name)
	}
	c, err := p.Parse(r, opts)
	if err != nil {
		return nil, err
	}
	c.URL = c.ID
	return c, err
}

// ParseFragment parses a codelab fragment provided in r, using a parser
// registered with the specified name.
func ParseFragment(name string, r io.Reader) ([]types.Node, error) {
	parsersMu.Lock()
	p, ok := parsers[name]
	parsersMu.Unlock()
	if !ok {
		return nil, fmt.Errorf("no parser named %q", name)
	}
	return p.ParseFragment(r)
}
<commit_msg>Create enum type for specifying underlying Markdown parser.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 parser

import (
	"fmt"
	"io"
	"sync"

	"github.com/googlecodelabs/tools/claat/types"
)

// Parser parses a codelab in specific resource format.
// Each parser needs to call Register to become a known parser.
type Parser interface {
	// Parse parses source r into a Codelab for the specified environment env.
	Parse(r io.Reader, opts Options) (*types.Codelab, error)

	// ParseFragment is similar to Parse except it doesn't parse codelab metadata.
	ParseFragment(r io.Reader) ([]types.Node, error)
}

type MarkdownParser int

const (
	Blackfriday MarkdownParser = iota
)

// Container for parsing options.
type Options struct {
	PassMetadata map[string]bool
	MDParser     MarkdownParser
}

func NewOptions() *Options {
	return &Options{
		PassMetadata: map[string]bool{},
		MDParser:     Blackfriday,
	}
}

var (
	parsersMu sync.Mutex // guards parsers
	parsers   = map[string]Parser{}
)

// Register registers a new parser f under specified name.
// It panics if another parser is already registered under the same name.
func Register(name string, p Parser) {
	parsersMu.Lock()
	defer parsersMu.Unlock()
	if _, exists := parsers[name]; exists {
		panic(fmt.Sprintf("parser %q already registered", name))
	}
	parsers[name] = p
}

// Parsers returns a slice of all registered parser names.
func Parsers() []string {
	parsersMu.Lock()
	defer parsersMu.Unlock()
	p := make([]string, 0, len(parsers))
	for k := range parsers {
		p = append(p, k)
	}
	return p
}

// Parse parses source r into a Codelab using a parser registered with
// the specified name.
func Parse(name string, r io.Reader, opts Options) (*types.Codelab, error) {
	parsersMu.Lock()
	p, ok := parsers[name]
	parsersMu.Unlock()
	if !ok {
		return nil, fmt.Errorf("no parser named %q", name)
	}
	c, err := p.Parse(r, opts)
	if err != nil {
		return nil, err
	}
	c.URL = c.ID
	return c, err
}

// ParseFragment parses a codelab fragment provided in r, using a parser
// registered with the specified name.
func ParseFragment(name string, r io.Reader) ([]types.Node, error) {
	parsersMu.Lock()
	p, ok := parsers[name]
	parsersMu.Unlock()
	if !ok {
		return nil, fmt.Errorf("no parser named %q", name)
	}
	return p.ParseFragment(r)
}
<|endoftext|>


<commit_before>package service

import (
	"net"
	"testing"
)

func TestRouter_Prepare(t *testing.T) {
	r := NewRouter()

	err := r.Prepare("")
	if err != ErrServiceExist {
		t.Fatal("expect(error)", ErrServiceExist, "got", err)
	}

	err = r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	service, exist := r.routes["test"]
	if !exist {
		t.Fatal("expect exist got !exist")
	}

	if service.openFn != nil {
		t.Fatal("expect openFn nil")
	}

	if service.closeFn != nil {
		t.Fatal("expect closeFn nil")
	}

	err = r.Prepare("test")
	if err == nil {
		t.Fatal("expect(error)", ErrServiceExist, "got", err)
	}

}

func TestRouter_Add(t *testing.T) {
	r := NewRouter()

	func() {
		defer func() {
			if r := recover(); r != nil {
				return
			}
			t.Fatal("expect panic")
		}()

		r.Add("test", nil, func() error {
			return nil
		})
	}()

	func() {
		defer func() {
			if r := recover(); r != nil {
				return
			}
			t.Fatal("expect panic")
		}()

		r.Add("test", func() (net.Conn, error) {
			return nil, nil
		}, nil)
	}()

	ok := r.Add("test", func() (net.Conn, error) {
		return nil, nil
	}, func() error {
		return nil
	})

	if ok {
		t.Fatal("expect !ok got ok")
	}

	err := r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	ok = r.Add("test", func() (net.Conn, error) {
		return nil, nil
	}, func() error {
		return nil
	})

	if !ok {
		t.Fatal("expect ok got !ok")
	}
}

func TestRouter_Get(t *testing.T) {
	r := NewRouter()
	service := r.Get("test")
	if service != nil {
		t.Fatal("expect nil got", service)
	}

	err := r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	service = r.Get("test")
	if service == nil {
		t.Fatal("expect not nil")
	}
}

func TestRouter_Remove(t *testing.T) {
	r := NewRouter()
	err := r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	_, exist := r.routes["test"]
	if !exist {
		t.Fatal("expect exist got !exist")
	}

	r.Remove("test")
	_, exist = r.routes["test"]
	if exist {
		t.Fatal("expect !exist got exist")
	}

	err = r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	closeCalled := false
	ok := r.Add("test", func() (net.Conn, error) {
		return nil, nil
	}, func() error {
		closeCalled = true
		return nil
	})

	if !ok {
		t.Fatal("expect ok got !ok")
	}

	r.Remove("test")
	if !closeCalled {
		t.Fatal("expect closeCalled got !closeCalled")
	}

	r.Remove("")
}

func TestRouter_All(t *testing.T) {
	must := func(err error) {
		if err != nil {
			t.Fatal(err)
		}
	}
	r := NewRouter()
	must(r.Prepare("abc"))
	must(r.Prepare("dec"))
	must(r.Prepare("23445"))
	must(r.Prepare("test"))

	ss := r.All()

	if len(ss) != 4 {
		t.Fatal(len(ss), "want", 4)
	}

	expectNames := []string{"23445", "abc", "dec", "test"}
	for i, s := range ss {
		if s.Name() != expectNames[i] {
			t.Fatal(s.Name(), "want", expectNames[i])
		}
	}

}
<commit_msg>add unit test for Router.All()<commit_after>package service

import (
	"net"
	"testing"
)

func TestRouter_Prepare(t *testing.T) {
	r := NewRouter()

	err := r.Prepare("")
	if err != ErrServiceExist {
		t.Fatal("expect(error)", ErrServiceExist, "got", err)
	}

	err = r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	service, exist := r.routes["test"]
	if !exist {
		t.Fatal("expect exist got !exist")
	}

	if service.openFn != nil {
		t.Fatal("expect openFn nil")
	}

	if service.closeFn != nil {
		t.Fatal("expect closeFn nil")
	}

	err = r.Prepare("test")
	if err == nil {
		t.Fatal("expect(error)", ErrServiceExist, "got", err)
	}

}

func TestRouter_Add(t *testing.T) {
	r := NewRouter()

	func() {
		defer func() {
			if r := recover(); r != nil {
				return
			}
			t.Fatal("expect panic")
		}()

		r.Add("test", nil, func() error {
			return nil
		})
	}()

	func() {
		defer func() {
			if r := recover(); r != nil {
				return
			}
			t.Fatal("expect panic")
		}()

		r.Add("test", func() (net.Conn, error) {
			return nil, nil
		}, nil)
	}()

	ok := r.Add("test", func() (net.Conn, error) {
		return nil, nil
	}, func() error {
		return nil
	})

	if ok {
		t.Fatal("expect !ok got ok")
	}

	err := r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	ok = r.Add("test", func() (net.Conn, error) {
		return nil, nil
	}, func() error {
		return nil
	})

	if !ok {
		t.Fatal("expect ok got !ok")
	}
}

func TestRouter_Get(t *testing.T) {
	r := NewRouter()
	service := r.Get("test")
	if service != nil {
		t.Fatal("expect nil got", service)
	}

	err := r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	service = r.Get("test")
	if service == nil {
		t.Fatal("expect not nil")
	}
}

func TestRouter_Remove(t *testing.T) {
	r := NewRouter()
	err := r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	_, exist := r.routes["test"]
	if !exist {
		t.Fatal("expect exist got !exist")
	}

	r.Remove("test")
	_, exist = r.routes["test"]
	if exist {
		t.Fatal("expect !exist got exist")
	}

	err = r.Prepare("test")
	if err != nil {
		t.Fatal(err)
	}

	closeCalled := false
	ok := r.Add("test", func() (net.Conn, error) {
		return nil, nil
	}, func() error {
		closeCalled = true
		return nil
	})

	if !ok {
		t.Fatal("expect ok got !ok")
	}

	r.Remove("test")
	if !closeCalled {
		t.Fatal("expect closeCalled got !closeCalled")
	}

	r.Remove("")
}

func TestRouter_All(t *testing.T) {
	must := func(err error) {
		if err != nil {
			t.Fatal(err)
		}
	}

	func() {
		r := NewRouter()
		ss := r.All()
		if len(ss) != 0 {
			t.Fatal(len(ss), "want", 0)
		}
	}()

	func() {
		r := NewRouter()
		must(r.Prepare("abc"))
		must(r.Prepare("dec"))
		must(r.Prepare("23445"))
		must(r.Prepare("test"))

		ss := r.All()

		if len(ss) != 4 {
			t.Fatal(len(ss), "want", 4)
		}

		expectNames := []string{"23445", "abc", "dec", "test"}
		for i, s := range ss {
			if s.Name() != expectNames[i] {
				t.Fatal(s.Name(), "want", expectNames[i])
			}
		}

	}()
}
<|endoftext|>


<commit_before>package endly

import (
	"fmt"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/data"
	"strings"
)

//DsUnitTableData represents table data
type DsUnitTableData struct {
	Table         string
	Value         interface{}
	AutoGenerate  map[string]string `json:",omitempty"`
	PostIncrement []string          `json:",omitempty"`
	Key           string
}

//AutoGenerateIfNeeded retrieves auto generated values
func (d *DsUnitTableData) AutoGenerateIfNeeded(state data.Map) error {
	for k, v := range d.AutoGenerate {
		value, has := state.GetValue(v)
		if !has {
			return fmt.Errorf("failed to autogenerate value for %v - unable to eval: %v", k, v)
		}
		state.SetValue(k, value)
	}
	return nil
}

//PostIncrementIfNeeded increments all specified counters by one.
func (d *DsUnitTableData) PostIncrementIfNeeded(state data.Map) {
	for _, key := range d.PostIncrement {
		keyText := toolbox.AsString(key)
		value, has := state.GetValue(keyText)
		if !has {
			value = 0
		}
		state.SetValue(keyText, toolbox.AsInt(value)+1)
	}
}

//GetValues a table records.
func (d *DsUnitTableData) GetValues(state data.Map) []map[string]interface{} {
	if toolbox.IsMap(d.Value) {
		var value = d.GetValue(state, d.Value)
		if len(value) == 0 {
			return []map[string]interface{}{}
		}
		return []map[string]interface{}{
			value,
		}
	}
	var result = make([]map[string]interface{}, 0)
	if toolbox.IsSlice(d.Value) {
		var aSlice = toolbox.AsSlice(d.Value)
		for _, item := range aSlice {
			value := d.GetValue(state, item)
			if len(value) > 0 {
				result = append(result, value)
			}
		}
	}
	return result
}

func (d *DsUnitTableData) expandThis(textValue string, value map[string]interface{}) interface{} {
	if strings.Contains(textValue, "this.") {
		var thisState = data.NewMap()
		for subKey, subValue := range value {
			if toolbox.IsString(subValue) {
				subKeyTextValue := toolbox.AsString(subValue)
				if !strings.Contains(subKeyTextValue, "this") {
					thisState.SetValue(fmt.Sprintf("this.%v", subKey), subKeyTextValue)
				}
			}
		}
		return thisState.Expand(textValue)
	}
	return textValue
}

//GetValue returns record.
func (d *DsUnitTableData) GetValue(state data.Map, source interface{}) map[string]interface{} {
	value := toolbox.AsMap(state.Expand(source))
	for k, v := range value {
		var textValue = toolbox.AsString(v)
		if strings.Contains(textValue, "this") {
			value[k] = d.expandThis(textValue, value)
		} else if strings.HasPrefix(textValue, "$") {
			delete(value, k)
		} else if strings.HasPrefix(textValue, "\\$") {
			value[k] = string(textValue[1:])
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var key = d.Key
	if key == "" {
		key = d.Table
	}
	if !dataStoreState.Has(key) {
		dataStoreState.Put(key, data.NewCollection())
	}

	records := dataStoreState.GetCollection(key)
	records.Push(value)
	return value
}

//AsTableRecords converts source into slice of *DsUnitTableData to create dsunit data as map[string][]map[string]interface{} (table with records)
func AsTableRecords(source interface{}, state data.Map) (interface{}, error) {
	var result = make(map[string][]map[string]interface{})
	if source == nil {
		return nil, reportError(fmt.Errorf("source was nil"))
	}
	if !state.Has(DataStoreUnitServiceID) {
		state.Put(DataStoreUnitServiceID, data.NewMap())
	}

	var prepareTableData, ok = source.([]*DsUnitTableData)

	if !ok {
		prepareTableData = make([]*DsUnitTableData, 0)
		err := converter.AssignConverted(&prepareTableData, source)
		if err != nil {
			return nil, err
		}
	}
	for _, tableData := range prepareTableData {
		var table = tableData.Table
		err := tableData.AutoGenerateIfNeeded(state)
		if err != nil {
			return nil, err
		}
		var values = tableData.GetValues(state)
		if len(values) > 0 {
			result[table] = append(result[table], values...)
			tableData.PostIncrementIfNeeded(state)
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var variable = &Variable{
		Name:    DataStoreUnitServiceID,
		Persist: true,
		Value:   dataStoreState,
	}
	err := variable.PersistValue()
	if err != nil {
		return nil, err
	}
	return result, nil
}
<commit_msg>updated AsTable from taking data strucute to a key from session pointing to data<commit_after>package endly

import (
	"fmt"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/data"
	"strings"
)

//DsUnitTableData represents table data
type DsUnitTableData struct {
	Table         string
	Value         interface{}
	AutoGenerate  map[string]string `json:",omitempty"`
	PostIncrement []string          `json:",omitempty"`
	Key           string
}

//AutoGenerateIfNeeded retrieves auto generated values
func (d *DsUnitTableData) AutoGenerateIfNeeded(state data.Map) error {
	for k, v := range d.AutoGenerate {
		value, has := state.GetValue(v)
		if !has {
			return fmt.Errorf("failed to autogenerate value for %v - unable to eval: %v", k, v)
		}
		state.SetValue(k, value)
	}
	return nil
}

//PostIncrementIfNeeded increments all specified counters by one.
func (d *DsUnitTableData) PostIncrementIfNeeded(state data.Map) {
	for _, key := range d.PostIncrement {
		keyText := toolbox.AsString(key)
		value, has := state.GetValue(keyText)
		if !has {
			value = 0
		}
		state.SetValue(keyText, toolbox.AsInt(value)+1)
	}
}

//GetValues a table records.
func (d *DsUnitTableData) GetValues(state data.Map) []map[string]interface{} {
	if toolbox.IsMap(d.Value) {
		var value = d.GetValue(state, d.Value)
		if len(value) == 0 {
			return []map[string]interface{}{}
		}
		return []map[string]interface{}{
			value,
		}
	}
	var result = make([]map[string]interface{}, 0)
	if toolbox.IsSlice(d.Value) {
		var aSlice = toolbox.AsSlice(d.Value)
		for _, item := range aSlice {
			value := d.GetValue(state, item)
			if len(value) > 0 {
				result = append(result, value)
			}
		}
	}
	return result
}

func (d *DsUnitTableData) expandThis(textValue string, value map[string]interface{}) interface{} {
	if strings.Contains(textValue, "this.") {
		var thisState = data.NewMap()
		for subKey, subValue := range value {
			if toolbox.IsString(subValue) {
				subKeyTextValue := toolbox.AsString(subValue)
				if !strings.Contains(subKeyTextValue, "this") {
					thisState.SetValue(fmt.Sprintf("this.%v", subKey), subKeyTextValue)
				}
			}
		}
		return thisState.Expand(textValue)
	}
	return textValue
}

//GetValue returns record.
func (d *DsUnitTableData) GetValue(state data.Map, source interface{}) map[string]interface{} {
	value := toolbox.AsMap(state.Expand(source))
	for k, v := range value {
		var textValue = toolbox.AsString(v)
		if strings.Contains(textValue, "this") {
			value[k] = d.expandThis(textValue, value)
		} else if strings.HasPrefix(textValue, "$") {
			delete(value, k)
		} else if strings.HasPrefix(textValue, "\\$") {
			value[k] = string(textValue[1:])
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var key = d.Key
	if key == "" {
		key = d.Table
	}
	if !dataStoreState.Has(key) {
		dataStoreState.Put(key, data.NewCollection())
	}

	records := dataStoreState.GetCollection(key)
	records.Push(value)
	return value
}

//AsTableRecords converts data spcified by dataKey into slice of *DsUnitTableData to create dsunit data as map[string][]map[string]interface{} (table with records)
func AsTableRecords(dataKey interface{}, state data.Map) (interface{}, error) {
	var result = make(map[string][]map[string]interface{})
	if state == nil {
		return nil, fmt.Errorf("state was nil")
	}

	source, has := state.GetValue(toolbox.AsString(dataKey))
	if !has || source == nil {
		return nil, reportError(fmt.Errorf("value for specified key was empty: %v", dataKey))
	}

	if !state.Has(DataStoreUnitServiceID) {
		state.Put(DataStoreUnitServiceID, data.NewMap())
	}

	var prepareTableData, ok = source.([]*DsUnitTableData)

	if !ok {
		prepareTableData = make([]*DsUnitTableData, 0)
		err := converter.AssignConverted(&prepareTableData, source)
		if err != nil {
			return nil, err
		}
	}
	for _, tableData := range prepareTableData {
		var table = tableData.Table
		err := tableData.AutoGenerateIfNeeded(state)
		if err != nil {
			return nil, err
		}
		var values = tableData.GetValues(state)
		if len(values) > 0 {
			result[table] = append(result[table], values...)
			tableData.PostIncrementIfNeeded(state)
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var variable = &Variable{
		Name:    DataStoreUnitServiceID,
		Persist: true,
		Value:   dataStoreState,
	}
	err := variable.PersistValue()
	if err != nil {
		return nil, err
	}
	return result, nil
}
<|endoftext|>


<commit_before>package clienttest

import (
	"fmt"
	"time"

	check "gopkg.in/check.v1"

	"github.com/radanalyticsio/oshinko-cli/rest/client/clusters"
	"github.com/radanalyticsio/oshinko-cli/rest/helpers/errors"
	"github.com/radanalyticsio/oshinko-cli/rest/models"
)

type lessThanChecker struct {
	*check.CheckerInfo
}

// The LessThan checker attempts to determine if the observed value is
// less than the expected. It will only attempt this on values that can be
// cast as int64.
var LessThan check.Checker = &lessThanChecker{
	&check.CheckerInfo{Name: "LessThan", Params: []string{"obtained", "compare"}},
}

func (checker *lessThanChecker) Check(params []interface{}, names []string) (result bool, error string) {
	defer func() {
		if v := recover(); v != nil {
			result = false
			error = fmt.Sprint(v)
		}
	}()
	return params[0].(int) < params[1].(int), ""
}

func (s *OshinkoRestTestSuite) TestCreateAndDeleteCluster(c *check.C) {
	cname := "e2ecluster"
	mcount := int64(1)
	wcount := int64(3)

	cconfig := models.NewClusterConfig{MasterCount: mcount, WorkerCount: wcount}
	cdetails := models.NewCluster{Name: &cname, Config: &cconfig}
	clparams := clusters.NewCreateClusterParams().WithCluster(&cdetails)

	// create a cluster
	_, err := s.cli.Clusters.CreateCluster(clparams)
	if err != nil {
		msg := err.(*clusters.CreateClusterDefault).Error() + "\n"
		for _, e := range err.(*clusters.CreateClusterDefault).Payload.Errors {
			msg += errors.SingleErrorToString(e)
		}
		c.Fatal(msg)
	}

	// read the cluster details
	// because it may take some time for the pods to become available, we
	// must loop and try multiple times to read them. if we fail to read
	// them after a set number of retries, we consider the test to have
	// failed.
	const retries = 30
	var tries int
	obsmcount, obswcount := int64(0), int64(0)
	cldparams := clusters.NewFindSingleClusterParams().WithName(cname)
	for tries = 0; tries < retries; tries++ {
		cldresult, err := s.cli.Clusters.FindSingleCluster(cldparams)
		if err != nil {
			msg := fmt.Sprintf("%s \n %+v",
				err.(*clusters.FindSingleClusterDefault).Error(),
				err.(*clusters.FindSingleClusterDefault).Payload.Errors)
			c.Fatal(msg)
		}

		// if enough pods are available, we loop through them and exit
		// the retry loop, otherwise sleep for 1 second.
		if len(cldresult.Payload.Cluster.Pods) >= int(mcount+wcount) {
			// loop through the pods to count workers and masters
			obsmcount = 0
			obswcount = 0
			for _, pod := range cldresult.Payload.Cluster.Pods {
				switch *pod.Type {
				case "master":
					if *pod.Status == "Running" {
						obsmcount += 1
					}
				case "worker":
					if *pod.Status == "Running" {
						obswcount += 1
					}
				}
			}
			if obsmcount+obswcount >= mcount+wcount {
				break
			}
		}

		time.Sleep(1 * time.Second)
	}

	c.Assert(tries, LessThan, retries)
	c.Assert(obsmcount, check.Equals, mcount)
	c.Assert(obswcount, check.Equals, wcount)

	// delete the cluster
	delparams := clusters.NewDeleteSingleClusterParams().WithName(cname)
	_, err = s.cli.Clusters.DeleteSingleCluster(delparams)
	if err != nil {
		switch err.(type) {
		case *clusters.DeleteSingleClusterDefault:
			c.Fatal(err.(*clusters.DeleteSingleClusterDefault).Error())
		default:
			c.Fatal(err)
		}
	}

	// confirm delete
	obsclcount := 0
	for tries = 0; tries < retries; tries++ {
		fcresult, err := s.cli.Clusters.FindClusters(nil)
		if err != nil {
			c.Fatal(err.(*clusters.FindClustersDefault).Error())
		}
		if obsclcount = len(fcresult.Payload.Clusters); obsclcount == 0 {
			break
		}
		time.Sleep(1 * time.Second)
	}

	c.Assert(tries, LessThan, retries)
	expclcount := 0
	c.Assert(obsclcount, check.Equals, expclcount)
}
<commit_msg>add scaling to the client tests<commit_after>package clienttest

import (
	"fmt"
	"time"

	check "gopkg.in/check.v1"

	"github.com/radanalyticsio/oshinko-cli/rest/client/clusters"
	"github.com/radanalyticsio/oshinko-cli/rest/helpers/errors"
	"github.com/radanalyticsio/oshinko-cli/rest/models"
)

type lessThanChecker struct {
	*check.CheckerInfo
}

// The LessThan checker attempts to determine if the observed value is
// less than the expected. It will only attempt this on values that can be
// cast as int64.
var LessThan check.Checker = &lessThanChecker{
	&check.CheckerInfo{Name: "LessThan", Params: []string{"obtained", "compare"}},
}

func (checker *lessThanChecker) Check(params []interface{}, names []string) (result bool, error string) {
	defer func() {
		if v := recover(); v != nil {
			result = false
			error = fmt.Sprint(v)
		}
	}()
	return params[0].(int) < params[1].(int), ""
}

func (s *OshinkoRestTestSuite) TestCreateAndDeleteCluster(c *check.C) {
	cname := "e2ecluster"
	mcount := int64(1)
	wcount := int64(3)

	cconfig := models.NewClusterConfig{MasterCount: mcount, WorkerCount: wcount}
	cdetails := models.NewCluster{Name: &cname, Config: &cconfig}
	clparams := clusters.NewCreateClusterParams().WithCluster(&cdetails)

	// create a cluster
	_, err := s.cli.Clusters.CreateCluster(clparams)
	if err != nil {
		msg := err.(*clusters.CreateClusterDefault).Error() + "\n"
		for _, e := range err.(*clusters.CreateClusterDefault).Payload.Errors {
			msg += errors.SingleErrorToString(e)
		}
		c.Fatal(msg)
	}

	// read the cluster details
	// because it may take some time for the pods to become available, we
	// must loop and try multiple times to read them. if we fail to read
	// them after a set number of retries, we consider the test to have
	// failed.
	const retries = 30
	var tries int
	obsmcount, obswcount := int64(0), int64(0)
	cldparams := clusters.NewFindSingleClusterParams().WithName(cname)
	for tries = 0; tries < retries; tries++ {
		cldresult, err := s.cli.Clusters.FindSingleCluster(cldparams)
		if err != nil {
			msg := fmt.Sprintf("%s \n %+v",
				err.(*clusters.FindSingleClusterDefault).Error(),
				err.(*clusters.FindSingleClusterDefault).Payload.Errors)
			c.Fatal(msg)
		}

		// if enough pods are available, we loop through them and exit
		// the retry loop, otherwise sleep for 1 second.
		if len(cldresult.Payload.Cluster.Pods) >= int(mcount+wcount) {
			// loop through the pods to count workers and masters
			obsmcount = 0
			obswcount = 0
			for _, pod := range cldresult.Payload.Cluster.Pods {
				switch *pod.Type {
				case "master":
					if *pod.Status == "Running" {
						obsmcount += 1
					}
				case "worker":
					if *pod.Status == "Running" {
						obswcount += 1
					}
				}
			}
			if obsmcount+obswcount >= mcount+wcount {
				break
			}
		}

		time.Sleep(1 * time.Second)
	}

	c.Assert(tries, LessThan, retries)
	c.Assert(obsmcount, check.Equals, mcount)
	c.Assert(obswcount, check.Equals, wcount)

	// scale the cluster
	// this will attempt to scale up the number of workers by 1. as with
	// the creation test, this test will loop for a number of retries to
	// give time for the new worker to be created.
	uwcount := int64(wcount + 1)
	ucconfig := models.NewClusterConfig{MasterCount: mcount, WorkerCount: uwcount}
	ucdetails := models.NewCluster{Name: &cname, Config: &ucconfig}
	uclparams := clusters.NewUpdateSingleClusterParams().WithCluster(&ucdetails).WithName(cname)

	// update the cluster
	_, err = s.cli.Clusters.UpdateSingleCluster(uclparams)
	if err != nil {
		msg := err.(*clusters.UpdateSingleClusterDefault).Error() + "\n"
		for _, e := range err.(*clusters.UpdateSingleClusterDefault).Payload.Errors {
			msg += errors.SingleErrorToString(e)
		}
		c.Fatal(msg)
	}

	// check for update completion
	obsmcount, obswcount = int64(0), int64(0)
	for tries = 0; tries < retries; tries++ {
		cldresult, err := s.cli.Clusters.FindSingleCluster(cldparams)
		if err != nil {
			msg := fmt.Sprintf("%s \n %+v",
				err.(*clusters.FindSingleClusterDefault).Error(),
				err.(*clusters.FindSingleClusterDefault).Payload.Errors)
			c.Fatal(msg)
		}

		// if enough pods are available, we loop through them and exit
		// the retry loop, otherwise sleep for 1 second.
		if len(cldresult.Payload.Cluster.Pods) >= int(mcount+uwcount) {
			// loop through the pods to count workers and masters
			obsmcount = 0
			obswcount = 0
			for _, pod := range cldresult.Payload.Cluster.Pods {
				switch *pod.Type {
				case "master":
					if *pod.Status == "Running" {
						obsmcount += 1
					}
				case "worker":
					if *pod.Status == "Running" {
						obswcount += 1
					}
				}
			}
			if obsmcount+obswcount >= mcount+uwcount {
				break
			}
		}

		time.Sleep(1 * time.Second)
	}

	c.Assert(tries, LessThan, retries)
	c.Assert(obsmcount, check.Equals, mcount)
	c.Assert(obswcount, check.Equals, uwcount)

	// delete the cluster
	delparams := clusters.NewDeleteSingleClusterParams().WithName(cname)
	_, err = s.cli.Clusters.DeleteSingleCluster(delparams)
	if err != nil {
		switch err.(type) {
		case *clusters.DeleteSingleClusterDefault:
			c.Fatal(err.(*clusters.DeleteSingleClusterDefault).Error())
		default:
			c.Fatal(err)
		}
	}

	// confirm delete
	obsclcount := 0
	for tries = 0; tries < retries; tries++ {
		fcresult, err := s.cli.Clusters.FindClusters(nil)
		if err != nil {
			c.Fatal(err.(*clusters.FindClustersDefault).Error())
		}
		if obsclcount = len(fcresult.Payload.Clusters); obsclcount == 0 {
			break
		}
		time.Sleep(1 * time.Second)
	}

	c.Assert(tries, LessThan, retries)
	expclcount := 0
	c.Assert(obsclcount, check.Equals, expclcount)
}
<|endoftext|>


<commit_before>package test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"testing"
	"time"
)

type dockerfile struct {
	// Local fs path to the Dockerfile
	base string

	// Commands represents a series of commands to be ran in the image
	commands []*Cmd

	// -t flag with build/run
	tag string

	// any errors specific to the dockerfile from `docker` commands
	err error

	// only run build, tag and run steps once
	wg sync.WaitGroup
}

func Dockerfile(where string) *dockerfile {
	if !strings.HasSuffix(where, "Dockerfile") {
		where = filepath.Join(where, "/Dockerfile")
	}

	// Grab the env name (e.g. envs/$env_name/Dockerfile)
	dir, _ := filepath.Split(where)
	now := time.Now().Unix()
	tag := fmt.Sprintf("cert-manage:%s-%d", filepath.Base(dir), now)

	return &dockerfile{
		base: where,
		tag:  tag,
	}
}

func (d *dockerfile) Run(cmd string, args ...string) {
	d.commands = append(d.commands, Command(cmd, args...))
}

func (d *dockerfile) CertManage(args ...string) {
	d.Run("/cert-manage", args...)
}

func (d *dockerfile) SuccessT(t *testing.T) {
	if runtime.GOOS == "darwin" {
		err := exec.Command("docker", "verison").Run()
		if err == nil {
			t.Fatal("travis-ci supports docker on OSX?? - https://docs.travis-ci.com/user/docker/")
		}
		if inCI() {
			t.Skip("travis-ci doesn't support docker on OSX - https://docs.travis-ci.com/user/docker/")
		}
	}

	d.prep()
	t.Helper()

	if d.err != nil {
		t.Fatal(d.err)
	}

	for i := range d.commands {
		d.commands[i].SuccessT(t)
	}
}

func (d *dockerfile) build() {
	d.wg.Add(1)
	defer d.wg.Done()

	// Copy our original image's contents into the dst file
	dir, err := ioutil.TempDir("", d.tag)
	if err != nil {
		d.err = fmt.Errorf("tempfile create err=%v", err)
		return
	}
	dst, err := os.Create(filepath.Join(dir, "Dockerfile"))
	if err != nil {
		d.err = fmt.Errorf("tmp Dockerfile create err=%v", err)
		return
	}
	defer os.Remove(dst.Name())

	src, err := os.Open(d.base)
	if err != nil {
		d.err = fmt.Errorf("tmpfile open err=%v", err)
		return
	}
	if _, err := io.Copy(dst, src); err != nil {
		d.err = fmt.Errorf("src->dst copy err=%v", err)
		return
	}
	if err := src.Close(); err != nil {
		d.err = fmt.Errorf("src close err=%v", err)
		return
	}

	// Add all commands to the Dockerfile
	command := "CMD exit 0"
	for i := range d.commands {
		command += fmt.Sprintf(" && %s %s", d.commands[i].command, strings.Join(d.commands[i].args, " "))
	}
	if _, err := dst.WriteString(command); err != nil {
		d.err = fmt.Errorf("command=%s err=%v", command, err)
		return
	}

	// Force all writes into our Dockerfile
	if err := dst.Sync(); err != nil {
		d.err = fmt.Errorf("dst fsync err=%v", err)
		return
	}

	cmd := exec.Command("docker", "build", "-t", d.tag, dir)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		d.err = fmt.Errorf("ERROR: err=%v\nOutput: %s", err, stderr.String())
	}
}

func (d *dockerfile) run() {
	d.wg.Add(1)
	defer d.wg.Done()

	// don't attempt anything if we've already failed
	if d.err != nil {
		return
	}

	cmd := exec.Command("docker", "run", "-t", d.tag)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		d.err = fmt.Errorf("ERROR: err=%v\nOutput: %s", err, stderr.String())
	}
}

func (d *dockerfile) prep() {
	d.build()
	d.run()
	d.wg.Wait()
}
<commit_msg>test: skip docker tests if not running dockerd<commit_after>package test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"testing"
	"time"
)

type dockerfile struct {
	// Local fs path to the Dockerfile
	base string

	// Commands represents a series of commands to be ran in the image
	commands []*Cmd

	// -t flag with build/run
	tag string

	// any errors specific to the dockerfile from `docker` commands
	err error

	// only run build, tag and run steps once
	wg sync.WaitGroup
}

func Dockerfile(where string) *dockerfile {
	if !strings.HasSuffix(where, "Dockerfile") {
		where = filepath.Join(where, "/Dockerfile")
	}

	// Grab the env name (e.g. envs/$env_name/Dockerfile)
	dir, _ := filepath.Split(where)
	now := time.Now().Unix()
	tag := fmt.Sprintf("cert-manage:%s-%d", filepath.Base(dir), now)

	return &dockerfile{
		base: where,
		tag:  tag,
	}
}

func (d *dockerfile) Run(cmd string, args ...string) {
	d.commands = append(d.commands, Command(cmd, args...))
}

func (d *dockerfile) CertManage(args ...string) {
	d.Run("/cert-manage", args...)
}

func (d *dockerfile) SuccessT(t *testing.T) {
	if runtime.GOOS == "darwin" {
		err := exec.Command("docker", "verison").Run()
		if err == nil {
			t.Fatal("travis-ci supports docker on OSX?? - https://docs.travis-ci.com/user/docker/")
		}
		if inCI() {
			t.Skip("travis-ci doesn't support docker on OSX - https://docs.travis-ci.com/user/docker/")
		}
	}

	if !d.enabled() {
		t.Skip("docker isn't enabled")
	}

	d.prep()
	t.Helper()

	if d.err != nil {
		t.Fatal(d.err)
	}

	for i := range d.commands {
		d.commands[i].SuccessT(t)
	}
}

func (d *dockerfile) build() {
	d.wg.Add(1)
	defer d.wg.Done()

	// Copy our original image's contents into the dst file
	dir, err := ioutil.TempDir("", d.tag)
	if err != nil {
		d.err = fmt.Errorf("tempfile create err=%v", err)
		return
	}
	dst, err := os.Create(filepath.Join(dir, "Dockerfile"))
	if err != nil {
		d.err = fmt.Errorf("tmp Dockerfile create err=%v", err)
		return
	}
	defer os.Remove(dst.Name())

	src, err := os.Open(d.base)
	if err != nil {
		d.err = fmt.Errorf("tmpfile open err=%v", err)
		return
	}
	if _, err := io.Copy(dst, src); err != nil {
		d.err = fmt.Errorf("src->dst copy err=%v", err)
		return
	}
	if err := src.Close(); err != nil {
		d.err = fmt.Errorf("src close err=%v", err)
		return
	}

	// Add all commands to the Dockerfile
	command := "CMD exit 0"
	for i := range d.commands {
		command += fmt.Sprintf(" && %s %s", d.commands[i].command, strings.Join(d.commands[i].args, " "))
	}
	if _, err := dst.WriteString(command); err != nil {
		d.err = fmt.Errorf("command=%s err=%v", command, err)
		return
	}

	// Force all writes into our Dockerfile
	if err := dst.Sync(); err != nil {
		d.err = fmt.Errorf("dst fsync err=%v", err)
		return
	}

	cmd := exec.Command("docker", "build", "-t", d.tag, dir)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		d.err = fmt.Errorf("ERROR: err=%v\nOutput: %s", err, stderr.String())
	}
}

func (d *dockerfile) run() {
	d.wg.Add(1)
	defer d.wg.Done()

	// don't attempt anything if we've already failed
	if d.err != nil {
		return
	}

	cmd := exec.Command("docker", "run", "-t", d.tag)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		d.err = fmt.Errorf("ERROR: err=%v\nOutput: %s", err, stderr.String())
	}
}

func (d *dockerfile) prep() {
	d.build()
	d.run()
	d.wg.Wait()
}

func (d *dockerfile) enabled() bool {
	out, _ := exec.Command("docker", "ps").CombinedOutput()
	if bytes.Contains(out, []byte("Cannot connect to the Docker daemon")) {
		return false
	}
	return true
}
<|endoftext|>