<commit_before>package processor

import (
	"bufio"
	"github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
	"github.com/gaia-docker/tugbot-collect/log"
	"golang.org/x/net/context"
	"io"
	"os"
	"path/filepath"
	"strings"
)

var logger = log.GetLogger("processor")

//Process any container that is pushed to the Tasks channel -
//collecting the results and write to disk / publish to the results service
type Processor struct {
	Tasks            chan string
	dockerClient     *client.Client
	outputDir        string
	resultServiceUrl string
	resultsDirLabel  string
	dockerRM         bool
}

//NewProcessor create new Processor and allocates Tasks buffered channel in size 10 to it
func NewProcessor(pDockerClient *client.Client, pOutputDir string, pResultServiceUrl string, pResultsDirLabel string, pDockerRM bool) Processor {
	p := Processor{
		dockerClient:     pDockerClient,
		outputDir:        pOutputDir,
		resultServiceUrl: pResultServiceUrl,
		resultsDirLabel:  pResultsDirLabel,
		dockerRM:         pDockerRM,
	}
	p.Tasks = make(chan string, 10)
	return p
}

//Run the processor (listen to the Tasks channel and performs the collection)
func (p Processor) Run() {
	go func() {
		for task := range p.Tasks {

			//We run each task in a separate goroutine to parallel the extraction
			go func(contId string) {
				logger.Info("processor is going to extract results from container with id: ", contId)

				ctx, cancel := context.WithCancel(context.Background())
				defer cancel()

				contInfo, err := p.dockerClient.ContainerInspect(ctx, contId)
				if err != nil {
					logger.Error("failed to inspect container with id: ", contId, ", cannot determine results dir location - discard processing this container")
					return
				}

				//copy the result dir from inside the container into memory
				//The result dir will be return in tar format
				resultDir := contInfo.Config.Labels[p.resultsDirLabel]
				logger.Info("going to extract results for container with id: ", contId, ", from this location inside the test container: ", resultDir)
				reader, pathstat, err := p.dockerClient.CopyFromContainer(ctx, contId, resultDir)
				if err != nil {
					logger.Error("failed to copy result dir from container with id: ", contId, ", error is: ", err, " - discard processing this container")
					return
				}

				//check that the resultdir is really a directory
				if !pathstat.Mode.IsDir() {
					logger.Error("results location:", resultDir, ", inside the container with id: ", contId, ", is not a directory - discard processing of this container")
					return
				}

				//write the results to disk
				writeToDiskStatus := make(chan error)
				writeToDisk(p.outputDir, contInfo.Config.Image, contId, reader, writeToDiskStatus)
				if <-writeToDiskStatus != nil {
					logger.Error("failed to write to disk")
					return
				}

				logger.Info("sucessfully extracted results from container with id: ", contId)

				if p.dockerRM {
					err = p.dockerClient.ContainerRemove(ctx, contId, types.ContainerRemoveOptions{})
					if err != nil {
						logger.Error("failed to remove container with id: ", contId, ", why: ", err)
						return
					}

					logger.Info("sucessfully removed (docker rm) container with id: ", contId)
				}
			}(task)
		}
	}()
}

func writeToDisk(outputDir, imageName, contId string, reader io.ReadCloser, returnVal chan error) {

	go func() {
		if outputDir == "/dev/null" {
			logger.Info("output dir is ", outputDir, ", skip writing to disk")
			returnVal <- nil
			return
		}

		//create output dir (is dir is already exist MkdirAll will return nil
		outDirFullPath := outputDir + string(filepath.Separator) + strings.Replace(imageName, "/", "_", -1) + "-" + contId[:11]
		err := os.MkdirAll(outDirFullPath, 0777)
		if err != nil {
			logger.Error("failed to create output dir: ", outDirFullPath, ", for container with id: ", contId, ", error is: ", err, " - discard processing this container")
			returnVal <- err
			return
		}
		logger.Info("going to write results from container with id: ", contId, ", into this location: ", outDirFullPath)

		// open output file
		fo, err := os.Create(outDirFullPath + string(filepath.Separator) + "results.tar")
		if err != nil {
			logger.Error("failed to create tar file on FS for container with id: ", contId, ", error is: ", err, " - discard processing this container")
			returnVal <- err
			return
		}
		// close fo on exit and check for its returned error
		defer func() {
			if err := fo.Close(); err != nil {
				logger.Error("failed to close FS tar file for container with id: ", contId, ", error is: ", err)
			}
		}()

		// make a buffer to keep chunks that are read
		// buffer size==32K
		buf := make([]byte, 32*1024)
		writer := bufio.NewWriter(fo)

		if _, err := io.CopyBuffer(writer, reader, buf); err != nil {
			logger.Error("failed to write to tar file for container with id: ", contId, ", error is: ", err, " - discard processing this container")
			returnVal <- err
			return
		}

		//All is good, returning nil on the channel
		returnVal <- nil
	}()
}
<commit_msg>Add comments to public interfaces<commit_after>package processor

import (
	"bufio"
	"github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
	"github.com/gaia-docker/tugbot-collect/log"
	"golang.org/x/net/context"
	"io"
	"os"
	"path/filepath"
	"strings"
)

var logger = log.GetLogger("processor")

//Processor is a struct to hold the Tasks channel
//You should use NewProcessor to allocate new one and the Run func to run it
type Processor struct {
	Tasks            chan string
	dockerClient     *client.Client
	outputDir        string
	resultServiceUrl string
	resultsDirLabel  string
	dockerRM         bool
}

//NewProcessor create new Processor and allocates Tasks buffered channel in size 10 to it
func NewProcessor(pDockerClient *client.Client, pOutputDir string, pResultServiceUrl string, pResultsDirLabel string, pDockerRM bool) Processor {
	p := Processor{
		dockerClient:     pDockerClient,
		outputDir:        pOutputDir,
		resultServiceUrl: pResultServiceUrl,
		resultsDirLabel:  pResultsDirLabel,
		dockerRM:         pDockerRM,
	}
	p.Tasks = make(chan string, 10)
	return p
}

//Run the processor (listen to the Tasks channel and performs the collection)
func (p Processor) Run() {
	go func() {
		for task := range p.Tasks {

			//We run each task in a separate goroutine to parallel the extraction
			go func(contId string) {
				logger.Info("processor is going to extract results from container with id: ", contId)

				ctx, cancel := context.WithCancel(context.Background())
				defer cancel()

				contInfo, err := p.dockerClient.ContainerInspect(ctx, contId)
				if err != nil {
					logger.Error("failed to inspect container with id: ", contId, ", cannot determine results dir location - discard processing this container")
					return
				}

				//copy the result dir from inside the container into memory
				//The result dir will be return in tar format
				resultDir := contInfo.Config.Labels[p.resultsDirLabel]
				logger.Info("going to extract results for container with id: ", contId, ", from this location inside the test container: ", resultDir)
				reader, pathstat, err := p.dockerClient.CopyFromContainer(ctx, contId, resultDir)
				if err != nil {
					logger.Error("failed to copy result dir from container with id: ", contId, ", error is: ", err, " - discard processing this container")
					return
				}

				//check that the resultdir is really a directory
				if !pathstat.Mode.IsDir() {
					logger.Error("results location:", resultDir, ", inside the container with id: ", contId, ", is not a directory - discard processing of this container")
					return
				}

				//write the results to disk
				writeToDiskStatus := make(chan error)
				writeToDisk(p.outputDir, contInfo.Config.Image, contId, reader, writeToDiskStatus)
				if <-writeToDiskStatus != nil {
					logger.Error("failed to write to disk")
					return
				}

				logger.Info("sucessfully extracted results from container with id: ", contId)

				if p.dockerRM {
					err = p.dockerClient.ContainerRemove(ctx, contId, types.ContainerRemoveOptions{})
					if err != nil {
						logger.Error("failed to remove container with id: ", contId, ", why: ", err)
						return
					}

					logger.Info("sucessfully removed (docker rm) container with id: ", contId)
				}
			}(task)
		}
	}()
}

func writeToDisk(outputDir, imageName, contId string, reader io.ReadCloser, returnVal chan error) {

	go func() {
		if outputDir == "/dev/null" {
			logger.Info("output dir is ", outputDir, ", skip writing to disk")
			returnVal <- nil
			return
		}

		//create output dir (is dir is already exist MkdirAll will return nil
		outDirFullPath := outputDir + string(filepath.Separator) + strings.Replace(imageName, "/", "_", -1) + "-" + contId[:11]
		err := os.MkdirAll(outDirFullPath, 0777)
		if err != nil {
			logger.Error("failed to create output dir: ", outDirFullPath, ", for container with id: ", contId, ", error is: ", err, " - discard processing this container")
			returnVal <- err
			return
		}
		logger.Info("going to write results from container with id: ", contId, ", into this location: ", outDirFullPath)

		// open output file
		fo, err := os.Create(outDirFullPath + string(filepath.Separator) + "results.tar")
		if err != nil {
			logger.Error("failed to create tar file on FS for container with id: ", contId, ", error is: ", err, " - discard processing this container")
			returnVal <- err
			return
		}
		// close fo on exit and check for its returned error
		defer func() {
			if err := fo.Close(); err != nil {
				logger.Error("failed to close FS tar file for container with id: ", contId, ", error is: ", err)
			}
		}()

		// make a buffer to keep chunks that are read
		// buffer size==32K
		buf := make([]byte, 32*1024)
		writer := bufio.NewWriter(fo)

		if _, err := io.CopyBuffer(writer, reader, buf); err != nil {
			logger.Error("failed to write to tar file for container with id: ", contId, ", error is: ", err, " - discard processing this container")
			returnVal <- err
			return
		}

		//All is good, returning nil on the channel
		returnVal <- nil
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"image"
	_ "image/gif"
	"io"
	"log"
	"net/http"
	"sync"
	"time"
)

// TODO: hardcoding this feels so gross.
// curl -s https://radar.weather.gov/ridge/RadarImg/N0R/ | egrep '\w+N0R_0.gif' -o | sort -u | cut -d'_' -f1
var STATIONS = []string{
	"ABC", "ABR", "ABX", "ACG", "AEC", "AHG", "AIH", "AKC", "AKQ",
	"AMA", "AMX", "APD", "APX", "ARX", "ATX", "BBX", "BGM", "BHX",
	"BIS", "BLX", "BMX", "BOX", "BRO", "BUF", "BYX", "CAE", "CBW",
	"CBX", "CCX", "CLE", "CLX", "CRP", "CXX", "CYS", "DAX", "DDC",
	"DFX", "DGX", "DIX", "DLH", "DMX", "DOX", "DTX", "DVN", "DYX",
	"EAX", "EMX", "ENX", "EOX", "EPZ", "ESX", "EVX", "EWX", "EYX",
	"FCX", "FDR", "FDX", "FFC", "FSD", "FSX", "FTG", "FWS", "GGW",
	"GJX", "GLD", "GRB", "GRK", "GRR", "GSP", "GUA", "GWX", "GYX",
	"HDX", "HGX", "HKI", "HKM", "HMO", "HNX", "HPX", "HTX", "HWA",
	"ICT", "ICX", "ILN", "ILX", "IND", "INX", "IWA", "IWX", "JAX",
	"JBQ", "JGX", "JKL", "JRV", "JUA", "KJK", "KSG", "LBB", "LCH",
	"LGX", "LIX", "LNX", "LOT", "LRX", "LSX", "LTX", "LVX", "LWX",
	"LZK", "MAF", "MAX", "MBX", "MHX", "MKX", "MLB", "MOB", "MPX",
	"MQT", "MRX", "MSX", "MTX", "MUX", "MVX", "MXX", "NKX", "NQA",
	"OAX", "ODN", "OHX", "OKX", "OTX", "PAH", "PBZ", "PDT", "POE",
	"PUX", "QYA", "RAX", "RGX", "RIW", "RLX", "RTX", "SFX", "SGF",
	"SHV", "SJT", "SOX", "SRX", "TBW", "TFX", "TLH", "TLX", "TWX",
	"TYX", "UDX", "UEX", "VAX", "VBX", "VNX", "VTX", "VWX", "YUX",
}

const UpdateInterval = 3 * time.Minute
const BaseImgURL = "https://radar.weather.gov/ridge/RadarImg/N0R/"

func updateStationImage(callsign, lastModified string) (io.ReadCloser, string) {
	URL := fmt.Sprintf("%s%s_N0R_0.gif", BaseImgURL, callsign)

	resp, err := http.Get(URL)
	if err != nil {
		log.Printf("err: failed to update %s: %+v\n", callsign, err)
		return nil, lastModified
	}

	// Don't process the same file twice.
	modified, ok := resp.Header["Last-Modified"]
	if ok && modified[0] == lastModified {
		log.Printf("info: %s unmodified since %s", callsign, lastModified)
		return nil, lastModified
	}

	return resp.Body, modified[0]
}

// RGB color value -> decibel
var ReflectivityGradient = map[uint32]int8{
	0xFFFFFF: 75,
	0x996699: 70,
	0xF800FD: 65,
	0xBC0000: 60,
	0xD40000: 55,
	0xFE0000: 50,
	0xFD9500: 45,
	0xE5BC00: 40,
	0xFDF802: 35,
	0x008E00: 30,
	0x01C501: 25,
	0x02FD02: 20,
	0x0300F4: 15,
	0x019FF4: 10,
	0x04E9E7: 5,
	0x646464: 0,
	0x999966: -5,
	0xCCCC99: -10,
	0x663366: -15,
	0x9854C6: -20,
	0xCC99CC: -25,
	0xCCFFFF: -30,
}

const (
	CHAR_WIDTH   = 80
	CHAR_HEIGHT  = 24
	PIXEL_WIDTH  = 80 * 2
	PIXEL_HEIGHT = 24 * 4
)

func readRidgeImage(reader io.ReadCloser) {
	defer reader.Close()
	img, _, err := image.Decode(reader)
	if err != nil {
		log.Printf("err: failed to decode image: %+v\n", err)
		return
	}

	reflMap := make([]uint32, PIXEL_WIDTH*PIXEL_HEIGHT)
	valMap := make([]uint32, CHAR_WIDTH*CHAR_HEIGHT)

	hit, miss := 0, 0
	bounds := img.Bounds()
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			r, g, b, _ := img.At(x, y).RGBA()
			rgb := ((r & 0x0ff) << 16) |
				((g & 0x0ff) << 8) |
				(b & 0x0ff)

			if _, ok := ReflectivityGradient[rgb]; ok {
				hit++
			} else {
				miss++
			}

		}
	}

	log.Printf("info: hit: %d miss: %d\n", hit, miss)
}

func registerStation(callsign string) {
	ticker := time.NewTicker(UpdateInterval)
	go func() {
		var imageReader io.ReadCloser
		modifiedAt := ""

		// Hack for immediate first ticker execution
		for ; true; <-ticker.C {
			start := time.Now()

			imageReader, modifiedAt = updateStationImage(callsign, modifiedAt)
			if imageReader != nil {
				readRidgeImage(imageReader)
			}

			duration := int64(time.Now().Sub(start) / time.Millisecond)
			fmt.Printf("Tick: %s [%d ms]\n", callsign, duration)
		}
	}()
}

func registerStations(stations []string) {
	for _, callsign := range stations {
		registerStation(callsign)
	}
}

func main() {
	var wg sync.WaitGroup

	// 1. Spawn schedulers for consuming RIDGE data
	registerStations(STATIONS)

	wg.Add(1)
	wg.Wait()
}
<commit_msg>Generate massive, colorful terminal blobs<commit_after>package main

import (
	"fmt"
	"image"
	_ "image/gif"
	"io"
	"log"
	"net/http"
	"sync"
	"time"
)

// TODO: hardcoding this feels so gross.
// curl -s https://radar.weather.gov/ridge/RadarImg/N0R/ | egrep '\w+N0R_0.gif' -o | sort -u | cut -d'_' -f1
var STATIONS = []string{
	// "ABC", "ABR", "ABX", "ACG", "AEC", "AHG", "AIH", "AKC", "AKQ",
	// "AMA", "AMX", "APD", "APX", "ARX", "ATX", "BBX", "BGM", "BHX",
	// "BIS", "BLX", "BMX", "BOX", "BRO", "BUF", "BYX", "CAE", "CBW",
	// "CBX", "CCX", "CLE", "CLX", "CRP", "CXX", "CYS", "DAX", "DDC",
	// "DFX", "DGX", "DIX", "DLH", "DMX", "DOX", "DTX", "DVN", "DYX",
	// "EAX", "EMX", "ENX", "EOX", "EPZ", "ESX", "EVX", "EWX", "EYX",
	// "FCX", "FDR", "FDX", "FFC", "FSD", "FSX", "FTG", "FWS", "GGW",
	// "GJX", "GLD", "GRB", "GRK", "GRR", "GSP", "GUA", "GWX", "GYX",
	// "HDX", "HGX", "HKI", "HKM", "HMO", "HNX", "HPX", "HTX", "HWA",
	// "ICT", "ICX", "ILN", "ILX", "IND", "INX", "IWA", "IWX", "JAX",
	// "JBQ", "JGX", "JKL", "JRV", "JUA", "KJK", "KSG", "LBB", "LCH",
	// "LGX", "LIX", "LNX", "LOT", "LRX", "LSX", "LTX", "LVX", "LWX",
	// "LZK", "MAF", "MAX", "MBX", "MHX", "MKX", "MLB", "MOB", "MPX",
	// "MQT", "MRX", "MSX", "MTX", "MUX", "MVX", "MXX", "NKX", "NQA",
	// "OAX", "ODN", "OHX", "OKX", "OTX", "PAH", "PBZ", "PDT", "POE",
	// "PUX", "QYA", "RAX", "RGX", "RIW", "RLX", "RTX", "SFX", "SGF",
	// "SHV", "SJT", "SOX", "SRX", "TBW", "TFX", "TLH", "TLX", "TWX",
	// "TYX", "UDX", "UEX", "VAX", "VBX", "VNX", "VTX", "VWX", "YUX",
	"VTX",
}

const UpdateInterval = 3 * time.Minute
const BaseImgURL = "https://radar.weather.gov/ridge/RadarImg/N0R/"

func updateStationImage(callsign, lastModified string) (io.ReadCloser, string) {
	URL := fmt.Sprintf("%s%s_N0R_0.gif", BaseImgURL, callsign)

	resp, err := http.Get(URL)
	if err != nil {
		log.Printf("err: failed to update %s: %+v\n", callsign, err)
		return nil, lastModified
	}

	// Don't process the same file twice.
	modified, ok := resp.Header["Last-Modified"]
	if ok && modified[0] == lastModified {
		log.Printf("info: %s unmodified since %s", callsign, lastModified)
		return nil, lastModified
	}

	return resp.Body, modified[0]
}

// TODO: fix awful naming
type colorPair struct {
	color     uint32
	decibel   int8
	termColor int
}

// RGB color value -> decibel
var ReflColorToDb = map[uint32]int8{}
var ReflDbToColor = []colorPair{
	{0xFFFFFF, 75, 37},
	{0x996699, 70, 35},
	{0xF800FD, 65, 35},
	{0xBC0000, 60, 31},
	{0xD40000, 55, 31},
	{0xFE0000, 50, 31},
	{0xFD9500, 45, 31},
	{0xE5BC00, 40, 33},
	{0xFDF802, 35, 33},
	{0x008E00, 30, 32},
	{0x01C501, 25, 32},
	{0x02FD02, 20, 32},
	{0x0300F4, 15, 34},
	{0x019FF4, 10, 94},
	{0x04E9E7, 5, 94},
	{0x646464, 0, 37},
	{0x999966, -5, 90},
	{0xCCCC99, -10, 90},
	{0x663366, -15, 95},
	{0x9854C6, -20, 95},
	{0xCC99CC, -25, 95},
	{0xCCFFFF, -30, 96},
}

func init() {
	ReflColorToDb = make(map[uint32]int8, len(ReflDbToColor))
	for _, pair := range ReflDbToColor {
		ReflColorToDb[pair.color] = pair.decibel
	}
}

const (
	PIXELS_PER_CHAR_X = 2
	PIXELS_PER_CHAR_Y = 4

	OUT_CHAR_WIDTH  = 80
	OUT_CHAR_HEIGHT = 24
)

func scaledIdx(x, y, fw, fh, tw, th uint32) (uint32, uint32) {
	scaledX := float32(x) / float32(fw)
	scaledY := float32(y) / float32(fh)

	return uint32(scaledX * float32(tw)),
		uint32(scaledY * float32(th))
}

func getChar(img image.Image, x, y int) ridgePixel {
	var intensity int32 = 0
	var mask uint16 = 0

	// Braille dots are indexed like so:
	// 1 4
	// 2 5
	// 3 6
	// 7 8
	bitMapping := []uint{
		0, 3,
		1, 4,
		2, 5,
		6, 7,
	}

	bounds := img.Bounds()

	for i := 0; i < PIXELS_PER_CHAR_X; i++ {
		px := (x * PIXELS_PER_CHAR_X) + i + bounds.Min.X
		for j := 0; j < PIXELS_PER_CHAR_Y; j++ {
			py := (y * PIXELS_PER_CHAR_Y) + j + bounds.Min.Y

			r, g, b, _ := img.At(px, py).RGBA()
			rgb := ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF)

			if pxDbVal, ok := ReflColorToDb[rgb]; ok {
				intensity += int32(pxDbVal)
				pos := bitMapping[j*2+i]
				mask |= (1 << pos)
			}
		}
	}

	avgIntensity := int8(float32(intensity) / (PIXELS_PER_CHAR_X * PIXELS_PER_CHAR_Y))
	color := int(0)

	for _, p := range ReflDbToColor {
		color = p.termColor
		if p.decibel <= avgIntensity {
			break
		}
	}

	return ridgePixel{
		ch:    rune(0x2800 | mask),
		color: color,
	}
}

type ridgePixel struct {
	ch    rune
	color int
}

func readRidgeImage(reader io.ReadCloser) {
	defer reader.Close()
	img, _, err := image.Decode(reader)
	if err != nil {
		log.Printf("err: failed to decode image: %+v\n", err)
		return
	}

	bounds := img.Bounds()

	iw, ih := bounds.Dx(), bounds.Dy()
	ow, oh := iw/PIXELS_PER_CHAR_X, ih/PIXELS_PER_CHAR_Y

	buf := make([][]ridgePixel, oh)
	for y := 0; y < oh; y++ {
		buf[y] = make([]ridgePixel, ow)
		for x := 0; x < ow; x++ {
			buf[y][x] = getChar(img, x, y)
			fmt.Printf("\033[%dm%c", buf[y][x].color, buf[y][x].ch)
		}
		fmt.Println()
	}
}

func registerStation(callsign string) {
	ticker := time.NewTicker(UpdateInterval)
	go func() {
		var imageReader io.ReadCloser
		modifiedAt := ""

		// Hack for immediate first ticker execution
		for ; true; <-ticker.C {
			start := time.Now()

			imageReader, modifiedAt = updateStationImage(callsign, modifiedAt)
			if imageReader != nil {
				readRidgeImage(imageReader)
			}

			duration := int64(time.Now().Sub(start) / time.Millisecond)
			fmt.Printf("Tick: %s [%d ms]\n", callsign, duration)
		}
	}()
}

func registerStations(stations []string) {
	for _, callsign := range stations {
		registerStation(callsign)
	}
}

func main() {
	var wg sync.WaitGroup

	// 1. Spawn schedulers for consuming RIDGE data
	registerStations(STATIONS)

	wg.Add(1)
	wg.Wait()
}
<|endoftext|>


<commit_before>// The plugin package provides the functionality to both expose a Packer
// plugin binary and to connect to an existing Packer plugin binary.
//
// Packer supports plugins in the form of self-contained external static
// Go binaries. These binaries behave in a certain way (enforced by this
// package) and are connected to in a certain way (also enforced by this
// package).
package plugin

import (
	"errors"
	"fmt"
	"github.com/mitchellh/packer/packer"
	packrpc "github.com/mitchellh/packer/packer/rpc"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"sync/atomic"
)

// This is a count of the number of interrupts the process has received.
// This is updated with sync/atomic whenever a SIGINT is received and can
// be checked by the plugin safely to take action.
var Interrupts int32 = 0

const MagicCookieKey = "PACKER_PLUGIN_MAGIC_COOKIE"
const MagicCookieValue = "d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d6991ca9872b2"

// The APIVersion is outputted along with the RPC address. The plugin
// client validates this API version and will show an error if it doesn't
// know how to speak it.
const APIVersion = "3"

// Server waits for a connection to this plugin and returns a Packer
// RPC server that you can use to register components and serve them.
func Server() (*packrpc.Server, error) {
	log.Printf("Plugin build against Packer '%s'", packer.GitCommit)

	if os.Getenv(MagicCookieKey) != MagicCookieValue {
		return nil, errors.New(
			"Please do not execute plugins directly. Packer will execute these for you.")
	}

	// If there is no explicit number of Go threads to use, then set it
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(runtime.NumCPU())
	}

	minPort, err := strconv.ParseInt(os.Getenv("PACKER_PLUGIN_MIN_PORT"), 10, 32)
	if err != nil {
		return nil, err
	}

	maxPort, err := strconv.ParseInt(os.Getenv("PACKER_PLUGIN_MAX_PORT"), 10, 32)
	if err != nil {
		return nil, err
	}

	log.Printf("Plugin minimum port: %d\n", minPort)
	log.Printf("Plugin maximum port: %d\n", maxPort)

	listener, err := serverListener(minPort, maxPort)
	if err != nil {
		return nil, err
	}
	defer listener.Close()

	// Output the address to stdout
	log.Printf("Plugin address: %s %s\n",
		listener.Addr().Network(), listener.Addr().String())
	fmt.Printf("%s|%s|%s\n",
		APIVersion,
		listener.Addr().Network(),
		listener.Addr().String())
	os.Stdout.Sync()

	// Accept a connection
	log.Println("Waiting for connection...")
	conn, err := listener.Accept()
	if err != nil {
		log.Printf("Error accepting connection: %s\n", err.Error())
		return nil, err
	}

	// Eat the interrupts
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	go func() {
		var count int32 = 0
		for {
			<-ch
			newCount := atomic.AddInt32(&count, 1)
			log.Printf("Received interrupt signal (count: %d). Ignoring.", newCount)
		}
	}()

	// Serve a single connection
	log.Println("Serving a plugin connection...")
	return packrpc.NewServer(conn), nil
}

func serverListener(minPort, maxPort int64) (net.Listener, error) {
	if runtime.GOOS == "windows" {
		return serverListener_tcp(minPort, maxPort)
	}

	return serverListener_unix()
}

func serverListener_tcp(minPort, maxPort int64) (net.Listener, error) {
	for port := minPort; port <= maxPort; port++ {
		address := fmt.Sprintf("127.0.0.1:%d", port)
		listener, err := net.Listen("tcp", address)
		if err == nil {
			return listener, nil
		}
	}

	return nil, errors.New("Couldn't bind plugin TCP listener")
}

func serverListener_unix() (net.Listener, error) {
	tf, err := ioutil.TempFile("", "packer-plugin")
	if err != nil {
		return nil, err
	}
	path := tf.Name()

	// Close the file and remove it because it has to not exist for
	// the domain socket.
	if err := tf.Close(); err != nil {
		return nil, err
	}
	if err := os.Remove(path); err != nil {
		return nil, err
	}

	return net.Listen("unix", path)
}
<commit_msg>packer/plugin: increase version for Yamux<commit_after>// The plugin package provides the functionality to both expose a Packer
// plugin binary and to connect to an existing Packer plugin binary.
//
// Packer supports plugins in the form of self-contained external static
// Go binaries. These binaries behave in a certain way (enforced by this
// package) and are connected to in a certain way (also enforced by this
// package).
package plugin

import (
	"errors"
	"fmt"
	"github.com/mitchellh/packer/packer"
	packrpc "github.com/mitchellh/packer/packer/rpc"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"sync/atomic"
)

// This is a count of the number of interrupts the process has received.
// This is updated with sync/atomic whenever a SIGINT is received and can
// be checked by the plugin safely to take action.
var Interrupts int32 = 0

const MagicCookieKey = "PACKER_PLUGIN_MAGIC_COOKIE"
const MagicCookieValue = "d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d6991ca9872b2"

// The APIVersion is outputted along with the RPC address. The plugin
// client validates this API version and will show an error if it doesn't
// know how to speak it.
const APIVersion = "4"

// Server waits for a connection to this plugin and returns a Packer
// RPC server that you can use to register components and serve them.
func Server() (*packrpc.Server, error) {
	log.Printf("Plugin build against Packer '%s'", packer.GitCommit)

	if os.Getenv(MagicCookieKey) != MagicCookieValue {
		return nil, errors.New(
			"Please do not execute plugins directly. Packer will execute these for you.")
	}

	// If there is no explicit number of Go threads to use, then set it
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(runtime.NumCPU())
	}

	minPort, err := strconv.ParseInt(os.Getenv("PACKER_PLUGIN_MIN_PORT"), 10, 32)
	if err != nil {
		return nil, err
	}

	maxPort, err := strconv.ParseInt(os.Getenv("PACKER_PLUGIN_MAX_PORT"), 10, 32)
	if err != nil {
		return nil, err
	}

	log.Printf("Plugin minimum port: %d\n", minPort)
	log.Printf("Plugin maximum port: %d\n", maxPort)

	listener, err := serverListener(minPort, maxPort)
	if err != nil {
		return nil, err
	}
	defer listener.Close()

	// Output the address to stdout
	log.Printf("Plugin address: %s %s\n",
		listener.Addr().Network(), listener.Addr().String())
	fmt.Printf("%s|%s|%s\n",
		APIVersion,
		listener.Addr().Network(),
		listener.Addr().String())
	os.Stdout.Sync()

	// Accept a connection
	log.Println("Waiting for connection...")
	conn, err := listener.Accept()
	if err != nil {
		log.Printf("Error accepting connection: %s\n", err.Error())
		return nil, err
	}

	// Eat the interrupts
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	go func() {
		var count int32 = 0
		for {
			<-ch
			newCount := atomic.AddInt32(&count, 1)
			log.Printf("Received interrupt signal (count: %d). Ignoring.", newCount)
		}
	}()

	// Serve a single connection
	log.Println("Serving a plugin connection...")
	return packrpc.NewServer(conn), nil
}

func serverListener(minPort, maxPort int64) (net.Listener, error) {
	if runtime.GOOS == "windows" {
		return serverListener_tcp(minPort, maxPort)
	}

	return serverListener_unix()
}

func serverListener_tcp(minPort, maxPort int64) (net.Listener, error) {
	for port := minPort; port <= maxPort; port++ {
		address := fmt.Sprintf("127.0.0.1:%d", port)
		listener, err := net.Listen("tcp", address)
		if err == nil {
			return listener, nil
		}
	}

	return nil, errors.New("Couldn't bind plugin TCP listener")
}

func serverListener_unix() (net.Listener, error) {
	tf, err := ioutil.TempFile("", "packer-plugin")
	if err != nil {
		return nil, err
	}
	path := tf.Name()

	// Close the file and remove it because it has to not exist for
	// the domain socket.
	if err := tf.Close(); err != nil {
		return nil, err
	}
	if err := os.Remove(path); err != nil {
		return nil, err
	}

	return net.Listen("unix", path)
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package gce

import (
	"github.com/juju/errors"
	"github.com/juju/schema"

	"github.com/juju/juju/environs/config"
)

const (
	// These are not GCE-official environment variable names.
	osEnvPrivateKey    = "GCE_PRIVATE_KEY"
	osEnvClientID      = "GCE_CLIENT_ID"
	osEnvClientEmail   = "GCE_CLIENT_EMAIL"
	osEnvRegion        = "GCE_REGION"
	osEnvProjectID     = "GCE_PROJECT_ID"
	osEnvImageEndpoint = "GCE_IMAGE_URL"

	cfgPrivateKey    = "private-key"
	cfgClientID      = "client-id"
	cfgClientEmail   = "client-email"
	cfgRegion        = "region"
	cfgProjectID     = "project-id"
	cfgImageEndpoint = "image-endpoint"
)

// boilerplateConfig will be shown in help output, so please keep it up to
// date when you change environment configuration below.
var boilerplateConfig = `
gce:
  type: gce

  # Google Auth Info
  private-key:
  client-email:
  client-id:

  # Google instance info
  # region: us-central1
  project-id:
  # image-endpoint: https://www.googleapis.com
`[1:]

var osEnvFields = map[string]string{
	osEnvPrivateKey:    cfgPrivateKey,
	osEnvClientID:      cfgClientID,
	osEnvClientEmail:   cfgClientEmail,
	osEnvRegion:        cfgRegion,
	osEnvProjectID:     cfgProjectID,
	osEnvImageEndpoint: cfgImageEndpoint,
}

var configFields = schema.Fields{
	cfgPrivateKey:    schema.String(),
	cfgClientID:      schema.String(),
	cfgClientEmail:   schema.String(),
	cfgRegion:        schema.String(),
	cfgProjectID:     schema.String(),
	cfgImageEndpoint: schema.String(),
}

var configDefaults = schema.Defaults{
	// See http://cloud-images.ubuntu.com/releases/streams/v1/com.ubuntu.cloud:released:gce.json
	cfgImageEndpoint: "https://www.googleapis.com",
}

var configSecretFields = []string{
	cfgPrivateKey,
}

var configImmutableFields = []string{
	cfgPrivateKey,
	cfgClientID,
	cfgClientEmail,
	cfgRegion,
	cfgProjectID,
	cfgImageEndpoint,
}

type environConfig struct {
	*config.Config
	attrs map[string]interface{}
}

func (c *environConfig) privateKey() string {
	return c.attrs[cfgPrivateKey].(string)
}

func (c *environConfig) clientID() string {
	return c.attrs[cfgClientID].(string)
}

func (c *environConfig) clientEmail() string {
	return c.attrs[cfgClientEmail].(string)
}

func (c *environConfig) region() string {
	return c.attrs[cfgRegion].(string)
}

func (c *environConfig) projectID() string {
	return c.attrs[cfgProjectID].(string)
}

func (c *environConfig) imageEndpoint() string {
	return c.attrs[cfgImageEndpoint].(string)
}

func (c *environConfig) auth() gceAuth {
	return gceAuth{
		clientID:    c.attrs[cfgClientID].(string),
		clientEmail: c.attrs[cfgClientEmail].(string),
		privateKey:  []byte(c.attrs[cfgPrivateKey].(string)),
	}
}

func (c *environConfig) newConnection() *gceConnection {
	return &gceConnection{
		region:    c.attrs[cfgRegion].(string),
		projectID: c.attrs[cfgProjectID].(string),
	}
}

func validateConfig(cfg, old *config.Config) (*environConfig, error) {
	// Check for valid changes and coerce the values (base config first
	// then custom).
	if err := config.Validate(cfg, old); err != nil {
		return nil, errors.Trace(err)
	}
	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, errors.Trace(err)
	}

	ecfg := &environConfig{cfg, validated}

	// TODO(ericsnow) Support pulling ID/PK from shell environment variables.

	// Check that no immutable fields have changed.
	if old != nil {
		attrs := old.UnknownAttrs()
		for _, field := range configImmutableFields {
			if attrs[field] != validated[field] {
				return nil, errors.Errorf("%s: cannot change from %v to %v", field, attrs[field], validated[field])
			}
		}
	}

	// Check sanity of GCE fields.
	if err := ecfg.auth().validate(); err != nil {
		return nil, errors.Trace(handleInvalidField(err))
	}
	if err := ecfg.newConnection().validate(); err != nil {
		return nil, errors.Trace(handleInvalidField(err))
	}

	// TODO(ericsnow) Follow up with someone on this.
	cfg, err = ecfg.Config.Apply(ecfg.attrs)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ecfg.Config = cfg
	return ecfg, nil
}

func handleInvalidField(err error) error {
	vErr := err.(*config.InvalidConfigValue)
	if vErr.Reason == nil && vErr.Value == "" {
		key := osEnvFields[vErr.Key]
		return errors.Errorf("%s: must not be empty", key)
	}
	return err
}
<commit_msg>provider/gce: Clarify a doc comment.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package gce

import (
	"github.com/juju/errors"
	"github.com/juju/schema"

	"github.com/juju/juju/environs/config"
)

const (
	// These are not GCE-official environment variable names.
	osEnvPrivateKey    = "GCE_PRIVATE_KEY"
	osEnvClientID      = "GCE_CLIENT_ID"
	osEnvClientEmail   = "GCE_CLIENT_EMAIL"
	osEnvRegion        = "GCE_REGION"
	osEnvProjectID     = "GCE_PROJECT_ID"
	osEnvImageEndpoint = "GCE_IMAGE_URL"

	cfgPrivateKey    = "private-key"
	cfgClientID      = "client-id"
	cfgClientEmail   = "client-email"
	cfgRegion        = "region"
	cfgProjectID     = "project-id"
	cfgImageEndpoint = "image-endpoint"
)

// boilerplateConfig will be shown in help output, so please keep it up to
// date when you change environment configuration below.
var boilerplateConfig = `
gce:
  type: gce

  # Google Auth Info
  private-key:
  client-email:
  client-id:

  # Google instance info
  # region: us-central1
  project-id:
  # image-endpoint: https://www.googleapis.com
`[1:]

var osEnvFields = map[string]string{
	osEnvPrivateKey:    cfgPrivateKey,
	osEnvClientID:      cfgClientID,
	osEnvClientEmail:   cfgClientEmail,
	osEnvRegion:        cfgRegion,
	osEnvProjectID:     cfgProjectID,
	osEnvImageEndpoint: cfgImageEndpoint,
}

var configFields = schema.Fields{
	cfgPrivateKey:    schema.String(),
	cfgClientID:      schema.String(),
	cfgClientEmail:   schema.String(),
	cfgRegion:        schema.String(),
	cfgProjectID:     schema.String(),
	cfgImageEndpoint: schema.String(),
}

var configDefaults = schema.Defaults{
	// See http://cloud-images.ubuntu.com/releases/streams/v1/com.ubuntu.cloud:released:gce.json
	cfgImageEndpoint: "https://www.googleapis.com",
}

var configSecretFields = []string{
	cfgPrivateKey,
}

var configImmutableFields = []string{
	cfgPrivateKey,
	cfgClientID,
	cfgClientEmail,
	cfgRegion,
	cfgProjectID,
	cfgImageEndpoint,
}

type environConfig struct {
	*config.Config
	attrs map[string]interface{}
}

func (c *environConfig) privateKey() string {
	return c.attrs[cfgPrivateKey].(string)
}

func (c *environConfig) clientID() string {
	return c.attrs[cfgClientID].(string)
}

func (c *environConfig) clientEmail() string {
	return c.attrs[cfgClientEmail].(string)
}

func (c *environConfig) region() string {
	return c.attrs[cfgRegion].(string)
}

func (c *environConfig) projectID() string {
	return c.attrs[cfgProjectID].(string)
}

func (c *environConfig) imageEndpoint() string {
	return c.attrs[cfgImageEndpoint].(string)
}

func (c *environConfig) auth() gceAuth {
	return gceAuth{
		clientID:    c.attrs[cfgClientID].(string),
		clientEmail: c.attrs[cfgClientEmail].(string),
		privateKey:  []byte(c.attrs[cfgPrivateKey].(string)),
	}
}

func (c *environConfig) newConnection() *gceConnection {
	return &gceConnection{
		region:    c.attrs[cfgRegion].(string),
		projectID: c.attrs[cfgProjectID].(string),
	}
}

func validateConfig(cfg, old *config.Config) (*environConfig, error) {
	// Check for valid changes and coerce the values (base config first
	// then custom).
	if err := config.Validate(cfg, old); err != nil {
		return nil, errors.Trace(err)
	}
	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, errors.Trace(err)
	}

	ecfg := &environConfig{cfg, validated}

	// TODO(ericsnow) Support pulling ID/PK from shell environment variables.

	// Check that no immutable fields have changed.
	if old != nil {
		attrs := old.UnknownAttrs()
		for _, field := range configImmutableFields {
			if attrs[field] != validated[field] {
				return nil, errors.Errorf("%s: cannot change from %v to %v", field, attrs[field], validated[field])
			}
		}
	}

	// Check sanity of GCE fields.
	if err := ecfg.auth().validate(); err != nil {
		return nil, errors.Trace(handleInvalidField(err))
	}
	if err := ecfg.newConnection().validate(); err != nil {
		return nil, errors.Trace(handleInvalidField(err))
	}

	// TODO(ericsnow) Follow up with someone on if it is appropriate
	// to call Apply here.
	cfg, err = ecfg.Config.Apply(ecfg.attrs)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ecfg.Config = cfg
	return ecfg, nil
}

func handleInvalidField(err error) error {
	vErr := err.(*config.InvalidConfigValue)
	if vErr.Reason == nil && vErr.Value == "" {
		key := osEnvFields[vErr.Key]
		return errors.Errorf("%s: must not be empty", key)
	}
	return err
}
<|endoftext|>


<commit_before>package frontend

import (
	"github.com/gin-gonic/gin"

	"github.com/aiyi/go-user/frontend/checkcode"
	"github.com/aiyi/go-user/frontend/middleware"
	"github.com/aiyi/go-user/frontend/oauth/wechat/mp"
	"github.com/aiyi/go-user/frontend/oauth/wechat/open"
	"github.com/aiyi/go-user/frontend/user"
)

var Engine *gin.Engine

func init() {
	Engine = gin.Default()

	Engine.GET("/oauth/wechat/mp/login_url", middleware.MustAuthHandler, mp.LoginURLHandler)
	Engine.GET("/oauth/wechat/open/login_url", middleware.MustAuthHandler, open.LoginURLHandler)

	UserGroupRouter := Engine.Group("/user")
	{
		UserGroupRouter.GET("/auth", user.AuthHandler)
	}

	CheckCodeGroupRouter := Engine.Group("/checkcode")
	{
		CheckCodeGroupRouter.POST("/request_for_phone", middleware.MustAuthHandler, checkcode.RequestForPhoneHandler)
		CheckCodeGroupRouter.POST("/request_for_email", middleware.MustAuthHandler, checkcode.RequestForEmailHandler)
	}
}
<commit_msg>no message<commit_after>package frontend

import (
	"github.com/gin-gonic/gin"

	"github.com/aiyi/go-user/frontend/checkcode"
	"github.com/aiyi/go-user/frontend/middleware"
	"github.com/aiyi/go-user/frontend/oauth/wechat/mp"
	"github.com/aiyi/go-user/frontend/oauth/wechat/open"
	tokenhandler "github.com/aiyi/go-user/frontend/token/handler"
	"github.com/aiyi/go-user/frontend/user"
)

var Engine *gin.Engine

func init() {
	Engine = gin.Default()

	Engine.GET("/oauth/wechat/mp/login_url", middleware.MustAuthHandler, mp.LoginURLHandler)
	Engine.GET("/oauth/wechat/mp/login", middleware.MustAuthHandler, mp.LoginHandler)
	Engine.GET("/oauth/wechat/open/login_url", middleware.MustAuthHandler, open.LoginURLHandler)
	Engine.GET("/oauth/wechat/open/login", middleware.MustAuthHandler, open.LoginHandler)

	Engine.GET("/token/refresh", middleware.MustAuthHandler, tokenhandler.RefreshHandler)

	UserGroupRouter := Engine.Group("/user")
	{
		UserGroupRouter.GET("/auth", user.AuthHandler)
	}

	CheckCodeGroupRouter := Engine.Group("/checkcode")
	{
		CheckCodeGroupRouter.POST("/request_for_phone", middleware.MustAuthHandler, checkcode.RequestForPhoneHandler)
		CheckCodeGroupRouter.POST("/request_for_email", middleware.MustAuthHandler, checkcode.RequestForEmailHandler)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 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 apiserver

import (
	"fmt"
	"net/http"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
	"github.com/golang/glog"
)

// statusError is an object that can be converted into an api.Status
type statusError interface {
	Status() api.Status
}

// errToAPIStatus converts an error to an api.Status object.
func errToAPIStatus(err error) *api.Status {
	switch t := err.(type) {
	case statusError:
		status := t.Status()
		status.Status = api.StatusFailure
		//TODO: check for invalid responses
		return &status
	default:
		status := http.StatusInternalServerError
		switch {
		//TODO: replace me with NewConflictErr
		case tools.IsEtcdTestFailed(err):
			status = http.StatusConflict
		}
		// Log errors that were not converted to an error status
		// by REST storage - these typically indicate programmer
		// error by not using pkg/api/errors, or unexpected failure
		// cases.
		glog.V(1).Infof("An unchecked error was received: %v", err)
		return &api.Status{
			Status:  api.StatusFailure,
			Code:    status,
			Reason:  api.StatusReasonUnknown,
			Message: err.Error(),
		}
	}
}

// notFound renders a simple not found error.
func notFound(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintf(w, "Not Found: %#v", req.RequestURI)
}

// badGatewayError renders a simple bad gateway error.
func badGatewayError(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusBadGateway)
	fmt.Fprintf(w, "Bad Gateway: %#v", req.RequestURI)
}
<commit_msg>Add forbidden error.<commit_after>/*
Copyright 2014 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 apiserver

import (
	"fmt"
	"net/http"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
	"github.com/golang/glog"
)

// statusError is an object that can be converted into an api.Status
type statusError interface {
	Status() api.Status
}

// errToAPIStatus converts an error to an api.Status object.
func errToAPIStatus(err error) *api.Status {
	switch t := err.(type) {
	case statusError:
		status := t.Status()
		status.Status = api.StatusFailure
		//TODO: check for invalid responses
		return &status
	default:
		status := http.StatusInternalServerError
		switch {
		//TODO: replace me with NewConflictErr
		case tools.IsEtcdTestFailed(err):
			status = http.StatusConflict
		}
		// Log errors that were not converted to an error status
		// by REST storage - these typically indicate programmer
		// error by not using pkg/api/errors, or unexpected failure
		// cases.
		glog.V(1).Infof("An unchecked error was received: %v", err)
		return &api.Status{
			Status:  api.StatusFailure,
			Code:    status,
			Reason:  api.StatusReasonUnknown,
			Message: err.Error(),
		}
	}
}

// notFound renders a simple not found error.
func notFound(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintf(w, "Not Found: %#v", req.RequestURI)
}

// badGatewayError renders a simple bad gateway error.
func badGatewayError(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusBadGateway)
	fmt.Fprintf(w, "Bad Gateway: %#v", req.RequestURI)
}

// forbidden renders a simple forbidden error
func forbidden(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusForbidden)
	fmt.Fprintf(w, "Forbidden: %#v", req.RequestURI)
}
<|endoftext|>


<commit_before>/*
	rulehunter - A server to find rules in data based on user specified goals
	Copyright (C) 2016 vLife Systems Ltd <http://vlifesystems.com>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program; see the file COPYING.  If not, see
	<http://www.gnu.org/licenses/>.
*/

package html

const licenceTpl = `
<!DOCTYPE html>

		{{ index .Html "head" }}
		<title>Rulehunter</title>

		{{ index .Html "nav" }}

Licence

Rulehunter - A server to find simple rules in data based on user specified goals.

Copyright (C) 2016 vLife Systems Ltd

This program is free software: you can redistribute it and/or modify
				it under the terms of the GNU Affero General Public License as published by
				the Free Software Foundation, either version 3 of the License, or
				(at your option) any later version.

This program is distributed in the hope that it will be useful,
				but WITHOUT ANY WARRANTY; without even the implied warranty of
				MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
				GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
				along with this program.  If not, see
				http://www.gnu.org/licenses/.

Source Code

The source code is available at: {{ .SourceURL }}.

			{{ index .Html "footer" }}

		{{ index .Html "bootstrapJS" }}

`
<commit_msg>Add 2017 to generated licence page<commit_after>/*
	rulehunter - A server to find rules in data based on user specified goals
	Copyright (C) 2016-2017 vLife Systems Ltd <http://vlifesystems.com>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program; see the file COPYING.  If not, see
	<http://www.gnu.org/licenses/>.
*/

package html

const licenceTpl = `
<!DOCTYPE html>

		{{ index .Html "head" }}
		<title>Rulehunter</title>

		{{ index .Html "nav" }}

Licence

Rulehunter - A server to find simple rules in data based on user specified goals.

Copyright (C) 2016-2017 vLife Systems Ltd

This program is free software: you can redistribute it and/or modify
				it under the terms of the GNU Affero General Public License as published by
				the Free Software Foundation, either version 3 of the License, or
				(at your option) any later version.

This program is distributed in the hope that it will be useful,
				but WITHOUT ANY WARRANTY; without even the implied warranty of
				MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
				GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
				along with this program.  If not, see
				http://www.gnu.org/licenses/.

Source Code

The source code is available at: {{ .SourceURL }}.

			{{ index .Html "footer" }}

		{{ index .Html "bootstrapJS" }}

`
<|endoftext|>


<commit_before>package tls

import (
	"crypto/x509"
	"crypto/x509/pkix"

	"github.com/openshift/installer/pkg/asset"
)

// KubeCA is the asset that generates the kube-ca key/cert pair.
type KubeCA struct {
	CertKey
}

var _ asset.Asset = (*KubeCA)(nil)

// Dependencies returns the dependency of the the cert/key pair, which includes
// the parent CA, and install config if it depends on the install config for
// DNS names, etc.
func (a *KubeCA) Dependencies() []asset.Asset {
	return []asset.Asset{
		&RootCA{},
	}
}

// Generate generates the cert/key pair based on its dependencies.
func (a *KubeCA) Generate(dependencies asset.Parents) error {
	rootCA := &RootCA{}
	dependencies.Get(rootCA)

	cfg := &CertCfg{
		Subject:   pkix.Name{CommonName: "kube-ca", OrganizationalUnit: []string{"bootkube"}},
		KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		Validity:  ValidityTenYears,
		IsCA:      true,
	}

	return a.CertKey.Generate(cfg, rootCA, "kube-ca", DoNotAppendParent)
}

// Name returns the human-friendly name of the asset.
func (a *KubeCA) Name() string {
	return "Certificate (kube-ca)"
}
<commit_msg>pkg/asset/tls: self-sign kube-ca<commit_after>package tls

import (
	"crypto/x509"
	"crypto/x509/pkix"

	"github.com/openshift/installer/pkg/asset"
	"github.com/pkg/errors"
)

// KubeCA is the asset that generates the kube-ca key/cert pair.
type KubeCA struct {
	CertKey
}

var _ asset.Asset = (*KubeCA)(nil)

// Dependencies returns the dependency of the the cert/key pair, which includes
// the parent CA, and install config if it depends on the install config for
// DNS names, etc.
func (a *KubeCA) Dependencies() []asset.Asset {
	return []asset.Asset{}
}

// Generate generates the cert/key pair based on its dependencies.
func (a *KubeCA) Generate(dependencies asset.Parents) error {

	cfg := &CertCfg{
		Subject:   pkix.Name{CommonName: "kube-ca", OrganizationalUnit: []string{"bootkube"}},
		KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		Validity:  ValidityTenYears,
		IsCA:      true,
	}

	key, crt, err := GenerateRootCertKey(cfg)
	if err != nil {
		return errors.Wrap(err, "failed to generate Kube CA")
	}

	a.KeyRaw = PrivateKeyToPem(key)
	a.CertRaw = CertToPem(crt)

	a.generateFiles("kube-ca")

	return nil
}

// Name returns the human-friendly name of the asset.
func (a *KubeCA) Name() string {
	return "Certificate (kube-ca)"
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors 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 chartutil

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"k8s.io/helm/pkg/proto/hapi/chart"
)

const (
	// ChartfileName is the default Chart file name.
	ChartfileName = "Chart.yaml"
	// ValuesfileName is the default values file name.
	ValuesfileName = "values.yaml"
	// TemplatesDir is the relative directory name for templates.
	TemplatesDir = "templates"
	// ChartsDir is the relative directory name for charts dependencies.
	ChartsDir = "charts"
	// IgnorefileName is the name of the Helm ignore file.
	IgnorefileName = ".helmignore"
	// IngressFileName is the name of the example ingress file.
	IngressFileName = "ingress.yaml"
	// DeploymentName is the name of the example deployment file.
	DeploymentName = "deployment.yaml"
	// ServiceName is the name of the example service file.
	ServiceName = "service.yaml"
	// NotesName is the name of the example NOTES.txt file.
	NotesName = "NOTES.txt"
	// HelpersName is the name of the example NOTES.txt file.
	HelpersName = "_helpers.tpl"
)

const defaultValues = `# Default values for %s.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - chart-example.local
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi

nodeSelector: {}

tolerations: []

affinity: {}
`

const defaultIgnore = `# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
`

const defaultIngress = `{{- if .Values.ingress.enabled -}}
{{- $fullName := include "<CHARTNAME>.fullname" . -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ $fullName }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ template "<CHARTNAME>.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
{{- with .Values.ingress.annotations }}
  annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
  tls:
  {{- range .Values.ingress.tls }}
    - hosts:
      {{- range .hosts }}
        - {{ . }}
      {{- end }}
      secretName: {{ .secretName }}
  {{- end }}
{{- end }}
  rules:
  {{- range .Values.ingress.hosts }}
    - host: {{ . }}
      http:
        paths:
          - path: {{ $ingressPath }}
            backend:
              serviceName: {{ $fullName }}
              servicePort: http
  {{- end }}
{{- end }}
`

const defaultDeployment = `apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ template "<CHARTNAME>.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "<CHARTNAME>.name" . }}
      release: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ template "<CHARTNAME>.name" . }}
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
{{ toYaml .Values.resources | indent 12 }}
    {{- with .Values.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
    {{- end }}
`

const defaultService = `apiVersion: v1
kind: Service
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ template "<CHARTNAME>.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: {{ template "<CHARTNAME>.name" . }}
    release: {{ .Release.Name }}
`

const defaultNotes = `1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "<CHARTNAME>.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get svc -w {{ template "<CHARTNAME>.fullname" . }}'
  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "<CHARTNAME>.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "<CHARTNAME>.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80
{{- end }}
`

const defaultHelpers = `{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "<CHARTNAME>.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "<CHARTNAME>.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "<CHARTNAME>.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
`

// CreateFrom creates a new chart, but scaffolds it from the src chart.
func CreateFrom(chartfile *chart.Metadata, dest string, src string) error {
	schart, err := Load(src)
	if err != nil {
		return fmt.Errorf("could not load %s: %s", src, err)
	}

	schart.Metadata = chartfile

	var updatedTemplates []*chart.Template

	for _, template := range schart.Templates {
		newData := Transform(string(template.Data), "<CHARTNAME>", schart.Metadata.Name)
		updatedTemplates = append(updatedTemplates, &chart.Template{Name: template.Name, Data: newData})
	}

	schart.Templates = updatedTemplates
	if schart.Values != nil {
		schart.Values = &chart.Config{Raw: string(Transform(schart.Values.Raw, "<CHARTNAME>", schart.Metadata.Name))}
	}
	return SaveDir(schart, dest)
}

// Create creates a new chart in a directory.
//
// Inside of dir, this will create a directory based on the name of
// chartfile.Name. It will then write the Chart.yaml into this directory and
// create the (empty) appropriate directories.
//
// The returned string will point to the newly created directory. It will be
// an absolute path, even if the provided base directory was relative.
//
// If dir does not exist, this will return an error.
// If Chart.yaml or any directories cannot be created, this will return an
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func Create(chartfile *chart.Metadata, dir string) (string, error) {
	path, err := filepath.Abs(dir)
	if err != nil {
		return path, err
	}

	if fi, err := os.Stat(path); err != nil {
		return path, err
	} else if !fi.IsDir() {
		return path, fmt.Errorf("no such directory %s", path)
	}

	n := chartfile.Name
	cdir := filepath.Join(path, n)
	if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() {
		return cdir, fmt.Errorf("file %s already exists and is not a directory", cdir)
	}
	if err := os.MkdirAll(cdir, 0755); err != nil {
		return cdir, err
	}

	cf := filepath.Join(cdir, ChartfileName)
	if _, err := os.Stat(cf); err != nil {
		if err := SaveChartfile(cf, chartfile); err != nil {
			return cdir, err
		}
	}

	for _, d := range []string{TemplatesDir, ChartsDir} {
		if err := os.MkdirAll(filepath.Join(cdir, d), 0755); err != nil {
			return cdir, err
		}
	}

	files := []struct {
		path    string
		content []byte
	}{
		{
			// values.yaml
			path:    filepath.Join(cdir, ValuesfileName),
			content: []byte(fmt.Sprintf(defaultValues, chartfile.Name)),
		},
		{
			// .helmignore
			path:    filepath.Join(cdir, IgnorefileName),
			content: []byte(defaultIgnore),
		},
		{
			// ingress.yaml
			path:    filepath.Join(cdir, TemplatesDir, IngressFileName),
			content: Transform(defaultIngress, "<CHARTNAME>", chartfile.Name),
		},
		{
			// deployment.yaml
			path:    filepath.Join(cdir, TemplatesDir, DeploymentName),
			content: Transform(defaultDeployment, "<CHARTNAME>", chartfile.Name),
		},
		{
			// service.yaml
			path:    filepath.Join(cdir, TemplatesDir, ServiceName),
			content: Transform(defaultService, "<CHARTNAME>", chartfile.Name),
		},
		{
			// NOTES.txt
			path:    filepath.Join(cdir, TemplatesDir, NotesName),
			content: Transform(defaultNotes, "<CHARTNAME>", chartfile.Name),
		},
		{
			// _helpers.tpl
			path:    filepath.Join(cdir, TemplatesDir, HelpersName),
			content: Transform(defaultHelpers, "<CHARTNAME>", chartfile.Name),
		},
	}

	for _, file := range files {
		if _, err := os.Stat(file.path); err == nil {
			// File exists and is okay. Skip it.
			continue
		}
		if err := ioutil.WriteFile(file.path, file.content, 0644); err != nil {
			return cdir, err
		}
	}
	return cdir, nil
}
<commit_msg>Add quoting support in ingress to allow wildcard domain<commit_after>/*
Copyright 2016 The Kubernetes Authors 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 chartutil

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"k8s.io/helm/pkg/proto/hapi/chart"
)

const (
	// ChartfileName is the default Chart file name.
	ChartfileName = "Chart.yaml"
	// ValuesfileName is the default values file name.
	ValuesfileName = "values.yaml"
	// TemplatesDir is the relative directory name for templates.
	TemplatesDir = "templates"
	// ChartsDir is the relative directory name for charts dependencies.
	ChartsDir = "charts"
	// IgnorefileName is the name of the Helm ignore file.
	IgnorefileName = ".helmignore"
	// IngressFileName is the name of the example ingress file.
	IngressFileName = "ingress.yaml"
	// DeploymentName is the name of the example deployment file.
	DeploymentName = "deployment.yaml"
	// ServiceName is the name of the example service file.
	ServiceName = "service.yaml"
	// NotesName is the name of the example NOTES.txt file.
	NotesName = "NOTES.txt"
	// HelpersName is the name of the example NOTES.txt file.
	HelpersName = "_helpers.tpl"
)

const defaultValues = `# Default values for %s.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - chart-example.local
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi

nodeSelector: {}

tolerations: []

affinity: {}
`

const defaultIgnore = `# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
`

const defaultIngress = `{{- if .Values.ingress.enabled -}}
{{- $fullName := include "<CHARTNAME>.fullname" . -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ $fullName }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ template "<CHARTNAME>.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
{{- with .Values.ingress.annotations }}
  annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
  tls:
  {{- range .Values.ingress.tls }}
    - hosts:
      {{- range .hosts }}
        - {{ . | quote }}
      {{- end }}
      secretName: {{ .secretName }}
  {{- end }}
{{- end }}
  rules:
  {{- range .Values.ingress.hosts }}
    - host: {{ . | quote }}
      http:
        paths:
          - path: {{ $ingressPath }}
            backend:
              serviceName: {{ $fullName }}
              servicePort: http
  {{- end }}
{{- end }}
`

const defaultDeployment = `apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ template "<CHARTNAME>.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "<CHARTNAME>.name" . }}
      release: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ template "<CHARTNAME>.name" . }}
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
{{ toYaml .Values.resources | indent 12 }}
    {{- with .Values.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
    {{- end }}
`

const defaultService = `apiVersion: v1
kind: Service
metadata:
  name: {{ template "<CHARTNAME>.fullname" . }}
  labels:
    app: {{ template "<CHARTNAME>.name" . }}
    chart: {{ template "<CHARTNAME>.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: {{ template "<CHARTNAME>.name" . }}
    release: {{ .Release.Name }}
`

const defaultNotes = `1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "<CHARTNAME>.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get svc -w {{ template "<CHARTNAME>.fullname" . }}'
  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "<CHARTNAME>.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "<CHARTNAME>.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80
{{- end }}
`

const defaultHelpers = `{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "<CHARTNAME>.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "<CHARTNAME>.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "<CHARTNAME>.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
`

// CreateFrom creates a new chart, but scaffolds it from the src chart.
func CreateFrom(chartfile *chart.Metadata, dest string, src string) error {
	schart, err := Load(src)
	if err != nil {
		return fmt.Errorf("could not load %s: %s", src, err)
	}

	schart.Metadata = chartfile

	var updatedTemplates []*chart.Template

	for _, template := range schart.Templates {
		newData := Transform(string(template.Data), "<CHARTNAME>", schart.Metadata.Name)
		updatedTemplates = append(updatedTemplates, &chart.Template{Name: template.Name, Data: newData})
	}

	schart.Templates = updatedTemplates
	if schart.Values != nil {
		schart.Values = &chart.Config{Raw: string(Transform(schart.Values.Raw, "<CHARTNAME>", schart.Metadata.Name))}
	}
	return SaveDir(schart, dest)
}

// Create creates a new chart in a directory.
//
// Inside of dir, this will create a directory based on the name of
// chartfile.Name. It will then write the Chart.yaml into this directory and
// create the (empty) appropriate directories.
//
// The returned string will point to the newly created directory. It will be
// an absolute path, even if the provided base directory was relative.
//
// If dir does not exist, this will return an error.
// If Chart.yaml or any directories cannot be created, this will return an
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func Create(chartfile *chart.Metadata, dir string) (string, error) {
	path, err := filepath.Abs(dir)
	if err != nil {
		return path, err
	}

	if fi, err := os.Stat(path); err != nil {
		return path, err
	} else if !fi.IsDir() {
		return path, fmt.Errorf("no such directory %s", path)
	}

	n := chartfile.Name
	cdir := filepath.Join(path, n)
	if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() {
		return cdir, fmt.Errorf("file %s already exists and is not a directory", cdir)
	}
	if err := os.MkdirAll(cdir, 0755); err != nil {
		return cdir, err
	}

	cf := filepath.Join(cdir, ChartfileName)
	if _, err := os.Stat(cf); err != nil {
		if err := SaveChartfile(cf, chartfile); err != nil {
			return cdir, err
		}
	}

	for _, d := range []string{TemplatesDir, ChartsDir} {
		if err := os.MkdirAll(filepath.Join(cdir, d), 0755); err != nil {
			return cdir, err
		}
	}

	files := []struct {
		path    string
		content []byte
	}{
		{
			// values.yaml
			path:    filepath.Join(cdir, ValuesfileName),
			content: []byte(fmt.Sprintf(defaultValues, chartfile.Name)),
		},
		{
			// .helmignore
			path:    filepath.Join(cdir, IgnorefileName),
			content: []byte(defaultIgnore),
		},
		{
			// ingress.yaml
			path:    filepath.Join(cdir, TemplatesDir, IngressFileName),
			content: Transform(defaultIngress, "<CHARTNAME>", chartfile.Name),
		},
		{
			// deployment.yaml
			path:    filepath.Join(cdir, TemplatesDir, DeploymentName),
			content: Transform(defaultDeployment, "<CHARTNAME>", chartfile.Name),
		},
		{
			// service.yaml
			path:    filepath.Join(cdir, TemplatesDir, ServiceName),
			content: Transform(defaultService, "<CHARTNAME>", chartfile.Name),
		},
		{
			// NOTES.txt
			path:    filepath.Join(cdir, TemplatesDir, NotesName),
			content: Transform(defaultNotes, "<CHARTNAME>", chartfile.Name),
		},
		{
			// _helpers.tpl
			path:    filepath.Join(cdir, TemplatesDir, HelpersName),
			content: Transform(defaultHelpers, "<CHARTNAME>", chartfile.Name),
		},
	}

	for _, file := range files {
		if _, err := os.Stat(file.path); err == nil {
			// File exists and is okay. Skip it.
			continue
		}
		if err := ioutil.WriteFile(file.path, file.content, 0644); err != nil {
			return cdir, err
		}
	}
	return cdir, nil
}
<|endoftext|>


<commit_before>package slack

import (
	"encoding/json"
	"fmt"
	"github.com/brettbuddin/victor/pkg/chat"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"net/url"
	"os"
)

func init() {
	chat.Register("slack", func(r chat.Robot) chat.Adapter {
		return &slack{
			robot: r,
			team:  os.Getenv("VICTOR_SLACK_TEAM"),
			token: os.Getenv("VICTOR_SLACK_TOKEN"),
		}
	})
}

type slack struct {
	robot chat.Robot
	team  string
	token string
}

func (s *slack) Run() {
	router := mux.NewRouter()
	router.HandleFunc("/hubot/slack-webhook", func(w http.ResponseWriter, r *http.Request) {
		s.robot.Receive(&message{
			userId:      r.PostFormValue("user_id"),
			userName:    r.PostFormValue("user_name"),
			channelId:   r.PostFormValue("channel_id"),
			channelName: r.PostFormValue("channel_name"),
			text:        r.PostFormValue("text"),
		})
	}).Methods("POST")
}

func (s *slack) Send(channelId, msg string) {
	body, err := json.Marshal(&outgoingMessage{
		Channel:  channelId,
		Username: s.robot.Name(),
		Text:     msg,
	})

	if err != nil {
		log.Println("error sending to chat:", err)
	}

	endpoint := fmt.Sprintf("https://%s.slack.com/services/hooks/incoming-webhook?token=%s", s.team, s.token)
	log.Println(endpoint)
	log.Println(string(body))
	log.Println(http.PostForm(endpoint, url.Values{"payload": {string(body)}}))
}

func (s *slack) Stop() {
}

type outgoingMessage struct {
	Channel  string `json:"channel"`
	Username string `json:"username"`
	Text     string `json:"text"`
}

type message struct {
	userId      string
	userName    string
	channelId   string
	channelName string
	text        string
}

func (m *message) UserId() string {
	return m.userId
}

func (m *message) UserName() string {
	return m.userName
}

func (m *message) ChannelId() string {
	return m.channelId
}

func (m *message) ChannelName() string {
	return m.channelName
}

func (m *message) Text() string {
	return m.text
}
<commit_msg>Just map it raw<commit_after>package slack

import (
	"encoding/json"
	"fmt"
	"github.com/brettbuddin/victor/pkg/chat"
	"log"
	"net/http"
	"net/url"
	"os"
)

func init() {
	chat.Register("slack", func(r chat.Robot) chat.Adapter {
		return &slack{
			robot: r,
			team:  os.Getenv("VICTOR_SLACK_TEAM"),
			token: os.Getenv("VICTOR_SLACK_TOKEN"),
		}
	})
}

type slack struct {
	robot chat.Robot
	team  string
	token string
}

func (s *slack) Run() {
	s.robot.HTTP().HandleFunc("/hubot/slack-webhook", func(w http.ResponseWriter, r *http.Request) {
		s.robot.Receive(&message{
			userId:      r.PostFormValue("user_id"),
			userName:    r.PostFormValue("user_name"),
			channelId:   r.PostFormValue("channel_id"),
			channelName: r.PostFormValue("channel_name"),
			text:        r.PostFormValue("text"),
		})
	})
}

func (s *slack) Send(channelId, msg string) {
	body, err := json.Marshal(&outgoingMessage{
		Channel:  channelId,
		Username: s.robot.Name(),
		Text:     msg,
	})

	if err != nil {
		log.Println("error sending to chat:", err)
	}

	endpoint := fmt.Sprintf("https://%s.slack.com/services/hooks/incoming-webhook?token=%s", s.team, s.token)
	log.Println(endpoint)
	log.Println(string(body))
	log.Println(http.PostForm(endpoint, url.Values{"payload": {string(body)}}))
}

func (s *slack) Stop() {
}

type outgoingMessage struct {
	Channel  string `json:"channel"`
	Username string `json:"username"`
	Text     string `json:"text"`
}

type message struct {
	userId      string
	userName    string
	channelId   string
	channelName string
	text        string
}

func (m *message) UserId() string {
	return m.userId
}

func (m *message) UserName() string {
	return m.userName
}

func (m *message) ChannelId() string {
	return m.channelId
}

func (m *message) ChannelName() string {
	return m.channelName
}

func (m *message) Text() string {
	return m.text
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google 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 cron

import (
	"context"
	"time"

	"github.com/grafeas/kritis/pkg/kritis/pods"

	"github.com/grafeas/kritis/pkg/kritis/apis/kritis/v1beta1"
	"github.com/grafeas/kritis/pkg/kritis/crd/securitypolicy"
	"github.com/grafeas/kritis/pkg/kritis/metadata"
	"github.com/grafeas/kritis/pkg/kritis/metadata/containeranalysis"
	"github.com/grafeas/kritis/pkg/kritis/violation"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/client-go/kubernetes"

	"github.com/sirupsen/logrus"
)

// For testing
var (
	checkInterval = 1 * time.Hour
	podChecker    = CheckPods
)

// For testing.
type podLister func(string) ([]corev1.Pod, error)
type violationChecker func(string, v1beta1.ImageSecurityPolicy) ([]metadata.Vulnerability, error)
type violationHandler func(string, *corev1.Pod, []metadata.Vulnerability) error

type Config struct {
	PodLister            podLister
	ViolationChecker     violationChecker
	ViolationStrategy    violation.Strategy
	SecurityPolicyLister func() ([]v1beta1.ImageSecurityPolicy, error)
}

var (
	defaultViolationStrategy = &violation.LoggingStrategy{}
)

func NewCronConfig(cs *kubernetes.Clientset, ca containeranalysis.ContainerAnalysis) *Config {

	vc := func(image string, isp v1beta1.ImageSecurityPolicy) ([]metadata.Vulnerability, error) {
		return securitypolicy.ValidateImageSecurityPolicy(isp, "", image, ca)
	}

	cfg := Config{
		PodLister:            pods.Pods,
		ViolationChecker:     vc,
		ViolationStrategy:    defaultViolationStrategy,
		SecurityPolicyLister: securitypolicy.ImageSecurityPolicies,
	}
	return &cfg
}

// Start starts the background processing of image security policies.
func Start(ctx context.Context, cfg Config) {
	c := time.NewTicker(checkInterval)
	done := ctx.Done()

	for {
		select {
		case <-c.C:
			isps, err := cfg.SecurityPolicyLister()
			if err != nil {
				logrus.Errorf("fetching image security policies: %s", err)
				continue
			}
			if err := podChecker(cfg, isps); err != nil {
				logrus.Errorf("error checking pods: %s", err)
			}
		case <-done:
			return
		}
	}
}

// CheckPods checks all running pods against defined policies.
func CheckPods(cfg Config, isps []v1beta1.ImageSecurityPolicy) error {
	for _, isp := range isps {
		ps, err := cfg.PodLister(isp.Namespace)
		if err != nil {
			return err
		}
		for _, p := range ps {
			for _, c := range pods.Images(p) {
				v, err := cfg.ViolationChecker(c, isp)
				if err != nil {
					return err
				}
				if len(v) != 0 {
					if err := cfg.ViolationStrategy.HandleViolation(c, &p, v); err != nil {
						logrus.Errorf("handling violations: %s", err)
					}
				}
			}
		}
	}
	return nil
}
<commit_msg>Remove violationhandler.<commit_after>/*
Copyright 2018 Google 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 cron

import (
	"context"
	"time"

	"github.com/grafeas/kritis/pkg/kritis/pods"

	"github.com/grafeas/kritis/pkg/kritis/apis/kritis/v1beta1"
	"github.com/grafeas/kritis/pkg/kritis/crd/securitypolicy"
	"github.com/grafeas/kritis/pkg/kritis/metadata"
	"github.com/grafeas/kritis/pkg/kritis/metadata/containeranalysis"
	"github.com/grafeas/kritis/pkg/kritis/violation"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/client-go/kubernetes"

	"github.com/sirupsen/logrus"
)

// For testing
var (
	checkInterval = 1 * time.Hour
	podChecker    = CheckPods
)

// For testing.
type podLister func(string) ([]corev1.Pod, error)
type violationChecker func(string, v1beta1.ImageSecurityPolicy) ([]metadata.Vulnerability, error)

type Config struct {
	PodLister            podLister
	ViolationChecker     violationChecker
	ViolationStrategy    violation.Strategy
	SecurityPolicyLister func() ([]v1beta1.ImageSecurityPolicy, error)
}

var (
	defaultViolationStrategy = &violation.LoggingStrategy{}
)

func NewCronConfig(cs *kubernetes.Clientset, ca containeranalysis.ContainerAnalysis) *Config {

	vc := func(image string, isp v1beta1.ImageSecurityPolicy) ([]metadata.Vulnerability, error) {
		return securitypolicy.ValidateImageSecurityPolicy(isp, "", image, ca)
	}

	cfg := Config{
		PodLister:            pods.Pods,
		ViolationChecker:     vc,
		ViolationStrategy:    defaultViolationStrategy,
		SecurityPolicyLister: securitypolicy.ImageSecurityPolicies,
	}
	return &cfg
}

// Start starts the background processing of image security policies.
func Start(ctx context.Context, cfg Config) {
	c := time.NewTicker(checkInterval)
	done := ctx.Done()

	for {
		select {
		case <-c.C:
			isps, err := cfg.SecurityPolicyLister()
			if err != nil {
				logrus.Errorf("fetching image security policies: %s", err)
				continue
			}
			if err := podChecker(cfg, isps); err != nil {
				logrus.Errorf("error checking pods: %s", err)
			}
		case <-done:
			return
		}
	}
}

// CheckPods checks all running pods against defined policies.
func CheckPods(cfg Config, isps []v1beta1.ImageSecurityPolicy) error {
	for _, isp := range isps {
		ps, err := cfg.PodLister(isp.Namespace)
		if err != nil {
			return err
		}
		for _, p := range ps {
			for _, c := range pods.Images(p) {
				v, err := cfg.ViolationChecker(c, isp)
				if err != nil {
					return err
				}
				if len(v) != 0 {
					if err := cfg.ViolationStrategy.HandleViolation(c, &p, v); err != nil {
						logrus.Errorf("handling violations: %s", err)
					}
				}
			}
		}
	}
	return nil
}
<|endoftext|>