<commit_before>// Copyright 2014 The Go-NetCDF Authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package netcdf

import "C"

const (
	_NC_NOERR    = 0
	_NC_MAX_NAME = 256
	_NC_GLOBAL   = -1 // Attribute id to put/get a global attribute
)

// FileMode represents a file's mode.
type FileMode C.int

// File modes for Open or Create
const (
	NC_DISKLESS FileMode = 0x0008 // use diskless file
	NC_MMAP     FileMode = 0x0010 // use diskless file with mmap
	NC_SHARE    FileMode = 0x0800 // share updates, limit cacheing
)

// File modes for Open
const (
	NC_NOWRITE FileMode = 0x0000 // set read-only access
	NC_WRITE   FileMode = 0x0001 // set read-write access
)

// File modes for Create
const (
	NC_CLOBBER       FileMode = 0x0000 // destroy existing file
	NC_NOCLOBBER     FileMode = 0x0004 // don't destroy existing file
	NC_CLASSIC_MODEL FileMode = 0x0100 // enforce classic model
	NC_NETCDF4       FileMode = 0x1000 // use netCDF-4/HDF5 format
	NC_64BIT_OFFSET  FileMode = 0x0200 // use large (64-bit) file offsets
)

// Type is a netCDF external data type.
type Type C.int

const (
	NC_BYTE   Type = 1      // signed 1 byte integer
	NC_CHAR   Type = 2      // ISO/ASCII character
	NC_SHORT  Type = 3      // signed 2 byte integer
	NC_INT    Type = 4      // signed 4 byte integer
	NC_LONG   Type = NC_INT // deprecated, but required for backward compatibility.
	NC_FLOAT  Type = 5      // single precision floating point number
	NC_DOUBLE Type = 6      // double precision floating point number
	NC_UBYTE  Type = 7      // unsigned 1 byte int
	NC_USHORT Type = 8      // unsigned 2-byte int
	NC_UINT   Type = 9      // unsigned 4-byte int
	NC_INT64  Type = 10     // signed 8-byte int
	NC_UINT64 Type = 11     // unsigned 8-byte int
	NC_STRING Type = 12     // string
)

var typeNames map[Type]string = map[Type]string{
	NC_BYTE:   "NC_BYTE",
	NC_CHAR:   "NC_CHAR",
	NC_SHORT:  "NC_SHORT",
	NC_INT:    "NC_INT",
	NC_FLOAT:  "NC_FLOAT",
	NC_DOUBLE: "NC_DOUBLE",
	NC_UBYTE:  "NC_UBYTE",
	NC_USHORT: "NC_USHORT",
	NC_UINT:   "NC_UINT",
	NC_INT64:  "NC_INT64",
	NC_UINT64: "NC_UINT64",
	NC_STRING: "NC_STRING",
}
<commit_msg>define Type as C.nc_type instead of int<commit_after>// Copyright 2014 The Go-NetCDF Authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package netcdf

// #include <netcdf.h>
import "C"

const (
	_NC_NOERR    = 0
	_NC_MAX_NAME = 256
	_NC_GLOBAL   = -1 // Attribute id to put/get a global attribute
)

// FileMode represents a file's mode.
type FileMode C.int

// File modes for Open or Create
const (
	NC_DISKLESS FileMode = 0x0008 // use diskless file
	NC_MMAP     FileMode = 0x0010 // use diskless file with mmap
	NC_SHARE    FileMode = 0x0800 // share updates, limit cacheing
)

// File modes for Open
const (
	NC_NOWRITE FileMode = 0x0000 // set read-only access
	NC_WRITE   FileMode = 0x0001 // set read-write access
)

// File modes for Create
const (
	NC_CLOBBER       FileMode = 0x0000 // destroy existing file
	NC_NOCLOBBER     FileMode = 0x0004 // don't destroy existing file
	NC_CLASSIC_MODEL FileMode = 0x0100 // enforce classic model
	NC_NETCDF4       FileMode = 0x1000 // use netCDF-4/HDF5 format
	NC_64BIT_OFFSET  FileMode = 0x0200 // use large (64-bit) file offsets
)

// Type is a netCDF external data type.
type Type C.nc_type

const (
	NC_BYTE   Type = 1      // signed 1 byte integer
	NC_CHAR   Type = 2      // ISO/ASCII character
	NC_SHORT  Type = 3      // signed 2 byte integer
	NC_INT    Type = 4      // signed 4 byte integer
	NC_LONG   Type = NC_INT // deprecated, but required for backward compatibility.
	NC_FLOAT  Type = 5      // single precision floating point number
	NC_DOUBLE Type = 6      // double precision floating point number
	NC_UBYTE  Type = 7      // unsigned 1 byte int
	NC_USHORT Type = 8      // unsigned 2-byte int
	NC_UINT   Type = 9      // unsigned 4-byte int
	NC_INT64  Type = 10     // signed 8-byte int
	NC_UINT64 Type = 11     // unsigned 8-byte int
	NC_STRING Type = 12     // string
)

var typeNames map[Type]string = map[Type]string{
	NC_BYTE:   "NC_BYTE",
	NC_CHAR:   "NC_CHAR",
	NC_SHORT:  "NC_SHORT",
	NC_INT:    "NC_INT",
	NC_FLOAT:  "NC_FLOAT",
	NC_DOUBLE: "NC_DOUBLE",
	NC_UBYTE:  "NC_UBYTE",
	NC_USHORT: "NC_USHORT",
	NC_UINT:   "NC_UINT",
	NC_INT64:  "NC_INT64",
	NC_UINT64: "NC_UINT64",
	NC_STRING: "NC_STRING",
}
<|endoftext|>


<commit_before>package sms

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"strconv"
)

const (
	uri         = "https://sms-rassilka.com/api/simple"
	defaultFrom = "inform"

	// Successful delivery statuses.
	StatusQueued    = "0"
	StatusSent      = "1"
	StatusDelivered = "3"

	// Unsuccessful delivery statuses.
	StatusUndeliveredUnavailable = "4"
	StatusUndeliveredSpam        = "15"
	StatusUndeliveredInvPhone    = "16"

	// TODO: Other delivery statuses.
)

// Sender is a library facade for sending SMS and retrieving delivery statuses.
type Sender struct {
	// Login on https://sms-rassilka.com
	Login string

	// MD5-hash of your password.
	PasswordMD5 string

	// SandboxMode is used to test the connection without actually wasting your balance.
	// If false, real SMS are sent and real delivery statuses are retrieved.
	// If true, no SMS are really sent and delivery statuses are fake.
	SandboxMode bool

	// Client allows to make requests with your own HTTP client.
	Client http.Client
}

// SendResult represents a result of sending an SMS.
type SendResult struct {
	SMSID     string
	SMSCnt    int
	SentAt    string
	DebugInfo string
}

// SendSMS sends an SMS right away with the default Sender.
func (s *Sender) SendSMS(to, text string) (SendResult, error) {
	return s.sendSMS(to, text, defaultFrom, "")
}

// SendSMSFrom sends an SMS right away from the specified Sender.
func (s *Sender) SendSMSFrom(to, text, from string) (SendResult, error) {
	return s.sendSMS(to, text, from, "")
}

// SendSMSAt sends an SMS from the default Sender at the specified time.
func (s *Sender) SendSMSAt(to, text, sendTime string) (SendResult, error) {
	return s.sendSMS(to, text, defaultFrom, sendTime)
}

// SendSMSFromAt sends an SMS from the specified Sender at the specified time.
func (s *Sender) SendSMSFromAt(to, text, from, sendTime string) (SendResult, error) {
	return s.sendSMS(to, text, from, sendTime)
}

// QueryStatus requests delivery status of an SMS.
func (s *Sender) QueryStatus(SMSID string) (DeliveryStatus, error) {
	args := map[string]string{
		"smsId": SMSID,
	}
	respReader, err := s.request(uri+"/status", args)
	if err != nil {
		return "", fmt.Errorf("failed to request status: %v", err.Error())
	}
	return s.parseStatusResponse(respReader)
}

func (s *Sender) parseStatusResponse(resp io.ReadCloser) (DeliveryStatus, error) {
	defer resp.Close()
	scanner := bufio.NewScanner(resp)
	// TODO: What if a scanner hits EOF?
	scanner.Scan()
	code := scanner.Text()
	scanner.Scan()
	t := scanner.Text()
	if code != "1" {
		return "", fmt.Errorf("error response: %s %s", code, t)
	}
	return DeliveryStatus(t), nil
}

func (s *Sender) sendSMS(to, text, from, sendTime string) (SendResult, error) {
	args := map[string]string{
		"to":   to,
		"text": text,
	}
	if from != "" {
		args["from"] = from
	}
	if sendTime != "" {
		args["sendTime"] = sendTime
	}
	respReader, err := s.request(uri+"/send", args)
	if err != nil {
		return SendResult{}, fmt.Errorf("failed to request the service: %v", err)
	}
	return s.parseSendSMSResponse(respReader)
}

func (s *Sender) parseSendSMSResponse(resp io.ReadCloser) (SendResult, error) {
	defer resp.Close()
	result := SendResult{}
	scanner := bufio.NewScanner(resp)
	// TODO: What if a scanner hits EOF?
	scanner.Scan()
	code := scanner.Text()
	if code != "1" {
		scanner.Scan()
		return SendResult{}, fmt.Errorf("got error response: %s %s", code, scanner.Text())
	}

	for line := 0; scanner.Scan(); line++ {
		switch line {
		case 0:
			result.SMSID = scanner.Text()
		case 1:
			c, err := strconv.Atoi(scanner.Text())
			if err != nil {
				return SendResult{}, fmt.Errorf("bad SMS count: %v", err)
			}
			result.SMSCnt = c
		case 2:
			result.SentAt = scanner.Text()
		default:
			result.DebugInfo += scanner.Text() + "\n"
		}
	}
	if err := scanner.Err(); err != nil {
		return SendResult{}, fmt.Errorf("bad response: %v", err.Error())
	}
	return result, nil
}

func (s *Sender) request(uri string, args map[string]string) (io.ReadCloser, error) {
	// The error is caught during tests.
	req, _ := http.NewRequest(http.MethodGet, uri, nil)
	q := req.URL.Query()
	q.Set("login", s.Login)
	q.Set("password", s.PasswordMD5)
	if s.SandboxMode {
		q.Set("mode", "dev")
	}
	for k, v := range args {
		q.Set(k, v)
	}
	req.URL.RawQuery = q.Encode()
	resp, err := s.Client.Do(req)
	if err != nil {
		return nil, err
	}
	return resp.Body, nil
}

// DeliveryStatus represents a delivery status. If you need an exact status, compare with constants above.
type DeliveryStatus string

// IsInProgress tells if a message is still being processed.
func (d DeliveryStatus) IsInProgress() bool {
	return d == StatusQueued || d == StatusSent
}

// IsDelivered tells if a message has in fact been delivered.
func (d DeliveryStatus) IsDelivered() bool {
	return d == StatusDelivered
}

// IsUndelivered tells if a message has been processed and undelivered by any reason.
func (d DeliveryStatus) IsUndelivered() bool {
	return !d.IsInProgress() && !d.IsDelivered()
}
<commit_msg>Delegated reader closing to appropriate functions<commit_after>package sms

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"strconv"
)

const (
	uri         = "https://sms-rassilka.com/api/simple"
	defaultFrom = "inform"

	// Successful delivery statuses.
	StatusQueued    = "0"
	StatusSent      = "1"
	StatusDelivered = "3"

	// Unsuccessful delivery statuses.
	StatusUndeliveredUnavailable = "4"
	StatusUndeliveredSpam        = "15"
	StatusUndeliveredInvPhone    = "16"

	// TODO: Other delivery statuses.
)

// Sender is a library facade for sending SMS and retrieving delivery statuses.
type Sender struct {
	// Login on https://sms-rassilka.com
	Login string

	// MD5-hash of your password.
	PasswordMD5 string

	// SandboxMode is used to test the connection without actually wasting your balance.
	// If false, real SMS are sent and real delivery statuses are retrieved.
	// If true, no SMS are really sent and delivery statuses are fake.
	SandboxMode bool

	// Client allows to make requests with your own HTTP client.
	Client http.Client
}

// SendResult represents a result of sending an SMS.
type SendResult struct {
	SMSID     string
	SMSCnt    int
	SentAt    string
	DebugInfo string
}

// SendSMS sends an SMS right away with the default Sender.
func (s *Sender) SendSMS(to, text string) (SendResult, error) {
	return s.sendSMS(to, text, defaultFrom, "")
}

// SendSMSFrom sends an SMS right away from the specified Sender.
func (s *Sender) SendSMSFrom(to, text, from string) (SendResult, error) {
	return s.sendSMS(to, text, from, "")
}

// SendSMSAt sends an SMS from the default Sender at the specified time.
func (s *Sender) SendSMSAt(to, text, sendTime string) (SendResult, error) {
	return s.sendSMS(to, text, defaultFrom, sendTime)
}

// SendSMSFromAt sends an SMS from the specified Sender at the specified time.
func (s *Sender) SendSMSFromAt(to, text, from, sendTime string) (SendResult, error) {
	return s.sendSMS(to, text, from, sendTime)
}

// QueryStatus requests delivery status of an SMS.
func (s *Sender) QueryStatus(SMSID string) (DeliveryStatus, error) {
	args := map[string]string{
		"smsId": SMSID,
	}
	resp, err := s.request(uri+"/status", args)
	if err != nil {
		return "", fmt.Errorf("failed to request status: %v", err.Error())
	}
	defer resp.Close()
	return s.parseStatusResponse(resp)
}

func (s *Sender) parseStatusResponse(resp io.Reader) (DeliveryStatus, error) {
	scanner := bufio.NewScanner(resp)
	// TODO: What if a scanner hits EOF?
	scanner.Scan()
	code := scanner.Text()
	scanner.Scan()
	t := scanner.Text()
	if code != "1" {
		return "", fmt.Errorf("error response: %s %s", code, t)
	}
	return DeliveryStatus(t), nil
}

func (s *Sender) sendSMS(to, text, from, sendTime string) (SendResult, error) {
	args := map[string]string{
		"to":   to,
		"text": text,
	}
	if from != "" {
		args["from"] = from
	}
	if sendTime != "" {
		args["sendTime"] = sendTime
	}
	resp, err := s.request(uri+"/send", args)
	if err != nil {
		return SendResult{}, fmt.Errorf("failed to request the service: %v", err)
	}
	defer resp.Close()
	return s.parseSendSMSResponse(resp)
}

func (s *Sender) parseSendSMSResponse(resp io.Reader) (SendResult, error) {
	result := SendResult{}
	scanner := bufio.NewScanner(resp)
	// TODO: What if a scanner hits EOF?
	scanner.Scan()
	code := scanner.Text()
	if code != "1" {
		scanner.Scan()
		return SendResult{}, fmt.Errorf("got error response: %s %s", code, scanner.Text())
	}

	for line := 0; scanner.Scan(); line++ {
		switch line {
		case 0:
			result.SMSID = scanner.Text()
		case 1:
			c, err := strconv.Atoi(scanner.Text())
			if err != nil {
				return SendResult{}, fmt.Errorf("bad SMS count: %v", err)
			}
			result.SMSCnt = c
		case 2:
			result.SentAt = scanner.Text()
		default:
			result.DebugInfo += scanner.Text() + "\n"
		}
	}
	if err := scanner.Err(); err != nil {
		return SendResult{}, fmt.Errorf("bad response: %v", err.Error())
	}
	return result, nil
}

func (s *Sender) request(uri string, args map[string]string) (io.ReadCloser, error) {
	// The error is caught during tests.
	req, _ := http.NewRequest(http.MethodGet, uri, nil)
	q := req.URL.Query()
	q.Set("login", s.Login)
	q.Set("password", s.PasswordMD5)
	if s.SandboxMode {
		q.Set("mode", "dev")
	}
	for k, v := range args {
		q.Set(k, v)
	}
	req.URL.RawQuery = q.Encode()
	resp, err := s.Client.Do(req)
	if err != nil {
		return nil, err
	}
	return resp.Body, nil
}

// DeliveryStatus represents a delivery status. If you need an exact status, compare with constants above.
type DeliveryStatus string

// IsInProgress tells if a message is still being processed.
func (d DeliveryStatus) IsInProgress() bool {
	return d == StatusQueued || d == StatusSent
}

// IsDelivered tells if a message has in fact been delivered.
func (d DeliveryStatus) IsDelivered() bool {
	return d == StatusDelivered
}

// IsUndelivered tells if a message has been processed and undelivered by any reason.
func (d DeliveryStatus) IsUndelivered() bool {
	return !d.IsInProgress() && !d.IsDelivered()
}
<|endoftext|>


<commit_before>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libhttpserver

import (
	"net/http"
	"strings"
)

type contentTypeOverridingResponseWriter struct {
	original http.ResponseWriter
}

var _ http.ResponseWriter = (*contentTypeOverridingResponseWriter)(nil)

func newContentTypeOverridingResponseWriter(
	original http.ResponseWriter) *contentTypeOverridingResponseWriter {
	return &contentTypeOverridingResponseWriter{
		original: original,
	}
}

// supportedContentTypes has exceptions to the libmime stuff because some types
// need special handling or are unsupported by frontend. The boolean value
// decides on whether this will be shown inline or as an attachment.
// We don't want to render SVG unless that has been audited, even if
// the file lacks a .svg extension.
var supportedContentTypes = map[string]bool{
	// Media
	"image/tiff":         false,
	"image/x-jng":        false,
	"image/vnd.wap.wbmp": false,
	"image/svg+xml":      false,
}

// displayInlineDefault decides on the Content-Disposition value (inline vs attachment) for
// the given mimeType by consulting the supportedContentTypes map and using the defaultValue
// parameter.
func displayInlineDefault(defaultValue bool, mimeType string) string {
	res, found := supportedContentTypes[mimeType]
	if (found && res) || (!found && defaultValue) {
		return "inline"
	}
	return "attachment"
}

func (w *contentTypeOverridingResponseWriter) calculateOverride(
	mimeType string) (newMimeType, disposition string) {
	// Send text/plain for all HTML and JS files to avoid them being executed
	// by the frontend WebView.
	ty := strings.ToLower(mimeType)
	switch {
	// First anything textual as text/plain.
	// Javascript is set to plain text by additionalMimeTypes map.
	// If text/something-dangerous would get here, we set it to plaintext.
	// If application/javascript somehow gets here it would be handled safely
	// by the default handler below.
	case strings.HasPrefix(ty, "text/"):
		return "text/plain", "inline"
	// Pass multimedia types through, and pdf too.
	// Some types get special handling here and are not shown inline (e.g. SVG).
	case strings.HasPrefix(ty, "audio/") ||
		strings.HasPrefix(ty, "image/") ||
		strings.HasPrefix(ty, "video/") ||
		ty == "application/pdf":
		return ty, displayInlineDefault(true, ty)
	// Otherwise default to text + attachment.
	// This is safe for all files.
	default:
		return "text/plain", "attachment"
	}
}

func (w *contentTypeOverridingResponseWriter) override() {
	t := w.original.Header().Get("Content-Type")
	if len(t) > 0 {
		ct, disp := w.calculateOverride(t)
		w.original.Header().Set("Content-Type", ct)
		w.original.Header().Set("Content-Disposition", disp)
	}
	w.original.Header().Set("X-Content-Type-Options", "nosniff")
}

func (w *contentTypeOverridingResponseWriter) Header() http.Header {
	return w.original.Header()
}

func (w *contentTypeOverridingResponseWriter) WriteHeader(statusCode int) {
	w.override()
	w.original.WriteHeader(statusCode)
}

func (w *contentTypeOverridingResponseWriter) Write(data []byte) (int, error) {
	w.override()
	return w.original.Write(data)
}

var additionalMimeTypes = map[string]string{
	".go":    "text/plain",
	".py":    "text/plain",
	".zsh":   "text/plain",
	".fish":  "text/plain",
	".cs":    "text/plain",
	".rb":    "text/plain",
	".m":     "text/plain",
	".mm":    "text/plain",
	".swift": "text/plain",
	".flow":  "text/plain",
	".php":   "text/plain",
	".pl":    "text/plain",
	".pm":    "text/plain",
	".sh":    "text/plain",
	".js":    "text/plain",
	".json":  "text/plain",
	".sql":   "text/plain",
	".rs":    "text/plain",
	".xml":   "text/plain",
	".tex":   "text/plain",
	".pub":   "text/plain",
	".atom":  "text/plain",
	".xhtml": "text/plain",
	".rss":   "text/plain",
	".tcl":   "text/plain",
	".tk":    "text/plain",
}
<commit_msg>libhttpserver: Rename displayInlineDefault to getDisposition<commit_after>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libhttpserver

import (
	"net/http"
	"strings"
)

type contentTypeOverridingResponseWriter struct {
	original http.ResponseWriter
}

var _ http.ResponseWriter = (*contentTypeOverridingResponseWriter)(nil)

func newContentTypeOverridingResponseWriter(
	original http.ResponseWriter) *contentTypeOverridingResponseWriter {
	return &contentTypeOverridingResponseWriter{
		original: original,
	}
}

// supportedContentTypes has exceptions to the libmime stuff because some types
// need special handling or are unsupported by frontend. The boolean value
// decides on whether this will be shown inline or as an attachment.
// We don't want to render SVG unless that has been audited, even if
// the file lacks a .svg extension.
var supportedContentTypes = map[string]bool{
	// Media
	"image/tiff":         false,
	"image/x-jng":        false,
	"image/vnd.wap.wbmp": false,
	"image/svg+xml":      false,
}

// getDisposition decides on the Content-Disposition value (inline vs attachment) for
// the given mimeType by consulting the supportedContentTypes map and using the defaultValue
// parameter.
func getDisposition(defaultInlineValue bool, mimeType string) string {
	res, found := supportedContentTypes[mimeType]
	if (found && res) || (!found && defaultInlineValue) {
		return "inline"
	}
	return "attachment"
}

func (w *contentTypeOverridingResponseWriter) calculateOverride(
	mimeType string) (newMimeType, disposition string) {
	// Send text/plain for all HTML and JS files to avoid them being executed
	// by the frontend WebView.
	ty := strings.ToLower(mimeType)
	switch {
	// First anything textual as text/plain.
	// Javascript is set to plain text by additionalMimeTypes map.
	// If text/something-dangerous would get here, we set it to plaintext.
	// If application/javascript somehow gets here it would be handled safely
	// by the default handler below.
	case strings.HasPrefix(ty, "text/"):
		return "text/plain", "inline"
	// Pass multimedia types through, and pdf too.
	// Some types get special handling here and are not shown inline (e.g. SVG).
	case strings.HasPrefix(ty, "audio/") ||
		strings.HasPrefix(ty, "image/") ||
		strings.HasPrefix(ty, "video/") ||
		ty == "application/pdf":
		return ty, getDisposition(true, ty)
	// Otherwise default to text + attachment.
	// This is safe for all files.
	default:
		return "text/plain", "attachment"
	}
}

func (w *contentTypeOverridingResponseWriter) override() {
	t := w.original.Header().Get("Content-Type")
	if len(t) > 0 {
		ct, disp := w.calculateOverride(t)
		w.original.Header().Set("Content-Type", ct)
		w.original.Header().Set("Content-Disposition", disp)
	}
	w.original.Header().Set("X-Content-Type-Options", "nosniff")
}

func (w *contentTypeOverridingResponseWriter) Header() http.Header {
	return w.original.Header()
}

func (w *contentTypeOverridingResponseWriter) WriteHeader(statusCode int) {
	w.override()
	w.original.WriteHeader(statusCode)
}

func (w *contentTypeOverridingResponseWriter) Write(data []byte) (int, error) {
	w.override()
	return w.original.Write(data)
}

var additionalMimeTypes = map[string]string{
	".go":    "text/plain",
	".py":    "text/plain",
	".zsh":   "text/plain",
	".fish":  "text/plain",
	".cs":    "text/plain",
	".rb":    "text/plain",
	".m":     "text/plain",
	".mm":    "text/plain",
	".swift": "text/plain",
	".flow":  "text/plain",
	".php":   "text/plain",
	".pl":    "text/plain",
	".pm":    "text/plain",
	".sh":    "text/plain",
	".js":    "text/plain",
	".json":  "text/plain",
	".sql":   "text/plain",
	".rs":    "text/plain",
	".xml":   "text/plain",
	".tex":   "text/plain",
	".pub":   "text/plain",
	".atom":  "text/plain",
	".xhtml": "text/plain",
	".rss":   "text/plain",
	".tcl":   "text/plain",
	".tk":    "text/plain",
}
<|endoftext|>


<commit_before>package gomol

import (
	. "gopkg.in/check.v1"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type GomolSuite struct{}

var _ = Suite(&GomolSuite{})

func (s *GomolSuite) TestAddLogger(c *C) {
	b := newBase()
	c.Check(b.loggers, HasLen, 0)

	ml := NewMemLogger()
	c.Check(ml.base, IsNil)

	b.AddLogger(ml)
	c.Check(b.loggers, HasLen, 1)
	c.Check(ml.base, Equals, b)
}

func (s *GomolSuite) TestInitLoggers(c *C) {
	b := newBase()

	ml1 := NewMemLogger()
	ml2 := NewMemLogger()

	b.AddLogger(ml1)
	b.AddLogger(ml2)

	b.InitLoggers()

	c.Check(ml1.IsInitialized, Equals, true)
	c.Check(ml2.IsInitialized, Equals, true)
}

func (s *GomolSuite) TestShutdownLoggers(c *C) {
	b := newBase()

	ml1 := NewMemLogger()
	ml2 := NewMemLogger()

	b.AddLogger(ml1)
	b.AddLogger(ml2)

	b.ShutdownLoggers()

	c.Check(ml1.IsShutdown, Equals, true)
	c.Check(ml2.IsShutdown, Equals, true)
}

func (s *GomolSuite) TestSetAttr(c *C) {
	b := newBase()

	b.SetAttr("attr1", 1)
	c.Check(b.BaseAttrs, HasLen, 1)
	c.Check(b.BaseAttrs["attr1"], Equals, 1)
	b.SetAttr("attr2", "val2")
	c.Check(b.BaseAttrs, HasLen, 2)
	c.Check(b.BaseAttrs["attr2"], Equals, "val2")
}

func (s *GomolSuite) TestRemoveAttr(c *C) {
	b := newBase()

	b.SetAttr("attr1", 1)
	c.Check(b.BaseAttrs, HasLen, 1)
	c.Check(b.BaseAttrs["attr1"], Equals, 1)

	b.RemoveAttr("attr1")
	c.Check(b.BaseAttrs, HasLen, 0)
}

func (s *GomolSuite) TestClearAttrs(c *C) {
	b := newBase()

	b.SetAttr("attr1", 1)
	b.SetAttr("attr2", "val2")
	c.Check(b.BaseAttrs, HasLen, 2)

	b.ClearAttrs()
	c.Check(b.BaseAttrs, HasLen, 0)
}
<commit_msg>Add more tests for base<commit_after>package gomol

import (
	. "gopkg.in/check.v1"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type GomolSuite struct{}

var _ = Suite(&GomolSuite{})

func (s *GomolSuite) TestAddLogger(c *C) {
	b := newBase()
	c.Check(b.loggers, HasLen, 0)

	ml := NewMemLogger()
	c.Check(ml.base, IsNil)

	b.AddLogger(ml)
	c.Check(b.loggers, HasLen, 1)
	c.Check(ml.base, Equals, b)
}

func (s *GomolSuite) TestInitLoggers(c *C) {
	b := newBase()

	ml1 := NewMemLogger()
	ml2 := NewMemLogger()

	b.AddLogger(ml1)
	b.AddLogger(ml2)

	b.InitLoggers()

	c.Check(ml1.IsInitialized, Equals, true)
	c.Check(ml2.IsInitialized, Equals, true)
}

func (s *GomolSuite) TestShutdownLoggers(c *C) {
	b := newBase()

	ml1 := NewMemLogger()
	ml2 := NewMemLogger()

	b.AddLogger(ml1)
	b.AddLogger(ml2)

	b.ShutdownLoggers()

	c.Check(ml1.IsShutdown, Equals, true)
	c.Check(ml2.IsShutdown, Equals, true)
}

func (s *GomolSuite) TestSetAttr(c *C) {
	b := newBase()

	b.SetAttr("attr1", 1)
	c.Check(b.BaseAttrs, HasLen, 1)
	c.Check(b.BaseAttrs["attr1"], Equals, 1)
	b.SetAttr("attr2", "val2")
	c.Check(b.BaseAttrs, HasLen, 2)
	c.Check(b.BaseAttrs["attr2"], Equals, "val2")
}

func (s *GomolSuite) TestRemoveAttr(c *C) {
	b := newBase()

	b.SetAttr("attr1", 1)
	c.Check(b.BaseAttrs, HasLen, 1)
	c.Check(b.BaseAttrs["attr1"], Equals, 1)

	b.RemoveAttr("attr1")
	c.Check(b.BaseAttrs, HasLen, 0)
}

func (s *GomolSuite) TestClearAttrs(c *C) {
	b := newBase()

	b.SetAttr("attr1", 1)
	b.SetAttr("attr2", "val2")
	c.Check(b.BaseAttrs, HasLen, 2)

	b.ClearAttrs()
	c.Check(b.BaseAttrs, HasLen, 0)
}

// Base func tests

func (s *GomolSuite) TestBaseDbg(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Dbg("test")

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelDbg)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelDbg)
}

func (s *GomolSuite) TestBaseDbgf(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Dbgf("test %v", 1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelDbg)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelDbg)
}

func (s *GomolSuite) TestBaseDbgm(c *C) {
	b := newBase()
	b.SetAttr("attr1", 1234)

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Dbgm(
		map[string]interface{}{
			"attr2": 4321,
			"attr3": "val3",
		},
		"test %v",
		1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Assert(l1.Messages[0].Attrs, HasLen, 3)
	c.Check(l1.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l1.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l1.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l1.Messages[0].Level, Equals, levelDbg)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Assert(l2.Messages[0].Attrs, HasLen, 3)
	c.Check(l2.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l2.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l2.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l2.Messages[0].Level, Equals, levelDbg)
}

func (s *GomolSuite) TestBaseInfo(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Info("test")

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelInfo)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelInfo)
}

func (s *GomolSuite) TestBaseInfof(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Infof("test %v", 1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelInfo)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelInfo)
}

func (s *GomolSuite) TestBaseInfom(c *C) {
	b := newBase()
	b.SetAttr("attr1", 1234)

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Infom(
		map[string]interface{}{
			"attr2": 4321,
			"attr3": "val3",
		},
		"test %v",
		1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Assert(l1.Messages[0].Attrs, HasLen, 3)
	c.Check(l1.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l1.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l1.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l1.Messages[0].Level, Equals, levelInfo)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Assert(l2.Messages[0].Attrs, HasLen, 3)
	c.Check(l2.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l2.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l2.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l2.Messages[0].Level, Equals, levelInfo)
}

func (s *GomolSuite) TestBaseWarn(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Warn("test")

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelWarn)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelWarn)
}

func (s *GomolSuite) TestBaseWarnf(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Warnf("test %v", 1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelWarn)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelWarn)
}

func (s *GomolSuite) TestBaseWarnm(c *C) {
	b := newBase()
	b.SetAttr("attr1", 1234)

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Warnm(
		map[string]interface{}{
			"attr2": 4321,
			"attr3": "val3",
		},
		"test %v",
		1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Assert(l1.Messages[0].Attrs, HasLen, 3)
	c.Check(l1.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l1.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l1.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l1.Messages[0].Level, Equals, levelWarn)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Assert(l2.Messages[0].Attrs, HasLen, 3)
	c.Check(l2.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l2.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l2.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l2.Messages[0].Level, Equals, levelWarn)
}

func (s *GomolSuite) TestBaseErr(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Err("test")

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelError)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelError)
}

func (s *GomolSuite) TestBaseErrf(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Errf("test %v", 1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelError)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelError)
}

func (s *GomolSuite) TestBaseErrm(c *C) {
	b := newBase()
	b.SetAttr("attr1", 1234)

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Errm(
		map[string]interface{}{
			"attr2": 4321,
			"attr3": "val3",
		},
		"test %v",
		1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Assert(l1.Messages[0].Attrs, HasLen, 3)
	c.Check(l1.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l1.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l1.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l1.Messages[0].Level, Equals, levelError)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Assert(l2.Messages[0].Attrs, HasLen, 3)
	c.Check(l2.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l2.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l2.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l2.Messages[0].Level, Equals, levelError)
}

func (s *GomolSuite) TestBaseFatal(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Fatal("test")

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelFatal)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelFatal)
}

func (s *GomolSuite) TestBaseFatalf(c *C) {
	b := newBase()

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Fatalf("test %v", 1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Check(l1.Messages[0].Attrs, HasLen, 0)
	c.Check(l1.Messages[0].Level, Equals, levelFatal)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Check(l2.Messages[0].Attrs, HasLen, 0)
	c.Check(l2.Messages[0].Level, Equals, levelFatal)
}

func (s *GomolSuite) TestBaseFatalm(c *C) {
	b := newBase()
	b.SetAttr("attr1", 1234)

	l1 := NewMemLogger()
	l2 := NewMemLogger()

	b.AddLogger(l1)
	b.AddLogger(l2)

	b.Fatalm(
		map[string]interface{}{
			"attr2": 4321,
			"attr3": "val3",
		},
		"test %v",
		1234)

	c.Assert(l1.Messages, HasLen, 1)
	c.Check(l1.Messages[0].Message, Equals, "test 1234")
	c.Assert(l1.Messages[0].Attrs, HasLen, 3)
	c.Check(l1.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l1.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l1.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l1.Messages[0].Level, Equals, levelFatal)

	c.Assert(l2.Messages, HasLen, 1)
	c.Check(l2.Messages[0].Message, Equals, "test 1234")
	c.Assert(l2.Messages[0].Attrs, HasLen, 3)
	c.Check(l2.Messages[0].Attrs["attr1"], Equals, 1234)
	c.Check(l2.Messages[0].Attrs["attr2"], Equals, 4321)
	c.Check(l2.Messages[0].Attrs["attr3"], Equals, "val3")
	c.Check(l2.Messages[0].Level, Equals, levelFatal)
}
<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"log"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	pzsyslog "github.com/venicegeo/pz-gocommon/syslog"
	pzworkflow "github.com/venicegeo/pz-workflow/workflow"
)

func main() {
	log.Printf("pz-workflow starting...")

	sys, logWriter, auditWriter := makeClients()

	kit, err := pzworkflow.NewKit(sys, logWriter, auditWriter, false)
	if err != nil {
		log.Fatal(err)
	}

	err = kit.Start()
	if err != nil {
		log.Fatal(err)
	}

	err = kit.Wait()
	if err != nil {
		log.Fatal(err)
	}
}

func makeClients() (
	*piazza.SystemConfig,
	pzsyslog.Writer,
	pzsyslog.Writer) {

	required := []piazza.ServiceName{
		piazza.PzElasticSearch,
		piazza.PzLogger,
		piazza.PzKafka,
		piazza.PzServiceController,
		piazza.PzIdam,
	}

	sys, err := piazza.NewSystemConfig(piazza.PzWorkflow, required)
	if err != nil {
		log.Fatal(err)
	}

	loggerIndex, loggerType, auditType, err := pzsyslog.GetRequiredEnvVars()
	if err != nil {
		log.Fatal(err)
	}

	idx, err := elasticsearch.NewIndex(sys, loggerIndex, "")
	if err != nil {
		log.Fatal(err)
	}

	logWriter, auditWriter, err := pzsyslog.GetRequiredESIWriters(idx, loggerType, auditType)
	if err != nil {
		log.Fatal(err)
	}

	stdOutWriter := pzsyslog.StdoutWriter{}

	return sys, logWriter, pzsyslog.NewMultiWriter([]pzsyslog.Writer{auditWriter, &stdOutWriter})
}
<commit_msg>Removed logger as a required service<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"log"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	pzsyslog "github.com/venicegeo/pz-gocommon/syslog"
	pzworkflow "github.com/venicegeo/pz-workflow/workflow"
)

func main() {
	log.Printf("pz-workflow starting...")

	sys, logWriter, auditWriter := makeClients()

	kit, err := pzworkflow.NewKit(sys, logWriter, auditWriter, false)
	if err != nil {
		log.Fatal(err)
	}

	err = kit.Start()
	if err != nil {
		log.Fatal(err)
	}

	err = kit.Wait()
	if err != nil {
		log.Fatal(err)
	}
}

func makeClients() (
	*piazza.SystemConfig,
	pzsyslog.Writer,
	pzsyslog.Writer) {

	required := []piazza.ServiceName{
		piazza.PzElasticSearch,
		piazza.PzKafka,
		piazza.PzServiceController,
		piazza.PzIdam,
	}

	sys, err := piazza.NewSystemConfig(piazza.PzWorkflow, required)
	if err != nil {
		log.Fatal(err)
	}

	loggerIndex, loggerType, auditType, err := pzsyslog.GetRequiredEnvVars()
	if err != nil {
		log.Fatal(err)
	}

	idx, err := elasticsearch.NewIndex(sys, loggerIndex, "")
	if err != nil {
		log.Fatal(err)
	}

	logWriter, auditWriter, err := pzsyslog.GetRequiredESIWriters(idx, loggerType, auditType)
	if err != nil {
		log.Fatal(err)
	}

	stdOutWriter := pzsyslog.StdoutWriter{}

	return sys, logWriter, pzsyslog.NewMultiWriter([]pzsyslog.Writer{auditWriter, &stdOutWriter})
}
<|endoftext|>


<commit_before>package kex

import (
	"github.com/keybase/client/go/libkb"
)

// For convenience, store libkb's G here...
var G *libkb.GlobalContext

func init() {
	G = libkb.G
}
<commit_msg>don't copy G into this package<commit_after>package kex

// For convenience, store libkb's G here...
/*
var G *libkb.GlobalContext

func init() {
	G = libkb.G
}
*/
<|endoftext|>


<commit_before>// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

// APIImages represent an image returned in the ListImages call.
type APIImages struct {
	ID          string   `json:"Id" yaml:"Id"`
	RepoTags    []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
	Created     int64    `json:"Created,omitempty" yaml:"Created,omitempty"`
	Size        int64    `json:"Size,omitempty" yaml:"Size,omitempty"`
	VirtualSize int64    `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
	ParentId    string   `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
}

type Image struct {
	ID              string    `json:"Id" yaml:"Id"`
	Parent          string    `json:"Parent,omitempty" yaml:"Parent,omitempty"`
	Comment         string    `json:"Comment,omitempty" yaml:"Comment,omitempty"`
	Created         time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
	Container       string    `json:"Container,omitempty" yaml:"Container,omitempty"`
	ContainerConfig Config    `json:"ContainerConfig,omitempty" yaml:"ContainerConfig,omitempty"`
	DockerVersion   string    `json:"DockerVersion,omitempty" yaml:"DockerVersion,omitempty"`
	Author          string    `json:"Author,omitempty" yaml:"Author,omitempty"`
	Config          *Config   `json:"Config,omitempty" yaml:"Config,omitempty"`
	Architecture    string    `json:"Architecture,omitempty" yaml:"Architecture,omitempty"`
	Size            int64     `json:"Size,omitempty" yaml:"Size,omitempty"`
}

// ImageHistory represent a layer in an image's history returned by the
// ImageHistory call.
type ImageHistory struct {
	ID        string   `json:"Id" yaml:"Id"`
	Tags      []string `json:"Tags,omitempty" yaml:"Tags,omitempty"`
	Created   int64    `json:"Created,omitempty" yaml:"Created,omitempty"`
	CreatedBy string   `json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
	Size      int64    `json:"Size,omitempty" yaml:"Size,omitempty"`
}

type ImagePre012 struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"container_config,omitempty"`
	DockerVersion   string    `json:"docker_version,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64     `json:"size,omitempty"`
}

var (
	// ErrNoSuchImage is the error returned when the image does not exist.
	ErrNoSuchImage = errors.New("no such image")

	// ErrMissingRepo is the error returned when the remote repository is
	// missing.
	ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")

	// ErrMissingOutputStream is the error returned when no output stream
	// is provided to some calls, like BuildImage.
	ErrMissingOutputStream = errors.New("missing output stream")

	// ErrMultipleContexts is the error returned when both a ContextDir and
	// InputStream are provided in BuildImageOptions
	ErrMultipleContexts = errors.New("image build may not be provided BOTH context dir and input stream")
)

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/VmcR6v for more details.
func (c *Client) ListImages(all bool) ([]APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// ImageHistory returns the history of the image by its name or ID.
//
// See http://goo.gl/2oJmNs for more details.
func (c *Client) ImageHistory(name string) ([]ImageHistory, error) {
	body, status, err := c.do("GET", "/images/"+name+"/history", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}
	var history []ImageHistory
	err = json.Unmarshal(body, &history)
	if err != nil {
		return nil, err
	}
	return history, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/znj0wM for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/Q112NY for more details.
func (c *Client) InspectImage(name string) (*Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}

	var image Image

	// if the caller elected to skip checking the server's version, assume it's the latest
	if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
		err = json.Unmarshal(body, &image)
		if err != nil {
			return nil, err
		}
	} else {
		var imagePre012 ImagePre012
		err = json.Unmarshal(body, &imagePre012)
		if err != nil {
			return nil, err
		}

		image.ID = imagePre012.ID
		image.Parent = imagePre012.Parent
		image.Comment = imagePre012.Comment
		image.Created = imagePre012.Created
		image.Container = imagePre012.Container
		image.ContainerConfig = imagePre012.ContainerConfig
		image.DockerVersion = imagePre012.DockerVersion
		image.Author = imagePre012.Author
		image.Config = imagePre012.Config
		image.Architecture = imagePre012.Architecture
		image.Size = imagePre012.Size
	}

	return &image, nil
}

// PushImageOptions represents options to use in the PushImage method.
//
// See http://goo.gl/pN8A3P for more details.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Tag of the image
	Tag string

	// Registry server to push the image
	Registry string

	OutputStream  io.Writer `qs:"-"`
	RawJSONStream bool      `qs:"-"`
}

// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authentication in the Docker index server.
type AuthConfiguration struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	Email    string `json:"email,omitempty"`
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// An empty instance of AuthConfiguration may be used for unauthenticated
// pushes.
//
// See http://goo.gl/pN8A3P for more details.
func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	headers := headersWithAuth(&auth)
	return c.stream("POST", path, true, opts.RawJSONStream, headers, nil, opts.OutputStream, nil)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/ACyYNS for more details.
type PullImageOptions struct {
	Repository    string `qs:"fromImage"`
	Registry      string
	Tag           string
	OutputStream  io.Writer `qs:"-"`
	RawJSONStream bool      `qs:"-"`
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/ACyYNS for more details.
func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}

	headers := headersWithAuth(&auth)
	return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
}

func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool) error {
	path := "/images/create?" + qs
	return c.stream("POST", path, true, rawJSONStream, headers, in, w, nil)
}

// LoadImageOptions represents the options for LoadImage Docker API Call
//
// See http://goo.gl/Y8NNCq for more details.
type LoadImageOptions struct {
	InputStream io.Reader
}

// LoadImage imports a tarball docker image
//
// See http://goo.gl/Y8NNCq for more details.
func (c *Client) LoadImage(opts LoadImageOptions) error {
	return c.stream("POST", "/images/load", true, false, nil, opts.InputStream, nil, nil)
}

// ExportImageOptions represent the options for ExportImage Docker API call
//
// See http://goo.gl/mi6kvk for more details.
type ExportImageOptions struct {
	Name         string
	OutputStream io.Writer
}

// ExportImage exports an image (as a tar file) into the stream
//
// See http://goo.gl/mi6kvk for more details.
func (c *Client) ExportImage(opts ExportImageOptions) error {
	return c.stream("GET", fmt.Sprintf("/images/%s/get", opts.Name), true, false, nil, nil, opts.OutputStream, nil)
}

// ImportImageOptions present the set of informations available for importing
// an image from a source file or the stdin.
//
// See http://goo.gl/PhBKnS for more details.
type ImportImageOptions struct {
	Repository string `qs:"repo"`
	Source     string `qs:"fromSrc"`
	Tag        string `qs:"tag"`

	InputStream  io.Reader `qs:"-"`
	OutputStream io.Writer `qs:"-"`
}

// ImportImage imports an image from a url, a file or stdin
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) ImportImage(opts ImportImageOptions) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	if opts.Source != "-" {
		opts.InputStream = nil
	}
	if opts.Source != "-" && !isURL(opts.Source) {
		f, err := os.Open(opts.Source)
		if err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		opts.InputStream = bytes.NewBuffer(b)
		opts.Source = "-"
	}
	return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, false)
}

// BuildImageOptions present the set of informations available for building an
// image from a tarfile with a Dockerfile in it.
//
// For more details about the Docker building process, see
// http://goo.gl/tlPXPu.
type BuildImageOptions struct {
	Name                string            `qs:"t"`
	NoCache             bool              `qs:"nocache"`
	SuppressOutput      bool              `qs:"q"`
	RmTmpContainer      bool              `qs:"rm"`
	ForceRmTmpContainer bool              `qs:"forcerm"`
	InputStream         io.Reader         `qs:"-"`
	OutputStream        io.Writer         `qs:"-"`
	RawJSONStream       bool              `qs:"-"`
	Remote              string            `qs:"remote"`
	Auth                AuthConfiguration `qs:"-"` // for older docker X-Registry-Auth header
	ContextDir          string            `qs:"-"`
}

// BuildImage builds an image from a tarball's url or a Dockerfile in the input
// stream.
//
// See http://goo.gl/wRsW76 for more details.
func (c *Client) BuildImage(opts BuildImageOptions) error {
	if opts.OutputStream == nil {
		return ErrMissingOutputStream
	}
	var headers = headersWithAuth(&opts.Auth)
	if opts.Remote != "" && opts.Name == "" {
		opts.Name = opts.Remote
	}
	if opts.InputStream != nil || opts.ContextDir != "" {
		headers["Content-Type"] = "application/tar"
	} else if opts.Remote == "" {
		return ErrMissingRepo
	}
	if opts.ContextDir != "" {
		if opts.InputStream != nil {
			return ErrMultipleContexts
		}
		var err error
		if opts.InputStream, err = createTarStream(opts.ContextDir); err != nil {
			return err
		}
	}

	return c.stream("POST", fmt.Sprintf("/build?%s",
		queryString(&opts)), true, opts.RawJSONStream, headers, opts.InputStream, opts.OutputStream, nil)
}

// TagImageOptions present the set of options to tag an image.
//
// See http://goo.gl/5g6qFy for more details.
type TagImageOptions struct {
	Repo  string
	Tag   string
	Force bool
}

// TagImage adds a tag to the image identified by the given name.
//
// See http://goo.gl/5g6qFy for more details.
func (c *Client) TagImage(name string, opts TagImageOptions) error {
	if name == "" {
		return ErrNoSuchImage
	}
	_, status, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
		queryString(&opts)), nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}

	return err
}

func isURL(u string) bool {
	p, err := url.Parse(u)
	if err != nil {
		return false
	}
	return p.Scheme == "http" || p.Scheme == "https"
}

func headersWithAuth(auth *AuthConfiguration) map[string]string {
	var headers = make(map[string]string)
	if auth == nil {
		return headers
	}
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(*auth)

	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
	return headers
}
<commit_msg>Allowing X-Registry-Config header to passed in via the environment<commit_after>// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

// APIImages represent an image returned in the ListImages call.
type APIImages struct {
	ID          string   `json:"Id" yaml:"Id"`
	RepoTags    []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
	Created     int64    `json:"Created,omitempty" yaml:"Created,omitempty"`
	Size        int64    `json:"Size,omitempty" yaml:"Size,omitempty"`
	VirtualSize int64    `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
	ParentId    string   `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
}

type Image struct {
	ID              string    `json:"Id" yaml:"Id"`
	Parent          string    `json:"Parent,omitempty" yaml:"Parent,omitempty"`
	Comment         string    `json:"Comment,omitempty" yaml:"Comment,omitempty"`
	Created         time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
	Container       string    `json:"Container,omitempty" yaml:"Container,omitempty"`
	ContainerConfig Config    `json:"ContainerConfig,omitempty" yaml:"ContainerConfig,omitempty"`
	DockerVersion   string    `json:"DockerVersion,omitempty" yaml:"DockerVersion,omitempty"`
	Author          string    `json:"Author,omitempty" yaml:"Author,omitempty"`
	Config          *Config   `json:"Config,omitempty" yaml:"Config,omitempty"`
	Architecture    string    `json:"Architecture,omitempty" yaml:"Architecture,omitempty"`
	Size            int64     `json:"Size,omitempty" yaml:"Size,omitempty"`
}

// ImageHistory represent a layer in an image's history returned by the
// ImageHistory call.
type ImageHistory struct {
	ID        string   `json:"Id" yaml:"Id"`
	Tags      []string `json:"Tags,omitempty" yaml:"Tags,omitempty"`
	Created   int64    `json:"Created,omitempty" yaml:"Created,omitempty"`
	CreatedBy string   `json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
	Size      int64    `json:"Size,omitempty" yaml:"Size,omitempty"`
}

type ImagePre012 struct {
	ID              string    `json:"id"`
	Parent          string    `json:"parent,omitempty"`
	Comment         string    `json:"comment,omitempty"`
	Created         time.Time `json:"created"`
	Container       string    `json:"container,omitempty"`
	ContainerConfig Config    `json:"container_config,omitempty"`
	DockerVersion   string    `json:"docker_version,omitempty"`
	Author          string    `json:"author,omitempty"`
	Config          *Config   `json:"config,omitempty"`
	Architecture    string    `json:"architecture,omitempty"`
	Size            int64     `json:"size,omitempty"`
}

var (
	// ErrNoSuchImage is the error returned when the image does not exist.
	ErrNoSuchImage = errors.New("no such image")

	// ErrMissingRepo is the error returned when the remote repository is
	// missing.
	ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")

	// ErrMissingOutputStream is the error returned when no output stream
	// is provided to some calls, like BuildImage.
	ErrMissingOutputStream = errors.New("missing output stream")

	// ErrMultipleContexts is the error returned when both a ContextDir and
	// InputStream are provided in BuildImageOptions
	ErrMultipleContexts = errors.New("image build may not be provided BOTH context dir and input stream")
)

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/VmcR6v for more details.
func (c *Client) ListImages(all bool) ([]APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// ImageHistory returns the history of the image by its name or ID.
//
// See http://goo.gl/2oJmNs for more details.
func (c *Client) ImageHistory(name string) ([]ImageHistory, error) {
	body, status, err := c.do("GET", "/images/"+name+"/history", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}
	var history []ImageHistory
	err = json.Unmarshal(body, &history)
	if err != nil {
		return nil, err
	}
	return history, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/znj0wM for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/Q112NY for more details.
func (c *Client) InspectImage(name string) (*Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}

	var image Image

	// if the caller elected to skip checking the server's version, assume it's the latest
	if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
		err = json.Unmarshal(body, &image)
		if err != nil {
			return nil, err
		}
	} else {
		var imagePre012 ImagePre012
		err = json.Unmarshal(body, &imagePre012)
		if err != nil {
			return nil, err
		}

		image.ID = imagePre012.ID
		image.Parent = imagePre012.Parent
		image.Comment = imagePre012.Comment
		image.Created = imagePre012.Created
		image.Container = imagePre012.Container
		image.ContainerConfig = imagePre012.ContainerConfig
		image.DockerVersion = imagePre012.DockerVersion
		image.Author = imagePre012.Author
		image.Config = imagePre012.Config
		image.Architecture = imagePre012.Architecture
		image.Size = imagePre012.Size
	}

	return &image, nil
}

// PushImageOptions represents options to use in the PushImage method.
//
// See http://goo.gl/pN8A3P for more details.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Tag of the image
	Tag string

	// Registry server to push the image
	Registry string

	OutputStream  io.Writer `qs:"-"`
	RawJSONStream bool      `qs:"-"`
}

// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authentication in the Docker index server.
type AuthConfiguration struct {
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	Email    string `json:"email,omitempty"`
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// An empty instance of AuthConfiguration may be used for unauthenticated
// pushes.
//
// See http://goo.gl/pN8A3P for more details.
func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	headers := headersWithAuth(&auth)
	return c.stream("POST", path, true, opts.RawJSONStream, headers, nil, opts.OutputStream, nil)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/ACyYNS for more details.
type PullImageOptions struct {
	Repository    string `qs:"fromImage"`
	Registry      string
	Tag           string
	OutputStream  io.Writer `qs:"-"`
	RawJSONStream bool      `qs:"-"`
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/ACyYNS for more details.
func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}

	headers := headersWithAuth(&auth)
	return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
}

func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool) error {
	path := "/images/create?" + qs
	return c.stream("POST", path, true, rawJSONStream, headers, in, w, nil)
}

// LoadImageOptions represents the options for LoadImage Docker API Call
//
// See http://goo.gl/Y8NNCq for more details.
type LoadImageOptions struct {
	InputStream io.Reader
}

// LoadImage imports a tarball docker image
//
// See http://goo.gl/Y8NNCq for more details.
func (c *Client) LoadImage(opts LoadImageOptions) error {
	return c.stream("POST", "/images/load", true, false, nil, opts.InputStream, nil, nil)
}

// ExportImageOptions represent the options for ExportImage Docker API call
//
// See http://goo.gl/mi6kvk for more details.
type ExportImageOptions struct {
	Name         string
	OutputStream io.Writer
}

// ExportImage exports an image (as a tar file) into the stream
//
// See http://goo.gl/mi6kvk for more details.
func (c *Client) ExportImage(opts ExportImageOptions) error {
	return c.stream("GET", fmt.Sprintf("/images/%s/get", opts.Name), true, false, nil, nil, opts.OutputStream, nil)
}

// ImportImageOptions present the set of informations available for importing
// an image from a source file or the stdin.
//
// See http://goo.gl/PhBKnS for more details.
type ImportImageOptions struct {
	Repository string `qs:"repo"`
	Source     string `qs:"fromSrc"`
	Tag        string `qs:"tag"`

	InputStream  io.Reader `qs:"-"`
	OutputStream io.Writer `qs:"-"`
}

// ImportImage imports an image from a url, a file or stdin
//
// See http://goo.gl/PhBKnS for more details.
func (c *Client) ImportImage(opts ImportImageOptions) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	if opts.Source != "-" {
		opts.InputStream = nil
	}
	if opts.Source != "-" && !isURL(opts.Source) {
		f, err := os.Open(opts.Source)
		if err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		opts.InputStream = bytes.NewBuffer(b)
		opts.Source = "-"
	}
	return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, false)
}

// BuildImageOptions present the set of informations available for building an
// image from a tarfile with a Dockerfile in it.
//
// For more details about the Docker building process, see
// http://goo.gl/tlPXPu.
type BuildImageOptions struct {
	Name                string            `qs:"t"`
	NoCache             bool              `qs:"nocache"`
	SuppressOutput      bool              `qs:"q"`
	RmTmpContainer      bool              `qs:"rm"`
	ForceRmTmpContainer bool              `qs:"forcerm"`
	InputStream         io.Reader         `qs:"-"`
	OutputStream        io.Writer         `qs:"-"`
	RawJSONStream       bool              `qs:"-"`
	Remote              string            `qs:"remote"`
	Auth                AuthConfiguration `qs:"-"` // for older docker X-Registry-Auth header
	ContextDir          string            `qs:"-"`
}

// BuildImage builds an image from a tarball's url or a Dockerfile in the input
// stream.
//
// See http://goo.gl/wRsW76 for more details.
func (c *Client) BuildImage(opts BuildImageOptions) error {
	if opts.OutputStream == nil {
		return ErrMissingOutputStream
	}
	var headers = headersWithAuth(&opts.Auth)
	if opts.Remote != "" && opts.Name == "" {
		opts.Name = opts.Remote
	}
	if opts.InputStream != nil || opts.ContextDir != "" {
		headers["Content-Type"] = "application/tar"
	} else if opts.Remote == "" {
		return ErrMissingRepo
	}
	if opts.ContextDir != "" {
		if opts.InputStream != nil {
			return ErrMultipleContexts
		}
		var err error
		if opts.InputStream, err = createTarStream(opts.ContextDir); err != nil {
			return err
		}
	}

	return c.stream("POST", fmt.Sprintf("/build?%s",
		queryString(&opts)), true, opts.RawJSONStream, headers, opts.InputStream, opts.OutputStream, nil)
}

// TagImageOptions present the set of options to tag an image.
//
// See http://goo.gl/5g6qFy for more details.
type TagImageOptions struct {
	Repo  string
	Tag   string
	Force bool
}

// TagImage adds a tag to the image identified by the given name.
//
// See http://goo.gl/5g6qFy for more details.
func (c *Client) TagImage(name string, opts TagImageOptions) error {
	if name == "" {
		return ErrNoSuchImage
	}
	_, status, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
		queryString(&opts)), nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}

	return err
}

func isURL(u string) bool {
	p, err := url.Parse(u)
	if err != nil {
		return false
	}
	return p.Scheme == "http" || p.Scheme == "https"
}

func headersWithAuth(auth *AuthConfiguration) map[string]string {
	var headers = make(map[string]string)
	if auth == nil {
		return headers
	}
	var buf bytes.Buffer
	json.NewEncoder(&buf).Encode(*auth)
	headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())

	if registryConfig := os.Getenv("DOCKER_X_REGISTRY_CONFIG"); registryConfig != "" {
		headers["X-Registry-Config"] = registryConfig
	}

	return headers
}
<|endoftext|>


<commit_before>// Package gosom implements the self organizing map algorithm.
package gosom

import (
	"encoding/json"
	"fmt"
	"io"
	"math/rand"

	"github.com/256dpi/gosom/functions"
)

// SOM holds an instance of a self organizing map.
type SOM struct {
	Width                int
	Height               int
	Nodes                Lattice
	CoolingFunction      string
	DistanceFunction     string
	NeighborhoodFunction string
}

// NewSOM creates and returns a new self organizing map.
func NewSOM(width, height int) *SOM {
	return &SOM{
		Width:                width,
		Height:               height,
		CoolingFunction:      "linear",
		DistanceFunction:     "euclidean",
		NeighborhoodFunction: "cone",
	}
}

// LoadSOMFromJSON reads data from source and returns a SOM.
func LoadSOMFromJSON(source io.Reader) (*SOM, error) {
	reader := json.NewDecoder(source)
	som := NewSOM(0, 0)

	err := reader.Decode(som)
	if err != nil {
		return nil, err
	}

	return som, nil
}

// InitializeWithZeroes initializes the nodes with zero initialized dimensions.
func (som *SOM) InitializeWithZeroes(dimensions int) {
	som.Nodes = NewLattice(som.Width, som.Height, dimensions)
}

// InitializeWithRandomValues initializes the nodes with random values between
// the calculated minimums and maximums per dimension.
func (som *SOM) InitializeWithRandomValues(data *Matrix) {
	som.Nodes = NewLattice(som.Width, som.Height, data.Columns)

	for _, node := range som.Nodes {
		for i := 0; i < data.Columns; i++ {
			r := (data.Maximums[i] - data.Minimums[i]) + data.Minimums[i]
			node.Weights[i] = r * rand.Float64()
		}
	}
}

// InitializeWithDataPoints initializes the nodes with random data points.
//
// Note: Do not use this function if your data set includes null values. Use
// InitializeWithRandomValues instead.
func (som *SOM) InitializeWithDataPoints(data *Matrix) {
	som.Nodes = NewLattice(som.Width, som.Height, data.Columns)

	for _, node := range som.Nodes {
		copy(node.Weights, data.RandomRow())
	}
}

// Closest returns the closest Node to the input.
func (som *SOM) Closest(input []float64) *Node {
	var nodes []*Node

	// get initial distance
	t := som.D(input, som.Nodes[0].Weights)

	for _, node := range som.Nodes {
		// calculate distance
		d := som.D(input, node.Weights)

		if d < t {
			// save distance, clear array and add winner
			t = d
			nodes = append([]*Node{}, node)
		} else if d == t {
			// add winner
			nodes = append(nodes, node)
		}
	}

	if len(nodes) > 1 {
		// return random winner
		return nodes[rand.Intn(len(nodes))]
	}

	return nodes[0]
}

// Neighbors returns the K nearest neighbors to the input.
func (som *SOM) Neighbors(input []float64, K int) []*Node {
	lat := som.Nodes.Sort(func(n1, n2 *Node) bool {
		d1 := som.D(input, n1.Weights)
		d2 := som.D(input, n2.Weights)

		return d1 < d2
	})

	return lat[:K]
}

// Step applies one step of learning.
func (som *SOM) Step(data *Matrix, step int, training *Training) {
	learningRate := training.LearningRate(step)
	radius := training.Radius(step)
	input := data.RandomRow()
	winningNode := som.Closest(input)

	for _, node := range som.Nodes {
		distance := som.D(winningNode.Position, node.Position)

		if distance < radius*2 {
			influence := som.NI(distance / radius)
			node.Adjust(input, influence*learningRate)
		}
	}
}

// Train trains the SOM from the data.
func (som *SOM) Train(data *Matrix, training *Training) {
	for step := 0; step < training.Steps; step++ {
		som.Step(data, step, training)
	}
}

// Classify returns the classification for input.
func (som *SOM) Classify(input []float64) []float64 {
	o := make([]float64, som.Dimensions())
	copy(o, som.Closest(input).Weights)
	return o
}

// Interpolate interpolates the input using K neighbors.
func (som *SOM) Interpolate(input []float64, K int) []float64 {
	neighbors := som.Neighbors(input, K)
	total := make([]float64, som.Dimensions())

	// add up all values
	for i := 0; i < len(neighbors); i++ {
		for j := 0; j < som.Dimensions(); j++ {
			total[j] += neighbors[i].Weights[j]
		}
	}

	// calculate average
	for i := 0; i < som.Dimensions(); i++ {
		total[i] = total[i] / float64(K)
	}

	return total
}

// WeightedInterpolate interpolates the input using K neighbors by weighting
// the distance to the input.
func (som *SOM) WeightedInterpolate(input []float64, K int) []float64 {
	neighbors := som.Neighbors(input, K)
	neighborWeights := make([]float64, K)
	total := make([]float64, som.Dimensions())
	sumWeights := make([]float64, som.Dimensions())

	// calculate weights for neighbors
	radius := som.D(input, neighbors[K-1].Weights)
	for i, n := range neighbors {
		distance := som.D(input, n.Weights)
		neighborWeights[i] = som.NI(distance / radius)
	}

	// add up all values
	for i := 0; i < len(neighbors); i++ {
		for j := 0; j < som.Dimensions(); j++ {
			total[j] += neighbors[i].Weights[j] * neighborWeights[i]
			sumWeights[j] += neighborWeights[i]
		}
	}

	// calculate average
	for i := 0; i < som.Dimensions(); i++ {
		total[i] = total[i] / sumWeights[i]
	}

	return total
}

// String returns a string matrix of all nodes and weights
func (som *SOM) String() string {
	s := ""

	for i := 0; i < som.Height; i++ {
		for j := 0; j < som.Width; j++ {
			k := i*som.Height + j
			s += fmt.Sprintf("%.2f ", som.Nodes[k].Weights)
		}

		s += "\n"
	}

	return s
}

// Dimensions returns the dimensions of the nodes.
func (som *SOM) Dimensions() int {
	return len(som.Nodes[0].Weights)
}

// WeightMatrix returns a matrix based on the weights of the nodes.
func (som *SOM) WeightMatrix() *Matrix {
	data := make([][]float64, len(som.Nodes))

	for i, node := range som.Nodes {
		data[i] = make([]float64, som.Dimensions())
		copy(data[i], node.Weights)
	}

	return NewMatrix(data)
}

// SaveAsJSON writes the SOM as a JSON file to destination.
func (som *SOM) SaveAsJSON(destination io.Writer) error {
	writer := json.NewEncoder(destination)
	return writer.Encode(som)
}

// CF is a convenience function for calculating cooling factors.
func (som *SOM) CF(progress float64) float64 {
	return functions.CoolingFactor(som.CoolingFunction, progress)
}

// D is a convenience function for calculating distances.
func (som *SOM) D(from, to []float64) float64 {
	return functions.Distance(som.DistanceFunction, from, to)
}

// NI is a convenience function for calculating neighborhood influences.
func (som *SOM) NI(distance float64) float64 {
	return functions.NeighborhoodInfluence(som.NeighborhoodFunction, distance)
}

// N is a convenience function for accessing nodes.
func (som *SOM) N(x, y int) *Node {
	return som.Nodes[y*som.Width+x]
}
<commit_msg>Closest will start with a random node<commit_after>// Package gosom implements the self organizing map algorithm.
package gosom

import (
	"encoding/json"
	"fmt"
	"io"
	"math/rand"

	"github.com/256dpi/gosom/functions"
)

// SOM holds an instance of a self organizing map.
type SOM struct {
	Width                int
	Height               int
	Nodes                Lattice
	CoolingFunction      string
	DistanceFunction     string
	NeighborhoodFunction string
}

// NewSOM creates and returns a new self organizing map.
func NewSOM(width, height int) *SOM {
	return &SOM{
		Width:                width,
		Height:               height,
		CoolingFunction:      "linear",
		DistanceFunction:     "euclidean",
		NeighborhoodFunction: "cone",
	}
}

// LoadSOMFromJSON reads data from source and returns a SOM.
func LoadSOMFromJSON(source io.Reader) (*SOM, error) {
	reader := json.NewDecoder(source)
	som := NewSOM(0, 0)

	err := reader.Decode(som)
	if err != nil {
		return nil, err
	}

	return som, nil
}

// InitializeWithZeroes initializes the nodes with zero initialized dimensions.
func (som *SOM) InitializeWithZeroes(dimensions int) {
	som.Nodes = NewLattice(som.Width, som.Height, dimensions)
}

// InitializeWithRandomValues initializes the nodes with random values between
// the calculated minimums and maximums per dimension.
func (som *SOM) InitializeWithRandomValues(data *Matrix) {
	som.Nodes = NewLattice(som.Width, som.Height, data.Columns)

	for _, node := range som.Nodes {
		for i := 0; i < data.Columns; i++ {
			r := (data.Maximums[i] - data.Minimums[i]) + data.Minimums[i]
			node.Weights[i] = r * rand.Float64()
		}
	}
}

// InitializeWithDataPoints initializes the nodes with random data points.
//
// Note: Do not use this function if your data set includes null values. Use
// InitializeWithRandomValues instead.
func (som *SOM) InitializeWithDataPoints(data *Matrix) {
	som.Nodes = NewLattice(som.Width, som.Height, data.Columns)

	for _, node := range som.Nodes {
		copy(node.Weights, data.RandomRow())
	}
}

// Closest returns the closest Node to the input.
func (som *SOM) Closest(input []float64) *Node {
	var nodes []*Node

	// select random to start with
	node := som.Nodes[rand.Intn(len(som.Nodes))]
	t := som.D(input, node.Weights)
	nodes = append(nodes, node)

	for _, node := range som.Nodes {
		// calculate distance
		d := som.D(input, node.Weights)

		if d < t {
			// save distance, clear array and add winner
			t = d
			nodes = append([]*Node{}, node)
		} else if d == t {
			// add winner
			nodes = append(nodes, node)
		}
	}

	if len(nodes) > 1 {
		// return random winner
		return nodes[rand.Intn(len(nodes))]
	}

	return nodes[0]
}

// Neighbors returns the K nearest neighbors to the input.
func (som *SOM) Neighbors(input []float64, K int) []*Node {
	lat := som.Nodes.Sort(func(n1, n2 *Node) bool {
		d1 := som.D(input, n1.Weights)
		d2 := som.D(input, n2.Weights)

		return d1 < d2
	})

	return lat[:K]
}

// Step applies one step of learning.
func (som *SOM) Step(data *Matrix, step int, training *Training) {
	learningRate := training.LearningRate(step)
	radius := training.Radius(step)
	input := data.RandomRow()
	winningNode := som.Closest(input)

	for _, node := range som.Nodes {
		distance := som.D(winningNode.Position, node.Position)

		if distance < radius*2 {
			influence := som.NI(distance / radius)
			node.Adjust(input, influence*learningRate)
		}
	}
}

// Train trains the SOM from the data.
func (som *SOM) Train(data *Matrix, training *Training) {
	for step := 0; step < training.Steps; step++ {
		som.Step(data, step, training)
	}
}

// Classify returns the classification for input.
func (som *SOM) Classify(input []float64) []float64 {
	o := make([]float64, som.Dimensions())
	copy(o, som.Closest(input).Weights)
	return o
}

// Interpolate interpolates the input using K neighbors.
func (som *SOM) Interpolate(input []float64, K int) []float64 {
	neighbors := som.Neighbors(input, K)
	total := make([]float64, som.Dimensions())

	// add up all values
	for i := 0; i < len(neighbors); i++ {
		for j := 0; j < som.Dimensions(); j++ {
			total[j] += neighbors[i].Weights[j]
		}
	}

	// calculate average
	for i := 0; i < som.Dimensions(); i++ {
		total[i] = total[i] / float64(K)
	}

	return total
}

// WeightedInterpolate interpolates the input using K neighbors by weighting
// the distance to the input.
func (som *SOM) WeightedInterpolate(input []float64, K int) []float64 {
	neighbors := som.Neighbors(input, K)
	neighborWeights := make([]float64, K)
	total := make([]float64, som.Dimensions())
	sumWeights := make([]float64, som.Dimensions())

	// calculate weights for neighbors
	radius := som.D(input, neighbors[K-1].Weights)
	for i, n := range neighbors {
		distance := som.D(input, n.Weights)
		neighborWeights[i] = som.NI(distance / radius)
	}

	// add up all values
	for i := 0; i < len(neighbors); i++ {
		for j := 0; j < som.Dimensions(); j++ {
			total[j] += neighbors[i].Weights[j] * neighborWeights[i]
			sumWeights[j] += neighborWeights[i]
		}
	}

	// calculate average
	for i := 0; i < som.Dimensions(); i++ {
		total[i] = total[i] / sumWeights[i]
	}

	return total
}

// String returns a string matrix of all nodes and weights
func (som *SOM) String() string {
	s := ""

	for i := 0; i < som.Height; i++ {
		for j := 0; j < som.Width; j++ {
			k := i*som.Height + j
			s += fmt.Sprintf("%.2f ", som.Nodes[k].Weights)
		}

		s += "\n"
	}

	return s
}

// Dimensions returns the dimensions of the nodes.
func (som *SOM) Dimensions() int {
	return len(som.Nodes[0].Weights)
}

// WeightMatrix returns a matrix based on the weights of the nodes.
func (som *SOM) WeightMatrix() *Matrix {
	data := make([][]float64, len(som.Nodes))

	for i, node := range som.Nodes {
		data[i] = make([]float64, som.Dimensions())
		copy(data[i], node.Weights)
	}

	return NewMatrix(data)
}

// SaveAsJSON writes the SOM as a JSON file to destination.
func (som *SOM) SaveAsJSON(destination io.Writer) error {
	writer := json.NewEncoder(destination)
	return writer.Encode(som)
}

// CF is a convenience function for calculating cooling factors.
func (som *SOM) CF(progress float64) float64 {
	return functions.CoolingFactor(som.CoolingFunction, progress)
}

// D is a convenience function for calculating distances.
func (som *SOM) D(from, to []float64) float64 {
	return functions.Distance(som.DistanceFunction, from, to)
}

// NI is a convenience function for calculating neighborhood influences.
func (som *SOM) NI(distance float64) float64 {
	return functions.NeighborhoodInfluence(som.NeighborhoodFunction, distance)
}

// N is a convenience function for accessing nodes.
func (som *SOM) N(x, y int) *Node {
	return som.Nodes[y*som.Width+x]
}
<|endoftext|>