<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// +build integration

package resources

import (
	"crypto/x509"

	xgrpc "github.com/m3db/m3em/x/grpc"

	"google.golang.org/grpc/credentials"
)

const (
	caCrtResource      = "CertAuth.crt"
	clientCrtResources = "m3em_client.uberinternal.com.crt"
	clientKeyResources = "m3em_client.uberinternal.com.key"
	serverName         = "m3em_server.uberinternal.com"
	serverCrtResources = "m3em_server.uberinternal.com.crt"
	serverKeyResources = "m3em_server.uberinternal.com.key"
)

// ClientTransportCredentials return a DialOption for TLS Client communication
func ClientTransportCredentials() (credentials.TransportCredentials, error) {
	caCrt, err := Asset(caCrtResource)
	if err != nil {
		return nil, err
	}

	clientCrt, err := Asset(clientCrtResources)
	if err != nil {
		return nil, err
	}

	clientKey, err := Asset(clientKeyResources)
	if err != nil {
		return nil, err
	}

	return xgrpc.NewClientCredentials(serverName, caCrt, clientCrt, clientKey)
}

// ServerTransportCredentials return a DialOption for TLS Server communication
func ServerTransportCredentials() (credentials.TransportCredentials, error) {
	caCrt, err := Asset(caCrtResource)
	if err != nil {
		return nil, err
	}

	serverCrt, err := Asset(serverCrtResources)
	if err != nil {
		return nil, err
	}

	serverKey, err := Asset(serverKeyResources)
	if err != nil {
		return nil, err
	}

	return xgrpc.NewServerCredentials(caCrt, serverCrt, serverKey)
}
<commit_msg>[cert] Remove unnecessary import from cert.go<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// +build integration

package resources

import (
	xgrpc "github.com/m3db/m3em/x/grpc"

	"google.golang.org/grpc/credentials"
)

const (
	caCrtResource      = "CertAuth.crt"
	clientCrtResources = "m3em_client.uberinternal.com.crt"
	clientKeyResources = "m3em_client.uberinternal.com.key"
	serverName         = "m3em_server.uberinternal.com"
	serverCrtResources = "m3em_server.uberinternal.com.crt"
	serverKeyResources = "m3em_server.uberinternal.com.key"
)

// ClientTransportCredentials return a DialOption for TLS Client communication
func ClientTransportCredentials() (credentials.TransportCredentials, error) {
	caCrt, err := Asset(caCrtResource)
	if err != nil {
		return nil, err
	}

	clientCrt, err := Asset(clientCrtResources)
	if err != nil {
		return nil, err
	}

	clientKey, err := Asset(clientKeyResources)
	if err != nil {
		return nil, err
	}

	return xgrpc.NewClientCredentials(serverName, caCrt, clientCrt, clientKey)
}

// ServerTransportCredentials return a DialOption for TLS Server communication
func ServerTransportCredentials() (credentials.TransportCredentials, error) {
	caCrt, err := Asset(caCrtResource)
	if err != nil {
		return nil, err
	}

	serverCrt, err := Asset(serverCrtResources)
	if err != nil {
		return nil, err
	}

	serverKey, err := Asset(serverKeyResources)
	if err != nil {
		return nil, err
	}

	return xgrpc.NewServerCredentials(caCrt, serverCrt, serverKey)
}
<|endoftext|>


<commit_before>package controllers

import (
	"fmt"
	"net/http"
)

type MainController struct {
}

func (mc *MainController) GetHandler(responseWriter http.ResponseWriter, request *http.Request, parameters map[string]string) {
	responseWriter.Header().Add("Content-Type", "application/json")
	fmt.Fprintf(responseWriter, `{"status":200, "message": "You reached the server"}`)
}
func (mc *MainController) GetVersionHandler(responseWriter http.ResponseWriter, request *http.Request, parameters map[string]string) {
	responseWriter.Header().Add("Content-Type", "application/json")
	fmt.Fprintf(responseWriter, `{"status":200, "version": "0.1.0.0"}`)
}

func NewMainController() MainController {
	return MainController{}
}
<commit_msg>Version Change<commit_after>package controllers

import (
	"fmt"
	"net/http"
)

type MainController struct {
}

func (mc *MainController) GetHandler(responseWriter http.ResponseWriter, request *http.Request, parameters map[string]string) {
	responseWriter.Header().Add("Content-Type", "application/json")
	fmt.Fprintf(responseWriter, `{"status":200, "message": "You reached the server"}`)
}
func (mc *MainController) GetVersionHandler(responseWriter http.ResponseWriter, request *http.Request, parameters map[string]string) {
	responseWriter.Header().Add("Content-Type", "application/json")
	fmt.Fprintf(responseWriter, `{"status":200, "version": "0.1.0.1"}`)
}

func NewMainController() MainController {
	return MainController{}
}
<|endoftext|>


<commit_before>/* Copyright 2017 Google Inc.
 * https://github.com/NeilFraser/CodeCity
 *
 * 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 interpreter

import (
	"CodeCity/server/interpreter/data"
)

func (intrp *Interpreter) initBuiltinObject() {
	intrp.mkBuiltin("Object", data.NewObject(nil, intrp.protos.ObjectProto))
	intrp.mkBuiltin("Object.prototype", intrp.protos.ObjectProto)

	intrp.mkBuiltinFunc("Object.prototype.toString", 0,
		func(intrp *Interpreter, this data.Value, args []data.Value) (ret data.Value, throw bool) {
			if this == nil {
				panic("Object.property.toString called with this == nil??")
			}
			return this.ToString(), false
		})

	intrp.mkBuiltinFunc("Object.defineProperty", 3,
		func(intrp *Interpreter, this data.Value, args []data.Value) (ret data.Value, throw bool) {
			// Need at least three arguments:
			for len(args) < 3 {
				args = append(args, data.Undefined{})
			}
			obj, ok := args[0].(data.Object)
			if !ok {
				return intrp.typeError("Object.defineProperty: first argument not an object"), true
			}
			key := string(args[1].ToString())
			desc, ok := args[2].(data.Object)
			if !ok {
				return intrp.typeError("Property description must be an object"), true
			}
			var pd data.Property
			var ne *data.NativeError
			pd.Value, ne = desc.Get("value")
			if ne != nil {
				return intrp.nativeError(ne), true
			}
			// FIXME: set owner
			pd.Owner = nil
			attrs := []struct {
				flag *bool
				key  string
			}{
				{&pd.W, "writeable"},
				{&pd.E, "enumerable"},
				{&pd.C, "configurable"},
				{&pd.R, "readable"},
				{&pd.I, "inheritable"},
			}
			for _, attr := range attrs {
				v, ne := desc.Get(attr.key)
				if ne != nil {
					return intrp.nativeError(ne), true
				}
				*(attr.flag) = bool(v.ToBoolean())
			}
			ne = obj.DefineOwnProperty(key, pd)
			if ne != nil {
				return intrp.nativeError(ne), true
			}
			return obj, false
		})

	intrp.mkBuiltinFunc("Object.getPrototypeOf", 1,
		func(intrp *Interpreter, this data.Value, args []data.Value) (ret data.Value, throw bool) {
			// Need at least one argument:
			for len(args) < 1 {
				args = append(args, data.Undefined{})
			}
			obj, ok := args[0].(data.Object)
			if !ok {
				return intrp.typeError("Object.getPrototypeOf: first argument not an object"), true
			}
			proto := obj.Proto()
			if proto == nil {
				return data.Null{}, false
			}
			return proto, false
		})
}
<commit_msg>Sort builtin properties to match order in ES5.1 spec<commit_after>/* Copyright 2017 Google Inc.
 * https://github.com/NeilFraser/CodeCity
 *
 * 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 interpreter

import (
	"CodeCity/server/interpreter/data"
)

func (intrp *Interpreter) initBuiltinObject() {
	intrp.mkBuiltin("Object", data.NewObject(nil, intrp.protos.ObjectProto))

	intrp.mkBuiltin("Object.prototype", intrp.protos.ObjectProto)

	intrp.mkBuiltinFunc("Object.getPrototypeOf", 1,
		func(intrp *Interpreter, this data.Value, args []data.Value) (ret data.Value, throw bool) {
			// Need at least one argument:
			for len(args) < 1 {
				args = append(args, data.Undefined{})
			}
			obj, ok := args[0].(data.Object)
			if !ok {
				return intrp.typeError("Object prototype may only be an Object or null"), true
			}
			proto := obj.Proto()
			if proto == nil {
				return data.Null{}, false
			}
			return proto, false
		})

	// Object.getOwnPropertyDescriptor
	// Object.getOwnPropertyNames
	// Object.create

	intrp.mkBuiltinFunc("Object.defineProperty", 3,
		func(intrp *Interpreter, this data.Value, args []data.Value) (ret data.Value, throw bool) {
			// Need at least three arguments:
			for len(args) < 3 {
				args = append(args, data.Undefined{})
			}
			obj, ok := args[0].(data.Object)
			if !ok {
				return intrp.typeError("Object.defineProperty: first argument not an object"), true
			}
			key := string(args[1].ToString())
			desc, ok := args[2].(data.Object)
			if !ok {
				return intrp.typeError("Property description must be an object"), true
			}
			var pd data.Property
			var ne *data.NativeError
			pd.Value, ne = desc.Get("value")
			if ne != nil {
				return intrp.nativeError(ne), true
			}
			// FIXME: set owner
			pd.Owner = nil
			attrs := []struct {
				flag *bool
				key  string
			}{
				{&pd.W, "writeable"},
				{&pd.E, "enumerable"},
				{&pd.C, "configurable"},
				{&pd.R, "readable"},
				{&pd.I, "inheritable"},
			}
			for _, attr := range attrs {
				v, ne := desc.Get(attr.key)
				if ne != nil {
					return intrp.nativeError(ne), true
				}
				*(attr.flag) = bool(v.ToBoolean())
			}
			ne = obj.DefineOwnProperty(key, pd)
			if ne != nil {
				return intrp.nativeError(ne), true
			}
			return obj, false
		})

	// Object.defineProperties
	// Object.seal
	// Object.freeze
	// Object.preventExtensions
	// Object.isSealed
	// Object.isFrozen
	// Object.isExtensible
	// Object.keys

	/****************************************************************/

	intrp.mkBuiltinFunc("Object.prototype.toString", 0,
		func(intrp *Interpreter, this data.Value, args []data.Value) (ret data.Value, throw bool) {
			if this == nil {
				panic("Object.property.toString called with this == nil??")
			}
			return this.ToString(), false
		})
}
<|endoftext|>


<commit_before>package keyshareserver

import (
	"github.com/privacybydesign/irmago/internal/keysharecore"

	"github.com/go-errors/errors"
)

var (
	ErrUserAlreadyExists = errors.New("Cannot create user, username already taken")
	ErrUserNotFound      = errors.New("Could not find specified user")
	ErrInvalidRecord     = errors.New("Invalid record in database")
)

type LogEntryType string

const (
	PinCheckRefused LogEntryType = "PIN_CHECK_REFUSED"
	PinCheckSuccess LogEntryType = "PIN_CHECK_SUCCESS"
	PinCheckFailed  LogEntryType = "PIN_CHECK_FAILED"
	PinCheckBlocked LogEntryType = "PIN_CHECK_BLOCKED"
	IrmaSession     LogEntryType = "IRMA_SESSION"
)

// Interface used by server to manage data storage
// there are multiple implementations of this, currently:
//  - memorydb (memorydb.go) storing all data in memory (forgets everything after reboot)
//  - postgresdb (postgresdb.go) storing all data in a postgres database
type KeyshareDB interface {
	// User management
	NewUser(user *KeyshareUser) error
	User(username string) (*KeyshareUser, error)
	UpdateUser(user *KeyshareUser) error

	// Pin checking logic
	// Reserve returns (allow, tries, wait, error)
	// where allow is whether we can do the actual pin check
	// tries is how many tries are remaining after doing so
	// wait is how long to wait if tries is 0 or allow false
	ReservePincheck(user *KeyshareUser) (bool, int, int64, error)
	ClearPincheck(user *KeyshareUser) error

	// User activity registration
	// SetSeen calls are used to track when a users account was last active, for deleting old accounts
	SetSeen(user *KeyshareUser) error
	AddLog(user *KeyshareUser, eventType LogEntryType, param interface{}) error

	// Store email verification tokens on registration
	AddEmailVerification(user *KeyshareUser, emailAddress, token string) error
}

// Actual data on a user used by this server.
type KeyshareUser struct {
	Username string
	Language string
	Coredata keysharecore.EncryptedKeysharePacket
	id       int64
}
<commit_msg>docs: improve keyshare db interface method documentation<commit_after>package keyshareserver

import (
	"github.com/privacybydesign/irmago/internal/keysharecore"

	"github.com/go-errors/errors"
)

var (
	ErrUserAlreadyExists = errors.New("Cannot create user, username already taken")
	ErrUserNotFound      = errors.New("Could not find specified user")
	ErrInvalidRecord     = errors.New("Invalid record in database")
)

type LogEntryType string

const (
	PinCheckRefused LogEntryType = "PIN_CHECK_REFUSED"
	PinCheckSuccess LogEntryType = "PIN_CHECK_SUCCESS"
	PinCheckFailed  LogEntryType = "PIN_CHECK_FAILED"
	PinCheckBlocked LogEntryType = "PIN_CHECK_BLOCKED"
	IrmaSession     LogEntryType = "IRMA_SESSION"
)

// Interface used by server to manage data storage
// there are multiple implementations of this, currently:
//  - memorydb (memorydb.go) storing all data in memory (forgets everything after reboot)
//  - postgresdb (postgresdb.go) storing all data in a postgres database
type KeyshareDB interface {
	// User management
	NewUser(user *KeyshareUser) error
	User(username string) (*KeyshareUser, error)
	UpdateUser(user *KeyshareUser) error

	// ReservePincheck reserves a pin check attempt. Return parameters:
	//  - allowed is whether the user is allowed to do the pin check (false if user is blocked)
	//  - tries is how many tries are remaining, after this pin check
	//  - wait is how long the user must wait before the next attempt is allowed if tries is 0
	// ReservePincheck increases the user's try count and (if applicable) the date when the user
	// is unblocked again in the database, regardless of if the pin check succeeds after this
	// invocation.
	ReservePincheck(user *KeyshareUser) (allowed bool, tries int, wait int64, err error)

	// ClearPincheck resets the user's pin count and unblock date fields in the database to their
	// default values (0 past attempts, no unblock date).
	ClearPincheck(user *KeyshareUser) error

	// User activity registration
	// SetSeen calls are used to track when a users account was last active, for deleting old accounts
	SetSeen(user *KeyshareUser) error
	AddLog(user *KeyshareUser, eventType LogEntryType, param interface{}) error

	// Store email verification tokens on registration
	AddEmailVerification(user *KeyshareUser, emailAddress, token string) error
}

// Actual data on a user used by this server.
type KeyshareUser struct {
	Username string
	Language string
	Coredata keysharecore.EncryptedKeysharePacket
	id       int64
}
<|endoftext|>


<commit_before>package ams

import (
	"context"
	"net/http"
	"path"

	"github.com/pkg/errors"
)

const (
	assetsEndpoint = "Assets"
)

const (
	OptionStorageEncrypted = 1 << iota
	OptionCommonEncryptionProtected
	OptionEnvelopeEncryptionProtected
	OptionNone = 0
)

const (
	StateInitialized = iota
	StatePublished   // The 'Publish' action has been deprecated. Remove the code that checks whether an asset is in the 'Published' state.
	StateDeleted
)

const (
	FormatOptionNoFormat          = 0
	FormatOptionAdaptiveStreaming = 1
)

type Asset struct {
	ID                 string `json:"Id"`
	State              int    `json:"State"`
	Created            string `json:"Created"`
	LastModified       string `json:"LastModified"`
	Name               string `json:"Name"`
	Options            int    `json:"Options"`
	FormatOption       int    `json:"FormatOption"`
	URI                string `json:"Uri"`
	StorageAccountName string `json:"StorageAccountName"`
}

func (c *Client) GetAsset(ctx context.Context, assetID string) (*Asset, error) {
	c.logger.Printf("[INFO] get asset #%s ...", assetID)

	endpoint := toAssetResource(assetID)
	var out Asset
	if err := c.get(ctx, endpoint, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed")
	return &out, nil
}

func (c *Client) GetAssets(ctx context.Context) ([]Asset, error) {
	c.logger.Printf("[INFO] get assets ...")

	var out struct {
		Assets []Asset `json:"value"`
	}
	if err := c.get(ctx, assetsEndpoint, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed")
	return out.Assets, nil
}

func (c *Client) CreateAsset(ctx context.Context, name string) (*Asset, error) {
	c.logger.Printf("[INFO] create asset [name=%#v] ...", name)

	params := map[string]interface{}{
		"Name": name,
	}
	var out Asset
	if err := c.post(ctx, assetsEndpoint, params, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed, new asset[#%s]", out.ID)
	return &out, nil
}

func (c *Client) GetAssetFiles(ctx context.Context, assetID string) ([]AssetFile, error) {
	c.logger.Printf("[INFO] get asset[#%s] files ...", assetID)

	endpoint := path.Join(toAssetResource(assetID), filesEndpoint)
	var out struct {
		AssetFiles []AssetFile `json:"value"`
	}
	if err := c.get(ctx, endpoint, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed")
	return out.AssetFiles, nil
}

func (c *Client) DeleteAsset(ctx context.Context, assetID string) error {
	endpoint := toAssetResource(assetID)
	req, err := c.newRequest(ctx, http.MethodDelete, endpoint)
	if err != nil {
		return errors.Wrap(err, "request build failed")
	}

	c.logger.Printf("[INFO] delete asset[#%s] ...")
	if err := c.do(req, http.StatusNoContent, nil); err != nil {
		return errors.Wrap(err, "request failed")
	}
	c.logger.Printf("[INFO] completed")
	return nil
}

func toAssetResource(assetID string) string {
	return toResource(assetsEndpoint, assetID)
}

func (c *Client) buildAssetURI(assetID string) string {
	return c.buildURI(toAssetResource(assetID))
}
<commit_msg>chore: change error message<commit_after>package ams

import (
	"context"
	"net/http"
	"path"

	"github.com/pkg/errors"
)

const (
	assetsEndpoint = "Assets"
)

const (
	OptionStorageEncrypted = 1 << iota
	OptionCommonEncryptionProtected
	OptionEnvelopeEncryptionProtected
	OptionNone = 0
)

const (
	StateInitialized = iota
	StatePublished   // The 'Publish' action has been deprecated. Remove the code that checks whether an asset is in the 'Published' state.
	StateDeleted
)

const (
	FormatOptionNoFormat          = 0
	FormatOptionAdaptiveStreaming = 1
)

type Asset struct {
	ID                 string `json:"Id"`
	State              int    `json:"State"`
	Created            string `json:"Created"`
	LastModified       string `json:"LastModified"`
	Name               string `json:"Name"`
	Options            int    `json:"Options"`
	FormatOption       int    `json:"FormatOption"`
	URI                string `json:"Uri"`
	StorageAccountName string `json:"StorageAccountName"`
}

func (c *Client) GetAsset(ctx context.Context, assetID string) (*Asset, error) {
	c.logger.Printf("[INFO] get asset #%s ...", assetID)

	endpoint := toAssetResource(assetID)
	var out Asset
	if err := c.get(ctx, endpoint, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed")
	return &out, nil
}

func (c *Client) GetAssets(ctx context.Context) ([]Asset, error) {
	c.logger.Printf("[INFO] get assets ...")

	var out struct {
		Assets []Asset `json:"value"`
	}
	if err := c.get(ctx, assetsEndpoint, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed")
	return out.Assets, nil
}

func (c *Client) CreateAsset(ctx context.Context, name string) (*Asset, error) {
	c.logger.Printf("[INFO] create asset [name=%#v] ...", name)

	params := map[string]interface{}{
		"Name": name,
	}
	var out Asset
	if err := c.post(ctx, assetsEndpoint, params, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed, new asset[#%s]", out.ID)
	return &out, nil
}

func (c *Client) GetAssetFiles(ctx context.Context, assetID string) ([]AssetFile, error) {
	c.logger.Printf("[INFO] get asset[#%s] files ...", assetID)

	endpoint := path.Join(toAssetResource(assetID), filesEndpoint)
	var out struct {
		AssetFiles []AssetFile `json:"value"`
	}
	if err := c.get(ctx, endpoint, &out); err != nil {
		return nil, err
	}

	c.logger.Printf("[INFO] completed")
	return out.AssetFiles, nil
}

func (c *Client) DeleteAsset(ctx context.Context, assetID string) error {
	endpoint := toAssetResource(assetID)
	req, err := c.newRequest(ctx, http.MethodDelete, endpoint)
	if err != nil {
		return errors.Wrap(err, "failed to construct request")
	}

	c.logger.Printf("[INFO] delete asset[#%s] ...")
	if err := c.do(req, http.StatusNoContent, nil); err != nil {
		return errors.Wrap(err, "request failed")
	}
	c.logger.Printf("[INFO] completed")
	return nil
}

func toAssetResource(assetID string) string {
	return toResource(assetsEndpoint, assetID)
}

func (c *Client) buildAssetURI(assetID string) string {
	return c.buildURI(toAssetResource(assetID))
}
<|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
 *
 *   https://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 matrix

import (
	"math"
	"testing"

	"github.com/google/go-cmp/cmp"
)

func TestNew(t *testing.T) {
	var tests = []struct {
		name               string
		rows, cols         int
		wantRows, wantCols int
	}{
		{
			name:     "Zero matrix",
			rows:     0,
			cols:     0,
			wantRows: 0,
			wantCols: 0,
		},
		{
			name:     "2x2 matrix",
			rows:     2,
			cols:     2,
			wantRows: 2,
			wantCols: 2,
		},
		{
			name:     "8x3 matrix",
			rows:     8,
			cols:     3,
			wantRows: 8,
			wantCols: 3,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m := New(tt.rows, tt.cols)
			if len(m) != tt.wantRows {
				t.Errorf("got %v rows, wanted %v rows", len(m), tt.wantRows)
			}
			if len(m) != 0 && len(m[0]) != tt.wantCols {
				t.Errorf("got %v columns, wanted %v columns", len(m[0]), tt.wantRows)
			}
		})
	}
}

func TestAdd(t *testing.T) {
	var tests = []struct {
		name     string
		matrices []Matrix
		want     Matrix
		wantErr  bool
	}{
		{
			name: "Zero matrices should sum to zero",
			matrices: []Matrix{
				Matrix{{0, 0}, {0, 0}},
				Matrix{{0, 0}, {0, 0}},
			},
			want:    Matrix{{0, 0}, {0, 0}},
			wantErr: false,
		},
		{
			name: "One matrix should sum to itself",
			matrices: []Matrix{
				Matrix{{2, 3}, {4, 5}},
			},
			want:    Matrix{{2, 3}, {4, 5}},
			wantErr: false,
		},
		{
			name: "2x2 matrices should sum properly",
			matrices: []Matrix{
				Matrix{{2, 6}, {1, 9}},
				Matrix{{4, 7}, {0, 3}},
			},
			want:    Matrix{{6, 13}, {1, 12}},
			wantErr: false,
		},
		{
			name: "Matrices with different numbers of columns should error",
			matrices: []Matrix{
				Matrix{{2, 6}, {1, 9}},
				Matrix{{4, 7, 5}, {0, 3, 0}},
			},
			wantErr: true,
		},
		{
			name: "Matrices with different numbers of rows should error",
			matrices: []Matrix{
				Matrix{{2, 6}, {1, 9}},
				Matrix{{4, 7}, {0, 3}, {1, 1}},
			},
			wantErr: true,
		},
		{
			name: "Matrices with float values should add properly",
			matrices: []Matrix{
				Matrix{{4.69, 8.74, -7.46}, {1.73, -4.76, -6.73}, {-5.27, 5.30, -4.43}},
				Matrix{{-1.39, -3.28, -9.67}, {-2.16, -8.18, -9.16}, {2.44, -5.99, -1.13}},
				Matrix{{-3.2, -0.4, -1.82}, {-1.12, 5.4, 5.14}, {.3, 3.67, -1.66}},
			},
			want:    Matrix{{.1, 5.06, -18.95}, {-1.55, -7.54, -10.75}, {-2.53, 2.98, -7.22}},
			wantErr: false,
		},
	}
	tolerance := .00001
	opt := cmp.Comparer(func(x, y float64) bool {
		diff := math.Abs(x - y)
		mean := math.Abs(x+y) / 2.0
		if math.IsNaN(diff / mean) {
			return true
		}
		return diff/mean < tolerance
	})

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m, err := Add(tt.matrices...)

			if err != nil && !tt.wantErr {
				t.Fatalf("got error %v, wanted no error", err)
			}

			if !cmp.Equal(m, tt.want, opt) {
				t.Fatalf("got %v, wanted %v", m, tt.want)
			}
		})
	}
}
<commit_msg>s/sum/add<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
 *
 *   https://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 matrix

import (
	"math"
	"testing"

	"github.com/google/go-cmp/cmp"
)

func TestNew(t *testing.T) {
	var tests = []struct {
		name               string
		rows, cols         int
		wantRows, wantCols int
	}{
		{
			name:     "Zero matrix",
			rows:     0,
			cols:     0,
			wantRows: 0,
			wantCols: 0,
		},
		{
			name:     "2x2 matrix",
			rows:     2,
			cols:     2,
			wantRows: 2,
			wantCols: 2,
		},
		{
			name:     "8x3 matrix",
			rows:     8,
			cols:     3,
			wantRows: 8,
			wantCols: 3,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m := New(tt.rows, tt.cols)
			if len(m) != tt.wantRows {
				t.Errorf("got %v rows, wanted %v rows", len(m), tt.wantRows)
			}
			if len(m) != 0 && len(m[0]) != tt.wantCols {
				t.Errorf("got %v columns, wanted %v columns", len(m[0]), tt.wantRows)
			}
		})
	}
}

func TestAdd(t *testing.T) {
	var tests = []struct {
		name     string
		matrices []Matrix
		want     Matrix
		wantErr  bool
	}{
		{
			name: "Zero matrices should add to zero",
			matrices: []Matrix{
				Matrix{{0, 0}, {0, 0}},
				Matrix{{0, 0}, {0, 0}},
			},
			want:    Matrix{{0, 0}, {0, 0}},
			wantErr: false,
		},
		{
			name: "One matrix should add to itself",
			matrices: []Matrix{
				Matrix{{2, 3}, {4, 5}},
			},
			want:    Matrix{{2, 3}, {4, 5}},
			wantErr: false,
		},
		{
			name: "2x2 matrices should add properly",
			matrices: []Matrix{
				Matrix{{2, 6}, {1, 9}},
				Matrix{{4, 7}, {0, 3}},
			},
			want:    Matrix{{6, 13}, {1, 12}},
			wantErr: false,
		},
		{
			name: "Matrices with different numbers of columns should error",
			matrices: []Matrix{
				Matrix{{2, 6}, {1, 9}},
				Matrix{{4, 7, 5}, {0, 3, 0}},
			},
			wantErr: true,
		},
		{
			name: "Matrices with different numbers of rows should error",
			matrices: []Matrix{
				Matrix{{2, 6}, {1, 9}},
				Matrix{{4, 7}, {0, 3}, {1, 1}},
			},
			wantErr: true,
		},
		{
			name: "Matrices with float values should add properly",
			matrices: []Matrix{
				Matrix{{4.69, 8.74, -7.46}, {1.73, -4.76, -6.73}, {-5.27, 5.30, -4.43}},
				Matrix{{-1.39, -3.28, -9.67}, {-2.16, -8.18, -9.16}, {2.44, -5.99, -1.13}},
				Matrix{{-3.2, -0.4, -1.82}, {-1.12, 5.4, 5.14}, {.3, 3.67, -1.66}},
			},
			want:    Matrix{{.1, 5.06, -18.95}, {-1.55, -7.54, -10.75}, {-2.53, 2.98, -7.22}},
			wantErr: false,
		},
	}
	tolerance := .00001
	opt := cmp.Comparer(func(x, y float64) bool {
		diff := math.Abs(x - y)
		mean := math.Abs(x+y) / 2.0
		if math.IsNaN(diff / mean) {
			return true
		}
		return diff/mean < tolerance
	})

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m, err := Add(tt.matrices...)

			if err != nil && !tt.wantErr {
				t.Fatalf("got error %v, wanted no error", err)
			}

			if !cmp.Equal(m, tt.want, opt) {
				t.Fatalf("got %v, wanted %v", m, tt.want)
			}
		})
	}
}
<|endoftext|>


<commit_before>/*
                       WARNING WARNING WARNING

                Attention all potential contributors

   This testfile is not in the best state. We've been slowly transitioning
   from the built in "testing" package to using Ginkgo. As you can see, we've
   changed the format, but a lot of the setup, test body, descriptions, etc
   are either hardcoded, completely lacking, or misleading.

   For example:

   Describe("Testing with ginkgo"...)      // This is not a great description
   It("TestDoesSoemthing"...)              // This is a horrible description

   Describe("create-user command"...       // Describe the actual object under test
   It("creates a user when provided ..."   // this is more descriptive

   For good examples of writing Ginkgo tests for the cli, refer to

   src/cf/commands/application/delete_app_test.go
   src/cf/terminal/ui_test.go
   src/github.com/cloudfoundry/loggregator_consumer/consumer_test.go
*/

package trace_test

import (
	"bytes"
	"cf/trace"
	"github.com/cloudfoundry/gofileutils/fileutils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"os"
	"runtime"
)

var _ = Describe("Testing with ginkgo", func() {
	It("TestTraceSetToFalse", func() {
		stdOut := bytes.NewBuffer([]byte{})
		trace.SetStdout(stdOut)

		os.Setenv(trace.CF_TRACE, "false")

		logger := trace.NewLogger()
		logger.Print("hello world")

		result, _ := ioutil.ReadAll(stdOut)
		Expect(string(result)).To(Equal(""))
	})

	It("TestTraceSetToTrue", func() {
		stdOut := bytes.NewBuffer([]byte{})
		trace.SetStdout(stdOut)

		os.Setenv(trace.CF_TRACE, "true")

		logger := trace.NewLogger()
		logger.Print("hello world")

		result, _ := ioutil.ReadAll(stdOut)
		Expect(string(result)).To(ContainSubstring("hello world"))
	})

	It("TestTraceSetToFile", func() {
		stdOut := bytes.NewBuffer([]byte{})
		trace.SetStdout(stdOut)

		fileutils.TempFile("trace_test", func(file *os.File, err error) {
			Expect(err).NotTo(HaveOccurred())
			file.Write([]byte("pre-existing content"))

			os.Setenv(trace.CF_TRACE, file.Name())

			logger := trace.NewLogger()
			logger.Print("hello world")

			file.Seek(0, os.SEEK_SET)
			result, err := ioutil.ReadAll(file)
			Expect(err).NotTo(HaveOccurred())

			byteString := string(result)
			Expect(byteString).To(ContainSubstring("pre-existing content"))
			Expect(byteString).To(ContainSubstring("hello world"))

			result, _ = ioutil.ReadAll(stdOut)
			Expect(string(result)).To(Equal(""))
		})
	})

	It("defaults to a StdoutLogger if the CF_TRACE file cannot be opened", func() {
		if runtime.GOOS != "windows" {
			stdOut := bytes.NewBuffer([]byte{})
			trace.SetStdout(stdOut)

			os.Setenv(trace.CF_TRACE, "/dev/null/whoops")

			logger := trace.NewLogger()
			logger.Print("hello world")

			result, _ := ioutil.ReadAll(stdOut)
			Expect(string(result)).To(ContainSubstring("hello world"))
		}
	})
})
<commit_msg>Clean up CF_TRACE tests<commit_after>package trace_test

import (
	"bytes"
	"cf/trace"
	"github.com/cloudfoundry/gofileutils/fileutils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"os"
	"runtime"
)

var _ = Describe("trace logger", func() {
	It("does not emit logs when CF_TRACE not set", func() {
		stdOut := bytes.NewBuffer([]byte{})
		trace.SetStdout(stdOut)

		os.Setenv(trace.CF_TRACE, "false")

		logger := trace.NewLogger()
		logger.Print("hello world")

		result, _ := ioutil.ReadAll(stdOut)
		Expect(string(result)).To(Equal(""))
	})

	It("emits messages when CF_TRACE is set to 'true'", func() {
		stdOut := bytes.NewBuffer([]byte{})
		trace.SetStdout(stdOut)

		os.Setenv(trace.CF_TRACE, "true")

		logger := trace.NewLogger()
		logger.Print("hello world")

		result, _ := ioutil.ReadAll(stdOut)
		Expect(string(result)).To(ContainSubstring("hello world"))
	})

	Context("when CF_TRACE is set to a filename", func() {
		It("writes logs to that file", func() {
			stdOut := bytes.NewBuffer([]byte{})
			trace.SetStdout(stdOut)

			fileutils.TempFile("trace_test", func(file *os.File, err error) {
				Expect(err).NotTo(HaveOccurred())
				file.Write([]byte("pre-existing content"))

				os.Setenv(trace.CF_TRACE, file.Name())

				logger := trace.NewLogger()
				logger.Print("hello world")

				file.Seek(0, os.SEEK_SET)
				result, err := ioutil.ReadAll(file)
				Expect(err).NotTo(HaveOccurred())

				byteString := string(result)
				Expect(byteString).To(ContainSubstring("pre-existing content"))
				Expect(byteString).To(ContainSubstring("hello world"))

				result, _ = ioutil.ReadAll(stdOut)
				Expect(string(result)).To(Equal(""))
			})
		})
	})

	Context("when CF_TRACE is set to a file path that cannot be opened", func() {
		It("defaults to printing to its out pipe", func() {
			if runtime.GOOS != "windows" {
				stdOut := bytes.NewBuffer([]byte{})
				trace.SetStdout(stdOut)

				os.Setenv(trace.CF_TRACE, "/dev/null/whoops")

				logger := trace.NewLogger()
				logger.Print("hello world")

				result, _ := ioutil.ReadAll(stdOut)
				Expect(string(result)).To(ContainSubstring("hello world"))
			}
		})

	})
})
<|endoftext|>


<commit_before>package bitsgo

import (
	"archive/zip"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/cloudfoundry-incubator/bits-service/logger"
	"github.com/cloudfoundry-incubator/bits-service/util"
	"github.com/pkg/errors"
)

type AppStashHandler struct {
	blobstore        NoRedirectBlobstore
	maxBodySizeLimit uint64
	minimumSize      uint64
	maximumSize      uint64
	metricsService   MetricsService
}

func NewAppStashHandlerWithSizeThresholds(blobstore NoRedirectBlobstore, maxBodySizeLimit uint64, minimumSize uint64, maximumSize uint64, metricsService MetricsService) *AppStashHandler {
	return &AppStashHandler{
		blobstore:        blobstore,
		maxBodySizeLimit: maxBodySizeLimit,
		minimumSize:      minimumSize,
		maximumSize:      maximumSize,
		metricsService:   metricsService,
	}
}

func (handler *AppStashHandler) PostMatches(responseWriter http.ResponseWriter, request *http.Request) {
	if !HandleBodySizeLimits(responseWriter, request, handler.maxBodySizeLimit) {
		return
	}
	body, e := ioutil.ReadAll(request.Body)
	util.PanicOnError(e)
	var fingerprints []Fingerprint
	e = json.Unmarshal(body, &fingerprints)
	if e != nil {
		logger.From(request).Debugw("Invalid body", "body", string(body), "error", e)
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		fmt.Fprintf(responseWriter, "Invalid body %s", body)
		return
	}
	if len(fingerprints) == 0 {
		logger.From(request).Debugw("Empty list", "body", string(body), "error", e)
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		util.FprintDescriptionAsJSON(responseWriter, "The request is semantically invalid: must be a non-empty array.")
		return
	}
	matchedFingerprints := []Fingerprint{} // this must not be nil, because the JSON marshaller will not marshal it correctly in case of []
	for _, entry := range fingerprints {
		if entry.Size < handler.minimumSize || entry.Size > handler.maximumSize {
			continue
		}
		exists, e := handler.blobstore.Exists(entry.Sha1)
		util.PanicOnError(e)
		if exists {
			matchedFingerprints = append(matchedFingerprints, entry)
		}
	}
	response, e := json.Marshal(&matchedFingerprints)
	util.PanicOnError(e)
	responseWriter.Write(response)
}

func (handler *AppStashHandler) PostEntries(responseWriter http.ResponseWriter, request *http.Request) {
	if !HandleBodySizeLimits(responseWriter, request, handler.maxBodySizeLimit) {
		return
	}
	uploadedFile, _, e := request.FormFile("application")
	if e != nil {
		badRequest(responseWriter, request, "Could not retrieve 'application' form parameter")
		return
	}
	defer uploadedFile.Close()

	tempZipFile, e := ioutil.TempFile("", "")
	util.PanicOnError(e)
	defer os.Remove(tempZipFile.Name())
	defer tempZipFile.Close()

	_, e = io.Copy(tempZipFile, uploadedFile)
	util.PanicOnError(e)

	openZipFile, e := zip.OpenReader(tempZipFile.Name())
	if e != nil {
		badRequest(responseWriter, request, "Bad Request: Not a valid zip file")
		return
	}
	defer openZipFile.Close()

	fingerprints := []Fingerprint{} // this must not be nil, because the JSON marshaller will not marshal it correctly in case of []
	for _, zipFileEntry := range openZipFile.File {
		if !zipFileEntry.FileInfo().Mode().IsRegular() {
			continue
		}
		sha, e := copyTo(handler.blobstore, zipFileEntry)
		if _, isNoSpaceLeftError := e.(*NoSpaceLeftError); isNoSpaceLeftError {
			http.Error(responseWriter, util.DescriptionAndCodeAsJSON(500000, "Request Entity Too Large"), http.StatusInsufficientStorage)
			return
		}
		util.PanicOnError(e)
		logger.From(request).Debugw("Filemode in zip File Entry", "filemode", zipFileEntry.FileInfo().Mode().String())
		fingerprints = append(fingerprints, Fingerprint{
			Sha1: sha,
			Fn:   zipFileEntry.Name,
			Mode: strconv.FormatInt(int64(zipFileEntry.FileInfo().Mode()), 8),
			Size: zipFileEntry.UncompressedSize64,
		})
	}
	receipt, e := json.Marshal(fingerprints)
	util.PanicOnError(e)
	responseWriter.WriteHeader(http.StatusCreated)
	responseWriter.Write(receipt)
}

func copyTo(blobstore NoRedirectBlobstore, zipFileEntry *zip.File) (sha string, err error) {
	unzippedReader, e := zipFileEntry.Open()
	if e != nil {
		return "", errors.WithStack(e)
	}
	defer unzippedReader.Close()

	tempZipEntryFile, e := ioutil.TempFile("", filepath.Base(zipFileEntry.Name))
	if e != nil {
		return "", errors.WithStack(e)
	}
	defer os.Remove(tempZipEntryFile.Name())
	defer tempZipEntryFile.Close()

	sha, e = copyCalculatingSha(tempZipEntryFile, unzippedReader)
	if e != nil {
		return "", errors.WithStack(e)
	}

	entryFileRead, e := os.Open(tempZipEntryFile.Name())
	if e != nil {
		return "", errors.WithStack(e)
	}
	defer entryFileRead.Close()

	e = blobstore.Put(sha, entryFileRead)
	if _, noSpaceLeft := e.(*NoSpaceLeftError); noSpaceLeft {
		return "", e
	}
	if e != nil {
		return "", errors.WithStack(e)
	}

	return
}

func copyCalculatingSha(writer io.Writer, reader io.Reader) (sha string, e error) {
	checkSum := sha1.New()

	_, e = io.Copy(io.MultiWriter(writer, checkSum), reader)
	if e != nil {
		return "", fmt.Errorf("error copying. Caused by: %v", e)
	}

	return fmt.Sprintf("%x", checkSum.Sum(nil)), nil
}

type Fingerprint struct {
	Fn   string `json:"fn"`
	Sha1 string `json:"sha1"`
	Size uint64 `json:"size"`
	Mode string `json:"mode"`
}

func (handler *AppStashHandler) PostBundles(responseWriter http.ResponseWriter, request *http.Request) {
	if !HandleBodySizeLimits(responseWriter, request, handler.maxBodySizeLimit) {
		return
	}

	var (
		resources io.Reader
		e         error
	)
	var zipReader *zip.Reader
	if strings.Contains(request.Header.Get("Content-Type"), "multipart/form-data") {
		resources, _, e = request.FormFile("resources")
		if e == http.ErrMissingFile {
			badRequest(responseWriter, request, "Could not retrieve form parameter 'resources")
			return
		}
		util.PanicOnError(e)
		zipFile, fi, e := request.FormFile("application")
		if e == http.ErrMissingFile {
			badRequest(responseWriter, request, "Could not retrieve form parameter 'application")
			return
		}
		util.PanicOnError(e)
		defer zipFile.Close()
		zipReader, e = zip.NewReader(zipFile, fi.Size)
		util.PanicOnError(e)
	} else {
		resources = request.Body
	}

	body, e := ioutil.ReadAll(resources)
	util.PanicOnError(e)

	var bundlesPayload []Fingerprint
	e = json.Unmarshal(body, &bundlesPayload)
	if e != nil {
		log.Printf("Invalid body %s", body)
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		util.FprintDescriptionAsJSON(responseWriter, "Invalid body %s", body)
		return
	}

	if isMissing, key := anyKeyMissingIn(bundlesPayload); isMissing {
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		util.FprintDescriptionAsJSON(responseWriter, "The request is semantically invalid: key `%v` missing or empty", key)
		return
	}

	tempZipFilename, e := CreateTempZipFileFrom(bundlesPayload, zipReader, handler.minimumSize, handler.maximumSize, handler.blobstore, handler.metricsService)
	if e != nil {
		if notFoundError, ok := e.(*NotFoundError); ok {
			responseWriter.WriteHeader(http.StatusNotFound)
			util.FprintDescriptionAsJSON(responseWriter, "%v not found", notFoundError.Error())
			return
		}
		panic(e)
	}
	defer os.Remove(tempZipFilename)

	tempZipFile, e := os.Open(tempZipFilename)
	util.PanicOnError(e)
	defer tempZipFile.Close()

	_, e = io.Copy(responseWriter, tempZipFile)
	util.PanicOnError(e)
}

func anyKeyMissingIn(bundlesPayload []Fingerprint) (bool, string) {
	for _, entry := range bundlesPayload {
		if entry.Sha1 == "" {
			return true, "sha1"
		}
		if entry.Fn == "" {
			return true, "fn"
		}
	}
	return false, ""
}
<commit_msg>Fix error message when sha1 not found<commit_after>package bitsgo

import (
	"archive/zip"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/cloudfoundry-incubator/bits-service/logger"
	"github.com/cloudfoundry-incubator/bits-service/util"
	"github.com/pkg/errors"
)

type AppStashHandler struct {
	blobstore        NoRedirectBlobstore
	maxBodySizeLimit uint64
	minimumSize      uint64
	maximumSize      uint64
	metricsService   MetricsService
}

func NewAppStashHandlerWithSizeThresholds(blobstore NoRedirectBlobstore, maxBodySizeLimit uint64, minimumSize uint64, maximumSize uint64, metricsService MetricsService) *AppStashHandler {
	return &AppStashHandler{
		blobstore:        blobstore,
		maxBodySizeLimit: maxBodySizeLimit,
		minimumSize:      minimumSize,
		maximumSize:      maximumSize,
		metricsService:   metricsService,
	}
}

func (handler *AppStashHandler) PostMatches(responseWriter http.ResponseWriter, request *http.Request) {
	if !HandleBodySizeLimits(responseWriter, request, handler.maxBodySizeLimit) {
		return
	}
	body, e := ioutil.ReadAll(request.Body)
	util.PanicOnError(e)
	var fingerprints []Fingerprint
	e = json.Unmarshal(body, &fingerprints)
	if e != nil {
		logger.From(request).Debugw("Invalid body", "body", string(body), "error", e)
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		fmt.Fprintf(responseWriter, "Invalid body %s", body)
		return
	}
	if len(fingerprints) == 0 {
		logger.From(request).Debugw("Empty list", "body", string(body), "error", e)
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		util.FprintDescriptionAsJSON(responseWriter, "The request is semantically invalid: must be a non-empty array.")
		return
	}
	matchedFingerprints := []Fingerprint{} // this must not be nil, because the JSON marshaller will not marshal it correctly in case of []
	for _, entry := range fingerprints {
		if entry.Size < handler.minimumSize || entry.Size > handler.maximumSize {
			continue
		}
		exists, e := handler.blobstore.Exists(entry.Sha1)
		util.PanicOnError(e)
		if exists {
			matchedFingerprints = append(matchedFingerprints, entry)
		}
	}
	response, e := json.Marshal(&matchedFingerprints)
	util.PanicOnError(e)
	responseWriter.Write(response)
}

func (handler *AppStashHandler) PostEntries(responseWriter http.ResponseWriter, request *http.Request) {
	if !HandleBodySizeLimits(responseWriter, request, handler.maxBodySizeLimit) {
		return
	}
	uploadedFile, _, e := request.FormFile("application")
	if e != nil {
		badRequest(responseWriter, request, "Could not retrieve 'application' form parameter")
		return
	}
	defer uploadedFile.Close()

	tempZipFile, e := ioutil.TempFile("", "")
	util.PanicOnError(e)
	defer os.Remove(tempZipFile.Name())
	defer tempZipFile.Close()

	_, e = io.Copy(tempZipFile, uploadedFile)
	util.PanicOnError(e)

	openZipFile, e := zip.OpenReader(tempZipFile.Name())
	if e != nil {
		badRequest(responseWriter, request, "Bad Request: Not a valid zip file")
		return
	}
	defer openZipFile.Close()

	fingerprints := []Fingerprint{} // this must not be nil, because the JSON marshaller will not marshal it correctly in case of []
	for _, zipFileEntry := range openZipFile.File {
		if !zipFileEntry.FileInfo().Mode().IsRegular() {
			continue
		}
		sha, e := copyTo(handler.blobstore, zipFileEntry)
		if _, isNoSpaceLeftError := e.(*NoSpaceLeftError); isNoSpaceLeftError {
			http.Error(responseWriter, util.DescriptionAndCodeAsJSON(500000, "Request Entity Too Large"), http.StatusInsufficientStorage)
			return
		}
		util.PanicOnError(e)
		logger.From(request).Debugw("Filemode in zip File Entry", "filemode", zipFileEntry.FileInfo().Mode().String())
		fingerprints = append(fingerprints, Fingerprint{
			Sha1: sha,
			Fn:   zipFileEntry.Name,
			Mode: strconv.FormatInt(int64(zipFileEntry.FileInfo().Mode()), 8),
			Size: zipFileEntry.UncompressedSize64,
		})
	}
	receipt, e := json.Marshal(fingerprints)
	util.PanicOnError(e)
	responseWriter.WriteHeader(http.StatusCreated)
	responseWriter.Write(receipt)
}

func copyTo(blobstore NoRedirectBlobstore, zipFileEntry *zip.File) (sha string, err error) {
	unzippedReader, e := zipFileEntry.Open()
	if e != nil {
		return "", errors.WithStack(e)
	}
	defer unzippedReader.Close()

	tempZipEntryFile, e := ioutil.TempFile("", filepath.Base(zipFileEntry.Name))
	if e != nil {
		return "", errors.WithStack(e)
	}
	defer os.Remove(tempZipEntryFile.Name())
	defer tempZipEntryFile.Close()

	sha, e = copyCalculatingSha(tempZipEntryFile, unzippedReader)
	if e != nil {
		return "", errors.WithStack(e)
	}

	entryFileRead, e := os.Open(tempZipEntryFile.Name())
	if e != nil {
		return "", errors.WithStack(e)
	}
	defer entryFileRead.Close()

	e = blobstore.Put(sha, entryFileRead)
	if _, noSpaceLeft := e.(*NoSpaceLeftError); noSpaceLeft {
		return "", e
	}
	if e != nil {
		return "", errors.WithStack(e)
	}

	return
}

func copyCalculatingSha(writer io.Writer, reader io.Reader) (sha string, e error) {
	checkSum := sha1.New()

	_, e = io.Copy(io.MultiWriter(writer, checkSum), reader)
	if e != nil {
		return "", fmt.Errorf("error copying. Caused by: %v", e)
	}

	return fmt.Sprintf("%x", checkSum.Sum(nil)), nil
}

type Fingerprint struct {
	Fn   string `json:"fn"`
	Sha1 string `json:"sha1"`
	Size uint64 `json:"size"`
	Mode string `json:"mode"`
}

func (handler *AppStashHandler) PostBundles(responseWriter http.ResponseWriter, request *http.Request) {
	if !HandleBodySizeLimits(responseWriter, request, handler.maxBodySizeLimit) {
		return
	}

	var (
		resources io.Reader
		e         error
	)
	var zipReader *zip.Reader
	if strings.Contains(request.Header.Get("Content-Type"), "multipart/form-data") {
		resources, _, e = request.FormFile("resources")
		if e == http.ErrMissingFile {
			badRequest(responseWriter, request, "Could not retrieve form parameter 'resources")
			return
		}
		util.PanicOnError(e)
		zipFile, fi, e := request.FormFile("application")
		if e == http.ErrMissingFile {
			badRequest(responseWriter, request, "Could not retrieve form parameter 'application")
			return
		}
		util.PanicOnError(e)
		defer zipFile.Close()
		zipReader, e = zip.NewReader(zipFile, fi.Size)
		util.PanicOnError(e)
	} else {
		resources = request.Body
	}

	body, e := ioutil.ReadAll(resources)
	util.PanicOnError(e)

	var bundlesPayload []Fingerprint
	e = json.Unmarshal(body, &bundlesPayload)
	if e != nil {
		log.Printf("Invalid body %s", body)
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		util.FprintDescriptionAsJSON(responseWriter, "Invalid body %s", body)
		return
	}

	if isMissing, key := anyKeyMissingIn(bundlesPayload); isMissing {
		responseWriter.WriteHeader(http.StatusUnprocessableEntity)
		util.FprintDescriptionAsJSON(responseWriter, "The request is semantically invalid: key `%v` missing or empty", key)
		return
	}

	tempZipFilename, e := CreateTempZipFileFrom(bundlesPayload, zipReader, handler.minimumSize, handler.maximumSize, handler.blobstore, handler.metricsService)
	if e != nil {
		if notFoundError, ok := e.(*NotFoundError); ok {
			responseWriter.WriteHeader(http.StatusNotFound)
			util.FprintDescriptionAsJSON(responseWriter, "%v not found", notFoundError.MissingKey)
			return
		}
		panic(e)
	}
	defer os.Remove(tempZipFilename)

	tempZipFile, e := os.Open(tempZipFilename)
	util.PanicOnError(e)
	defer tempZipFile.Close()

	_, e = io.Copy(responseWriter, tempZipFile)
	util.PanicOnError(e)
}

func anyKeyMissingIn(bundlesPayload []Fingerprint) (bool, string) {
	for _, entry := range bundlesPayload {
		if entry.Sha1 == "" {
			return true, "sha1"
		}
		if entry.Fn == "" {
			return true, "fn"
		}
	}
	return false, ""
}
<|endoftext|>


<commit_before>package assert

import (
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"time"
)

// TestingT is an interface wrapper around *testing.T
type TestingT interface {
	Errorf(format string, args ...interface{})
}

// Comparison a custom function that returns true on success and false on failure
type Comparison func() (success bool)

/*
	Helper functions
*/

// ObjectsAreEqual determines if two objects are considered equal.
//
// This function does no assertion of any kind.
func ObjectsAreEqual(a, b interface{}) bool {

	if reflect.DeepEqual(a, b) {
		return true
	}

	if reflect.ValueOf(a) == reflect.ValueOf(b) {
		return true
	}

	// Last ditch effort
	if fmt.Sprintf("%#v", a) == fmt.Sprintf("%#v", b) {
		return true
	}

	return false

}

/* CallerInfo is necessary because the assert functions use the testing object
internally, causing it to print the file:line of the assert method, rather than where
the problem actually occured in calling code.*/

// CallerInfo returns a string containing the file and line number of the assert call
// that failed.
func CallerInfo() string {

	file := ""
	line := 0
	ok := false

	for i := 0; ; i++ {
		_, file, line, ok = runtime.Caller(i)
		if !ok {
			return ""
		}
		parts := strings.Split(file, "/")
		dir := parts[len(parts)-2]
		file = parts[len(parts)-1]
		if (dir != "assert" && dir != "mock") || file == "mock_test.go" {
			break
		}
	}

	return fmt.Sprintf("%s:%d", file, line)
}

// getWhitespaceString returns a string that is long enough to overwrite the default
// output from the go testing framework.
func getWhitespaceString() string {

	_, file, line, ok := runtime.Caller(1)
	if !ok {
		return ""
	}
	parts := strings.Split(file, "/")
	file = parts[len(parts)-1]

	return strings.Repeat(" ", len(fmt.Sprintf("%s:%d:      ", file, line)))

}

func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
	if len(msgAndArgs) == 0 || msgAndArgs == nil {
		return ""
	}
	if len(msgAndArgs) == 1 {
		return msgAndArgs[0].(string)
	}
	if len(msgAndArgs) > 1 {
		return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
	}
	return ""
}

// Fail reports a failure through
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)

	if len(message) > 0 {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r\tMessages:\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage, message)
	} else {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage)
	}

	return false
}

// Implements asserts that an object is implemented by the specified interface.
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	interfaceType := reflect.TypeOf(interfaceObject).Elem()

	if !reflect.TypeOf(object).Implements(interfaceType) {
		return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
	}

	return true

}

// IsType asserts that the specified objects are of the same type.
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
		return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
	}

	return true
}

// Equal asserts that two objects are equal.
//
//    assert.Equal(t, 123, 123, "123 and 123 should be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Equal(t TestingT, a, b interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(a, b) {
		return Fail(t, fmt.Sprintf("Not equal: %#v != %#v", a, b), msgAndArgs...)
	}

	return true

}

// Exactly asserts that two objects are equal is value and type.
//
//    assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Exactly(t TestingT, a, b interface{}, msgAndArgs ...interface{}) bool {

	aType := reflect.TypeOf(a)
	bType := reflect.TypeOf(b)

	if aType != bType {
		return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
	}

	return Equal(t, a, b, msgAndArgs...)

}

// NotNil asserts that the specified object is not nil.
//
//    assert.NotNil(t, err, "err should be something")
//
// Returns whether the assertion was successful (true) or not (false).
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	var success bool = true

	if object == nil {
		success = false
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			success = false
		}
	}

	if !success {
		Fail(t, "Expected not to be nil.", msgAndArgs...)
	}

	return success
}

// Nil asserts that the specified object is nil.
//
//    assert.Nil(t, err, "err should be nothing")
//
// Returns whether the assertion was successful (true) or not (false).
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	if object == nil {
		return true
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			return true
		}
	}

	return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
}

// isEmpty gets whether the specified object is considered empty or not.
func isEmpty(object interface{}) bool {

	if object == nil {
		return true
	} else if object == "" {
		return true
	} else if object == 0 {
		return true
	} else if object == false {
		return true
	}

	objValue := reflect.ValueOf(object)
	switch objValue.Kind() {
	case reflect.Map:
		fallthrough
	case reflect.Slice:
		{
			return (objValue.Len() == 0)
		}
	}

	return false

}

// Empty asserts that the specified object is empty.  I.e. nil, "", false, 0 or a
// slice with len == 0.
//
// assert.Empty(t, obj)
//
// Returns whether the assertion was successful (true) or not (false).
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// Empty asserts that the specified object is NOT empty.  I.e. not nil, "", false, 0 or a
// slice with len == 0.
//
// if assert.NotEmpty(t, obj) {
//   assert.Equal(t, "two", obj[1])
// }
//
// Returns whether the assertion was successful (true) or not (false).
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := !isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// True asserts that the specified value is true.
//
//    assert.True(t, myBool, "myBool should be true")
//
// Returns whether the assertion was successful (true) or not (false).
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != true {
		return Fail(t, "Should be true", msgAndArgs...)
	}

	return true

}

// False asserts that the specified value is true.
//
//    assert.False(t, myBool, "myBool should be false")
//
// Returns whether the assertion was successful (true) or not (false).
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != false {
		return Fail(t, "Should be false", msgAndArgs...)
	}

	return true

}

// NotEqual asserts that the specified values are NOT equal.
//
//    assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func NotEqual(t TestingT, a, b interface{}, msgAndArgs ...interface{}) bool {

	if ObjectsAreEqual(a, b) {
		return Fail(t, "Should not be equal", msgAndArgs...)
	}

	return true

}

// Contains asserts that the specified string contains the specified substring.
//
//    assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
//
// Returns whether the assertion was successful (true) or not (false).
func Contains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if !strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// NotContains asserts that the specified string does NOT contain the specified substring.
//
//    assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
//
// Returns whether the assertion was successful (true) or not (false).
func NotContains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// Uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
	result := comp()
	if !result {
		Fail(t, "Condition failed!", msgAndArgs...)
	}
	return result
}

// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
// methods, and represents a simple func that takes no arguments, and returns nothing.
type PanicTestFunc func()

// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
func didPanic(f PanicTestFunc) (bool, interface{}) {

	var didPanic bool = false
	var message interface{}
	func() {

		defer func() {
			if message = recover(); message != nil {
				didPanic = true
			}
		}()

		// call the target function
		f()

	}()

	return didPanic, message

}

// Panics asserts that the code inside the specified PanicTestFunc panics.
//
//   assert.Panics(t, func(){
//     GoCrazy()
//   }, "Calling GoCrazy() should panic")
//
// Returns whether the assertion was successful (true) or not (false).
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
//
//   assert.NotPanics(t, func(){
//     RemainCalm()
//   }, "Calling RemainCalm() should NOT panic")
//
// Returns whether the assertion was successful (true) or not (false).
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// WithinDuration asserts that the two times are within duration delta of each other.
//
//   assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
//
// Returns whether the assertion was successful (true) or not (false).
func WithinDuration(t TestingT, a, b time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {

	dt := a.Sub(b)
	if dt < -delta || dt > delta {
		return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", a, b, dt, delta), msgAndArgs...)
	}

	return true
}

/*
	Errors
*/

// NoError asserts that a function returned no error (i.e. `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.NoError(t, err) {
//	   assert.Equal(t, actualObj, expectedObj)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func NoError(t TestingT, theError error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return Nil(t, theError, "No error is expected but got %v %s", theError, message)

}

// Error asserts that a function returned an error (i.e. not `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.Error(t, err, "An error was expected") {
//	   assert.Equal(t, err, expectedError)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func Error(t TestingT, theError error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return NotNil(t, theError, "An error is expected but got nil. %s", message)

}
<commit_msg>Fixes #2<commit_after>package assert

import (
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"time"
)

// TestingT is an interface wrapper around *testing.T
type TestingT interface {
	Errorf(format string, args ...interface{})
}

// Comparison a custom function that returns true on success and false on failure
type Comparison func() (success bool)

/*
	Helper functions
*/

// ObjectsAreEqual determines if two objects are considered equal.
//
// This function does no assertion of any kind.
func ObjectsAreEqual(expected, actual interface{}) bool {

	if reflect.DeepEqual(expected, actual) {
		return true
	}

	if reflect.ValueOf(expected) == reflect.ValueOf(actual) {
		return true
	}

	// Last ditch effort
	if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) {
		return true
	}

	return false

}

/* CallerInfo is necessary because the assert functions use the testing object
internally, causing it to print the file:line of the assert method, rather than where
the problem actually occured in calling code.*/

// CallerInfo returns a string containing the file and line number of the assert call
// that failed.
func CallerInfo() string {

	file := ""
	line := 0
	ok := false

	for i := 0; ; i++ {
		_, file, line, ok = runtime.Caller(i)
		if !ok {
			return ""
		}
		parts := strings.Split(file, "/")
		dir := parts[len(parts)-2]
		file = parts[len(parts)-1]
		if (dir != "assert" && dir != "mock") || file == "mock_test.go" {
			break
		}
	}

	return fmt.Sprintf("%s:%d", file, line)
}

// getWhitespaceString returns a string that is long enough to overwrite the default
// output from the go testing framework.
func getWhitespaceString() string {

	_, file, line, ok := runtime.Caller(1)
	if !ok {
		return ""
	}
	parts := strings.Split(file, "/")
	file = parts[len(parts)-1]

	return strings.Repeat(" ", len(fmt.Sprintf("%s:%d:      ", file, line)))

}

func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
	if len(msgAndArgs) == 0 || msgAndArgs == nil {
		return ""
	}
	if len(msgAndArgs) == 1 {
		return msgAndArgs[0].(string)
	}
	if len(msgAndArgs) > 1 {
		return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
	}
	return ""
}

// Fail reports a failure through
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)

	if len(message) > 0 {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r\tMessages:\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage, message)
	} else {
		t.Errorf("\r%s\r\tLocation:\t%s\n\r\tError:\t\t%s\n\r", getWhitespaceString(), CallerInfo(), failureMessage)
	}

	return false
}

// Implements asserts that an object is implemented by the specified interface.
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	interfaceType := reflect.TypeOf(interfaceObject).Elem()

	if !reflect.TypeOf(object).Implements(interfaceType) {
		return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
	}

	return true

}

// IsType asserts that the specified objects are of the same type.
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
		return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
	}

	return true
}

// Equal asserts that two objects are equal.
//
//    assert.Equal(t, 123, 123, "123 and 123 should be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	if !ObjectsAreEqual(expected, actual) {
		return Fail(t, fmt.Sprintf("Not equal: %#v != %#v", expected, actual), msgAndArgs...)
	}

	return true

}

// Exactly asserts that two objects are equal is value and type.
//
//    assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	aType := reflect.TypeOf(expected)
	bType := reflect.TypeOf(actual)

	if aType != bType {
		return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
	}

	return Equal(t, expected, actual, msgAndArgs...)

}

// NotNil asserts that the specified object is not nil.
//
//    assert.NotNil(t, err, "err should be something")
//
// Returns whether the assertion was successful (true) or not (false).
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	var success bool = true

	if object == nil {
		success = false
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			success = false
		}
	}

	if !success {
		Fail(t, "Expected not to be nil.", msgAndArgs...)
	}

	return success
}

// Nil asserts that the specified object is nil.
//
//    assert.Nil(t, err, "err should be nothing")
//
// Returns whether the assertion was successful (true) or not (false).
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	if object == nil {
		return true
	} else {
		value := reflect.ValueOf(object)
		kind := value.Kind()
		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
			return true
		}
	}

	return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
}

// isEmpty gets whether the specified object is considered empty or not.
func isEmpty(object interface{}) bool {

	if object == nil {
		return true
	} else if object == "" {
		return true
	} else if object == 0 {
		return true
	} else if object == false {
		return true
	}

	objValue := reflect.ValueOf(object)
	switch objValue.Kind() {
	case reflect.Map:
		fallthrough
	case reflect.Slice:
		{
			return (objValue.Len() == 0)
		}
	}

	return false

}

// Empty asserts that the specified object is empty.  I.e. nil, "", false, 0 or a
// slice with len == 0.
//
// assert.Empty(t, obj)
//
// Returns whether the assertion was successful (true) or not (false).
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// Empty asserts that the specified object is NOT empty.  I.e. not nil, "", false, 0 or a
// slice with len == 0.
//
// if assert.NotEmpty(t, obj) {
//   assert.Equal(t, "two", obj[1])
// }
//
// Returns whether the assertion was successful (true) or not (false).
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {

	pass := !isEmpty(object)
	if !pass {
		Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
	}

	return pass

}

// True asserts that the specified value is true.
//
//    assert.True(t, myBool, "myBool should be true")
//
// Returns whether the assertion was successful (true) or not (false).
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != true {
		return Fail(t, "Should be true", msgAndArgs...)
	}

	return true

}

// False asserts that the specified value is true.
//
//    assert.False(t, myBool, "myBool should be false")
//
// Returns whether the assertion was successful (true) or not (false).
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {

	if value != false {
		return Fail(t, "Should be false", msgAndArgs...)
	}

	return true

}

// NotEqual asserts that the specified values are NOT equal.
//
//    assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
//
// Returns whether the assertion was successful (true) or not (false).
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {

	if ObjectsAreEqual(expected, actual) {
		return Fail(t, "Should not be equal", msgAndArgs...)
	}

	return true

}

// Contains asserts that the specified string contains the specified substring.
//
//    assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
//
// Returns whether the assertion was successful (true) or not (false).
func Contains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if !strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// NotContains asserts that the specified string does NOT contain the specified substring.
//
//    assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
//
// Returns whether the assertion was successful (true) or not (false).
func NotContains(t TestingT, s, contains string, msgAndArgs ...interface{}) bool {

	if strings.Contains(s, contains) {
		return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
	}

	return true

}

// Uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
	result := comp()
	if !result {
		Fail(t, "Condition failed!", msgAndArgs...)
	}
	return result
}

// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
// methods, and represents a simple func that takes no arguments, and returns nothing.
type PanicTestFunc func()

// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
func didPanic(f PanicTestFunc) (bool, interface{}) {

	var didPanic bool = false
	var message interface{}
	func() {

		defer func() {
			if message = recover(); message != nil {
				didPanic = true
			}
		}()

		// call the target function
		f()

	}()

	return didPanic, message

}

// Panics asserts that the code inside the specified PanicTestFunc panics.
//
//   assert.Panics(t, func(){
//     GoCrazy()
//   }, "Calling GoCrazy() should panic")
//
// Returns whether the assertion was successful (true) or not (false).
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
//
//   assert.NotPanics(t, func(){
//     RemainCalm()
//   }, "Calling RemainCalm() should NOT panic")
//
// Returns whether the assertion was successful (true) or not (false).
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {

	if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
		return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
	}

	return true
}

// WithinDuration asserts that the two times are within duration delta of each other.
//
//   assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
//
// Returns whether the assertion was successful (true) or not (false).
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {

	dt := expected.Sub(actual)
	if dt < -delta || dt > delta {
		return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, dt, delta), msgAndArgs...)
	}

	return true
}

/*
	Errors
*/

// NoError asserts that a function returned no error (i.e. `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.NoError(t, err) {
//	   assert.Equal(t, actualObj, expectedObj)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func NoError(t TestingT, theError error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return Nil(t, theError, "No error is expected but got %v %s", theError, message)

}

// Error asserts that a function returned an error (i.e. not `nil`).
//
//   actualObj, err := SomeFunction()
//   if assert.Error(t, err, "An error was expected") {
//	   assert.Equal(t, err, expectedError)
//   }
//
// Returns whether the assertion was successful (true) or not (false).
func Error(t TestingT, theError error, msgAndArgs ...interface{}) bool {

	message := messageFromMsgAndArgs(msgAndArgs...)
	return NotNil(t, theError, "An error is expected but got nil. %s", message)

}
<|endoftext|>


<commit_before>package docker

import (
	"github.com/docker/docker/pkg/stringutils"
	"github.com/docker/docker/runconfig"
	"github.com/hyperhq/hyper/lib/docker/daemon"
)

func (cli Docker) SendCmdCreate(name, image string, entrypoint, cmds []string, userConfig interface{}) ([]byte, int, error) {
	config := &runconfig.Config{
		Image:      image,
		Cmd:        stringutils.NewStrSlice(cmds...),
		Entrypoint: stringutils.NewStrSlice(entrypoint...),
	}
	if userConfig != nil {
		config = userConfig.(*runconfig.Config)
	}
	hostConfig := &runconfig.HostConfig{}
	containerResp, err := cli.daemon.ContainerCreate(&daemon.ContainerCreateConfig{
		Name:            name,
		Config:          config,
		HostConfig:      hostConfig,
		AdjustCPUShares: false,
	})
	if err != nil {
		return nil, 500, err
	}
	return []byte(containerResp.ID), 200, nil
}
<commit_msg>docker check nil of entrypoint<commit_after>package docker

import (
	"github.com/docker/docker/pkg/stringutils"
	"github.com/docker/docker/runconfig"
	"github.com/hyperhq/hyper/lib/docker/daemon"
)

func (cli Docker) SendCmdCreate(name, image string, entrypoint, cmds []string, userConfig interface{}) ([]byte, int, error) {
	config := &runconfig.Config{
		Image: image,
		Cmd:   stringutils.NewStrSlice(cmds...),
	}

	if len(entrypoint) != 0 {
		config.Entrypoint = stringutils.NewStrSlice(entrypoint...)
	}

	if userConfig != nil {
		config = userConfig.(*runconfig.Config)
	}
	hostConfig := &runconfig.HostConfig{}
	containerResp, err := cli.daemon.ContainerCreate(&daemon.ContainerCreateConfig{
		Name:            name,
		Config:          config,
		HostConfig:      hostConfig,
		AdjustCPUShares: false,
	})
	if err != nil {
		return nil, 500, err
	}
	return []byte(containerResp.ID), 200, nil
}
<|endoftext|>


<commit_before>package docker

import (
	"bufio"
	"bytes"
	"context"
	"github.com/ViBiOh/docker-deploy/jsonHttp"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/strslice"
	"github.com/docker/docker/client"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
)

const host = `DOCKER_HOST`
const version = `DOCKER_VERSION`
const configurationFile = `./users`

var commaByte = []byte(`,`)
var splitLogs = regexp.MustCompile(`.{8}(.*?)\n`)

var containersRequest = regexp.MustCompile(`/containers/?$`)
var containerRequest = regexp.MustCompile(`/containers/([^/]+)/?$`)
var startRequest = regexp.MustCompile(`/containers/([^/]+)/start`)
var stopRequest = regexp.MustCompile(`/containers/([^/]+)/stop`)
var restartRequest = regexp.MustCompile(`/containers/([^/]+)/restart`)
var logRequest = regexp.MustCompile(`/containers/([^/]+)/logs`)

type results struct {
	Results interface{} `json:"results"`
}

type user struct {
	username string
	password string
}

type dockerCompose struct {
	Version  string
	Services map[string]struct {
		Image       string
		Command     string
		Environment map[string]string
		Labels      map[string]string
	}
}

var docker *client.Client
var users map[string]*user

func handleError(w http.ResponseWriter, err error) {
	log.Print(err)
	http.Error(w, err.Error(), http.StatusInternalServerError)
}

func readConfiguration(path string) map[string]*user {
	configFile, err := os.Open(path)
	defer configFile.Close()

	if err != nil {
		log.Print(err)
		return nil
	}

	users := make(map[string]*user)

	scanner := bufio.NewScanner(configFile)
	for scanner.Scan() {
		parts := bytes.Split(scanner.Bytes(), commaByte)
		user := user{string(parts[0]), string(parts[1])}

		users[strings.ToLower(user.username)] = &user
	}

	return users
}

func init() {
	users = readConfiguration(configurationFile)

	client, err := client.NewClient(os.Getenv(host), os.Getenv(version), nil, nil)
	if err != nil {
		log.Fatal(err)
	} else {
		docker = client
	}
}

func inspectContainer(w http.ResponseWriter, containerID []byte) {
	if container, err := docker.ContainerInspect(context.Background(), string(containerID)); err != nil {
		handleError(w, err)
	} else {
		jsonHttp.ResponseJSON(w, container)
	}
}

func startContainer(w http.ResponseWriter, containerID []byte) {
	if err := docker.ContainerStart(context.Background(), string(containerID), types.ContainerStartOptions{}); err != nil {
		handleError(w, err)
	} else {
		w.Write(nil)
	}
}

func stopContainer(w http.ResponseWriter, containerID []byte) {
	if err := docker.ContainerStop(context.Background(), string(containerID), nil); err != nil {
		handleError(w, err)
	} else {
		w.Write(nil)
	}
}

func restartContainer(w http.ResponseWriter, containerID []byte) {
	if err := docker.ContainerRestart(context.Background(), string(containerID), nil); err != nil {
		handleError(w, err)
	} else {
		w.Write(nil)
	}
}

func logContainer(w http.ResponseWriter, containerID []byte) {
	logs, err := docker.ContainerLogs(context.Background(), string(containerID), types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: false})
	if err != nil {
		handleError(w, err)
		return
	}

	defer logs.Close()

	if logLines, err := ioutil.ReadAll(logs); err != nil {
		handleError(w, err)
	} else {
		matches := splitLogs.FindAllSubmatch(logLines, -1)
		cleanLogs := make([]string, 0, len(matches))
		for _, match := range matches {
			cleanLogs = append(cleanLogs, string(match[1]))
		}

		jsonHttp.ResponseJSON(w, results{cleanLogs})
	}
}

func listContainers(w http.ResponseWriter) {
	if containers, err := docker.ContainerList(context.Background(), types.ContainerListOptions{All: true}); err != nil {
		handleError(w, err)
	} else {
		jsonHttp.ResponseJSON(w, results{containers})
	}
}

func readBody(body io.ReadCloser) ([]byte, error) {
	defer body.Close()
	return ioutil.ReadAll(body)
}

func getTraefikNetwork() (*types.NetworkResource, error) {
	args := filters.NewArgs()
	args.Add(`name`, `traefik`)

	networks, err := docker.NetworkList(context.Background(), types.NetworkListOptions{Filters: args})
	if err != nil {
		return nil, err
	}
	return &networks[0], nil
}

func runCompose(w http.ResponseWriter, name []byte, composeFile []byte) {
	compose := dockerCompose{}

	if err := yaml.Unmarshal(composeFile, &compose); err != nil {
		handleError(w, err)
		return
	}

	traefikNetwork, err := getTraefikNetwork()
	if err != nil {
		handleError(w, err)
		return
	}

	ids := make([]string, len(compose.Services))
	for serviceName, service := range compose.Services {
		environments := make([]string, len(service.Environment))
		for key, value := range service.Environment {
			environments = append(environments, key+`=`+value)
		}

		id, err := docker.ContainerCreate(
			context.Background(),
			&container.Config{
				Image:  service.Image,
				Cmd:    strslice.StrSlice([]string{service.Command}),
				Labels: service.Labels,
				Env:    environments,
			},
			&container.HostConfig{
				LogConfig: container.LogConfig{Type: `json-file`, Config: map[string]string{
					`max-size`: `50m`,
				}},
				RestartPolicy:  container.RestartPolicy{Name: `on-failure`, MaximumRetryCount: 5},
				ReadonlyRootfs: true,
				Resources: container.Resources{
					CPUShares: 128,
					Memory:    134217728,
				},
				SecurityOpt: []string{`no-new-privileges`},
			},
			&network.NetworkingConfig{
				EndpointsConfig: map[string]*network.EndpointSettings{
					"default": &network.EndpointSettings{
						NetworkID: traefikNetwork.ID,
					},
				},
			},
			string(name)+`_`+serviceName,
		)

		if err != nil {
			handleError(w, err)
			return
		}

		ids = append(ids, id.ID)
	}

	jsonHttp.ResponseJSON(w, results{ids})
}

func isAuthenticated(r *http.Request) bool {
	username, password, ok := r.BasicAuth()

	if ok {
		user, ok := users[strings.ToLower(username)]

		if ok && user.password == password {
			return true
		}
	}

	return false
}

func unauthorized(w http.ResponseWriter) {
	http.Error(w, `Authentication required`, http.StatusUnauthorized)
}

// Handler for Hello request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type, Authorization`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET, POST`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	if r.Method == http.MethodOptions {
		w.Write(nil)
		return
	}

	urlPath := []byte(r.URL.Path)

	if containersRequest.Match(urlPath) && r.Method == http.MethodGet {
		listContainers(w)
	} else if isAuthenticated(r) {
		if containerRequest.Match(urlPath) && r.Method == http.MethodPost {
			if composeBody, err := readBody(r.Body); err != nil {
				handleError(w, err)
			} else {
				runCompose(w, containerRequest.FindSubmatch(urlPath)[1], composeBody)
			}
		} else if containerRequest.Match(urlPath) && r.Method == http.MethodGet {
			inspectContainer(w, containerRequest.FindSubmatch(urlPath)[1])
		} else if startRequest.Match(urlPath) && r.Method == http.MethodPost {
			startContainer(w, startRequest.FindSubmatch(urlPath)[1])
		} else if stopRequest.Match(urlPath) && r.Method == http.MethodPost {
			stopContainer(w, stopRequest.FindSubmatch(urlPath)[1])
		} else if restartRequest.Match(urlPath) && r.Method == http.MethodPost {
			restartContainer(w, restartRequest.FindSubmatch(urlPath)[1])
		} else if logRequest.Match(urlPath) && r.Method == http.MethodGet {
			logContainer(w, logRequest.FindSubmatch(urlPath)[1])
		}
	} else {
		unauthorized(w)
	}
}
<commit_msg>Update docker.go<commit_after>package docker

import (
	"bufio"
	"bytes"
	"context"
	"github.com/ViBiOh/docker-deploy/jsonHttp"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/strslice"
	"github.com/docker/docker/client"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
)

const host = `DOCKER_HOST`
const version = `DOCKER_VERSION`
const configurationFile = `./users`

var commaByte = []byte(`,`)
var splitLogs = regexp.MustCompile(`.{8}(.*?)\n`)

var containersRequest = regexp.MustCompile(`/containers/?$`)
var containerRequest = regexp.MustCompile(`/containers/([^/]+)/?$`)
var startRequest = regexp.MustCompile(`/containers/([^/]+)/start`)
var stopRequest = regexp.MustCompile(`/containers/([^/]+)/stop`)
var restartRequest = regexp.MustCompile(`/containers/([^/]+)/restart`)
var logRequest = regexp.MustCompile(`/containers/([^/]+)/logs`)

type results struct {
	Results interface{} `json:"results"`
}

type user struct {
	username string
	password string
}

type dockerCompose struct {
	Version  string
	Services map[string]struct {
		Image       string
		Command     string
		Environment map[string]string
		Labels      map[string]string
	}
}

var docker *client.Client
var users map[string]*user

func handleError(w http.ResponseWriter, err error) {
	log.Print(err)
	http.Error(w, err.Error(), http.StatusInternalServerError)
}

func readConfiguration(path string) map[string]*user {
	configFile, err := os.Open(path)
	defer configFile.Close()

	if err != nil {
		log.Print(err)
		return nil
	}

	users := make(map[string]*user)

	scanner := bufio.NewScanner(configFile)
	for scanner.Scan() {
		parts := bytes.Split(scanner.Bytes(), commaByte)
		user := user{string(parts[0]), string(parts[1])}

		users[strings.ToLower(user.username)] = &user
	}

	return users
}

func init() {
	users = readConfiguration(configurationFile)

	client, err := client.NewClient(os.Getenv(host), os.Getenv(version), nil, nil)
	if err != nil {
		log.Fatal(err)
	} else {
		docker = client
	}
}

func inspectContainer(w http.ResponseWriter, containerID []byte) {
	if container, err := docker.ContainerInspect(context.Background(), string(containerID)); err != nil {
		handleError(w, err)
	} else {
		jsonHttp.ResponseJSON(w, container)
	}
}

func startContainer(w http.ResponseWriter, containerID []byte) {
	if err := docker.ContainerStart(context.Background(), string(containerID), types.ContainerStartOptions{}); err != nil {
		handleError(w, err)
	} else {
		w.Write(nil)
	}
}

func stopContainer(w http.ResponseWriter, containerID []byte) {
	if err := docker.ContainerStop(context.Background(), string(containerID), nil); err != nil {
		handleError(w, err)
	} else {
		w.Write(nil)
	}
}

func restartContainer(w http.ResponseWriter, containerID []byte) {
	if err := docker.ContainerRestart(context.Background(), string(containerID), nil); err != nil {
		handleError(w, err)
	} else {
		w.Write(nil)
	}
}

func logContainer(w http.ResponseWriter, containerID []byte) {
	logs, err := docker.ContainerLogs(context.Background(), string(containerID), types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: false})
	if err != nil {
		handleError(w, err)
		return
	}

	defer logs.Close()

	if logLines, err := ioutil.ReadAll(logs); err != nil {
		handleError(w, err)
	} else {
		matches := splitLogs.FindAllSubmatch(logLines, -1)
		cleanLogs := make([]string, 0, len(matches))
		for _, match := range matches {
			cleanLogs = append(cleanLogs, string(match[1]))
		}

		jsonHttp.ResponseJSON(w, results{cleanLogs})
	}
}

func listContainers(w http.ResponseWriter) {
	if containers, err := docker.ContainerList(context.Background(), types.ContainerListOptions{All: true}); err != nil {
		handleError(w, err)
	} else {
		jsonHttp.ResponseJSON(w, results{containers})
	}
}

func readBody(body io.ReadCloser) ([]byte, error) {
	defer body.Close()
	return ioutil.ReadAll(body)
}

func getTraefikNetwork() (*types.NetworkResource, error) {
	args := filters.NewArgs()
	args.Add(`name`, `traefik`)

	networks, err := docker.NetworkList(context.Background(), types.NetworkListOptions{Filters: args})
	if err != nil {
		return nil, err
	}
	return &networks[0], nil
}

func runCompose(w http.ResponseWriter, name []byte, composeFile []byte) {
	compose := dockerCompose{}

	if err := yaml.Unmarshal(composeFile, &compose); err != nil {
		handleError(w, err)
		return
	}

	traefikNetwork, err := getTraefikNetwork()
	if err != nil {
		handleError(w, err)
		return
	}

	ids := make([]string, len(compose.Services))
	for serviceName, service := range compose.Services {
		environments := make([]string, len(service.Environment))
		for key, value := range service.Environment {
			environments = append(environments, key+`=`+value)
		}

		id, err := docker.ContainerCreate(
			context.Background(),
			&container.Config{
				Image:  service.Image,
				Cmd:    strslice.StrSlice([]string{service.Command}),
				Labels: service.Labels,
				Env:    environments,
			},
			&container.HostConfig{
				LogConfig: container.LogConfig{Type: `json-file`, Config: map[string]string{
					`max-size`: `50m`,
				}},
				RestartPolicy:  container.RestartPolicy{Name: `on-failure`, MaximumRetryCount: 5},
				ReadonlyRootfs: true,
				Resources: container.Resources{
					CPUShares: 128,
					Memory:    134217728,
				},
				SecurityOpt: []string{`no-new-privileges`},
			},
			&network.NetworkingConfig{
				EndpointsConfig: map[string]*network.EndpointSettings{
					"traefik": &network.EndpointSettings{
						NetworkID: traefikNetwork.ID,
					},
				},
			},
			string(name)+`_`+serviceName,
		)

		if err != nil {
			handleError(w, err)
			return
		}

		ids = append(ids, id.ID)
	}

	jsonHttp.ResponseJSON(w, results{ids})
}

func isAuthenticated(r *http.Request) bool {
	username, password, ok := r.BasicAuth()

	if ok {
		user, ok := users[strings.ToLower(username)]

		if ok && user.password == password {
			return true
		}
	}

	return false
}

func unauthorized(w http.ResponseWriter) {
	http.Error(w, `Authentication required`, http.StatusUnauthorized)
}

// Handler for Hello request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type, Authorization`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET, POST`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	if r.Method == http.MethodOptions {
		w.Write(nil)
		return
	}

	urlPath := []byte(r.URL.Path)

	if containersRequest.Match(urlPath) && r.Method == http.MethodGet {
		listContainers(w)
	} else if isAuthenticated(r) {
		if containerRequest.Match(urlPath) && r.Method == http.MethodPost {
			if composeBody, err := readBody(r.Body); err != nil {
				handleError(w, err)
			} else {
				runCompose(w, containerRequest.FindSubmatch(urlPath)[1], composeBody)
			}
		} else if containerRequest.Match(urlPath) && r.Method == http.MethodGet {
			inspectContainer(w, containerRequest.FindSubmatch(urlPath)[1])
		} else if startRequest.Match(urlPath) && r.Method == http.MethodPost {
			startContainer(w, startRequest.FindSubmatch(urlPath)[1])
		} else if stopRequest.Match(urlPath) && r.Method == http.MethodPost {
			stopContainer(w, stopRequest.FindSubmatch(urlPath)[1])
		} else if restartRequest.Match(urlPath) && r.Method == http.MethodPost {
			restartContainer(w, restartRequest.FindSubmatch(urlPath)[1])
		} else if logRequest.Match(urlPath) && r.Method == http.MethodGet {
			logContainer(w, logRequest.FindSubmatch(urlPath)[1])
		}
	} else {
		unauthorized(w)
	}
}
<|endoftext|>


<commit_before>package ae

import (
	"fmt"
	"testing"
)

func TestAE_scaleFactor(t *testing.T) {
	t.Parallel()
	tests := []struct {
		nodes int
		scale int
	}{
		{100, 1},
		{200, 2},
		{1000, 4},
		{10000, 8},
	}
	for _, tt := range tests {
		t.Run(fmt.Sprintf("%d nodes", tt.nodes), func(t *testing.T) {
			if got, want := scaleFactor(tt.nodes), tt.scale; got != want {
				t.Fatalf("got scale factor %d want %d", got, want)
			}
		})
	}
}

func TestAE_nestedPauseResume(t *testing.T) {
	t.Parallel()
	l := NewStateSyner(nil, 0, nil, nil)
	if l.Paused() != false {
		t.Fatal("syncer should be unPaused after init")
	}
	l.Pause()
	if l.Paused() != true {
		t.Fatal("syncer should be Paused after first call to Pause()")
	}
	l.Pause()
	if l.Paused() != true {
		t.Fatal("syncer should STILL be Paused after second call to Pause()")
	}
	l.Resume()
	if l.Paused() != true {
		t.Fatal("syncer should STILL be Paused after FIRST call to Resume()")
	}
	l.Resume()
	if l.Paused() != false {
		t.Fatal("syncer should NOT be Paused after SECOND call to Resume()")
	}

	defer func() {
		err := recover()
		if err == nil {
			t.Fatal("unbalanced Resume() should cause a panic()")
		}
	}()
	l.Resume()
}
<commit_msg>ae: add test for ifNotPausedRun<commit_after>package ae

import (
	"errors"
	"fmt"
	"reflect"
	"testing"
)

func TestAE_scaleFactor(t *testing.T) {
	t.Parallel()
	tests := []struct {
		nodes int
		scale int
	}{
		{100, 1},
		{200, 2},
		{1000, 4},
		{10000, 8},
	}
	for _, tt := range tests {
		t.Run(fmt.Sprintf("%d nodes", tt.nodes), func(t *testing.T) {
			if got, want := scaleFactor(tt.nodes), tt.scale; got != want {
				t.Fatalf("got scale factor %d want %d", got, want)
			}
		})
	}
}

func TestAE_nestedPauseResume(t *testing.T) {
	t.Parallel()
	l := NewStateSyner(nil, 0, nil, nil)
	if l.Paused() != false {
		t.Fatal("syncer should be unPaused after init")
	}
	l.Pause()
	if l.Paused() != true {
		t.Fatal("syncer should be Paused after first call to Pause()")
	}
	l.Pause()
	if l.Paused() != true {
		t.Fatal("syncer should STILL be Paused after second call to Pause()")
	}
	l.Resume()
	if l.Paused() != true {
		t.Fatal("syncer should STILL be Paused after FIRST call to Resume()")
	}
	l.Resume()
	if l.Paused() != false {
		t.Fatal("syncer should NOT be Paused after SECOND call to Resume()")
	}

	defer func() {
		err := recover()
		if err == nil {
			t.Fatal("unbalanced Resume() should cause a panic()")
		}
	}()
	l.Resume()
}

func TestAE_ifNotPausedRun(t *testing.T) {
	l := NewStateSyner(nil, 0, nil, nil)

	errCalled := errors.New("f called")
	f := func() error { return errCalled }

	l.Pause()
	err := l.ifNotPausedRun(f)
	if got, want := err, errPaused; !reflect.DeepEqual(got, want) {
		t.Fatalf("got error %q want %q", got, want)
	}
	l.Resume()

	err = l.ifNotPausedRun(f)
	if got, want := err, errCalled; got != want {
		t.Fatalf("got error %q want %q", got, want)
	}
}
<|endoftext|>