<commit_before>// Inferno utils/5l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
//
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
//
// 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.

package main

import (
	"cmd/internal/ld"
	"cmd/internal/obj"
	"fmt"
	"log"
)

// Reading object files.

func main() {
	linkarchinit()
	ld.Ldmain()
}

func linkarchinit() {
	ld.Thestring = "arm"
	ld.Thelinkarch = &ld.Linkarm

	ld.Thearch.Thechar = thechar
	ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
	ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
	ld.Thearch.Regsize = ld.Thelinkarch.Regsize
	ld.Thearch.Funcalign = FuncAlign
	ld.Thearch.Maxalign = MaxAlign
	ld.Thearch.Minlc = MINLC
	ld.Thearch.Dwarfregsp = DWARFREGSP

	ld.Thearch.Adddynlib = adddynlib
	ld.Thearch.Adddynrel = adddynrel
	ld.Thearch.Adddynsym = adddynsym
	ld.Thearch.Archinit = archinit
	ld.Thearch.Archreloc = archreloc
	ld.Thearch.Archrelocvariant = archrelocvariant
	ld.Thearch.Asmb = asmb
	ld.Thearch.Elfreloc1 = elfreloc1
	ld.Thearch.Elfsetupplt = elfsetupplt
	ld.Thearch.Gentext = gentext
	ld.Thearch.Machoreloc1 = machoreloc1
	ld.Thearch.Lput = ld.Lputl
	ld.Thearch.Wput = ld.Wputl
	ld.Thearch.Vput = ld.Vputl

	ld.Thearch.Linuxdynld = "/lib/ld-linux.so.3" // 2 for OABI, 3 for EABI
	ld.Thearch.Freebsddynld = "/usr/libexec/ld-elf.so.1"
	ld.Thearch.Openbsddynld = "XXX"
	ld.Thearch.Netbsddynld = "/libexec/ld.elf_so"
	ld.Thearch.Dragonflydynld = "XXX"
	ld.Thearch.Solarisdynld = "XXX"
}

func archinit() {
	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
	// Go was built; see ../../make.bash.
	if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
		ld.Linkmode = ld.LinkInternal
	}

	switch ld.HEADTYPE {
	default:
		if ld.Linkmode == ld.LinkAuto {
			ld.Linkmode = ld.LinkInternal
		}
		if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
			log.Fatalf("cannot use -linkmode=external with -H %s", ld.Headstr(int(ld.HEADTYPE)))
		}

	case ld.Hlinux,
		ld.Hfreebsd,
		ld.Hnacl,
		ld.Hdarwin:
		break
	}

	switch ld.HEADTYPE {
	default:
		ld.Diag("unknown -H option")
		ld.Errorexit()
		fallthrough

	case ld.Hplan9: /* plan 9 */
		ld.HEADR = 32

		if ld.INITTEXT == -1 {
			ld.INITTEXT = 4128
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 4096
		}

	case ld.Hlinux, /* arm elf */
		ld.Hfreebsd,
		ld.Hnetbsd:
		ld.Debug['d'] = 0
		// with dynamic linking
		ld.Elfinit()
		ld.HEADR = ld.ELFRESERVE
		if ld.INITTEXT == -1 {
			ld.INITTEXT = 0x10000 + int64(ld.HEADR)
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 4096
		}

	case ld.Hnacl:
		ld.Elfinit()
		ld.HEADR = 0x10000
		ld.Funcalign = 16
		if ld.INITTEXT == -1 {
			ld.INITTEXT = 0x20000
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 0x10000
		}

	case ld.Hdarwin: /* apple MACH */
		ld.Debug['w'] = 1 // disable DWARF generataion
		ld.Machoinit()
		ld.HEADR = ld.INITIAL_MACHO_HEADR
		if ld.INITTEXT == -1 {
			ld.INITTEXT = 4096 + int64(ld.HEADR)
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 4096
		}
	}

	if ld.INITDAT != 0 && ld.INITRND != 0 {
		fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(ld.INITDAT), uint32(ld.INITRND))
	}

	// embed goarm to runtime.goarm
	s := ld.Linklookup(ld.Ctxt, "runtime.goarm", 0)

	s.Type = ld.SRODATA
	ld.Adduint8(ld.Ctxt, s, uint8(ld.Ctxt.Goarm))
}
<commit_msg>cmd/5l: make 5l work on openbsd<commit_after>// Inferno utils/5l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
//
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
//
// 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.

package main

import (
	"cmd/internal/ld"
	"cmd/internal/obj"
	"fmt"
	"log"
)

// Reading object files.

func main() {
	linkarchinit()
	ld.Ldmain()
}

func linkarchinit() {
	ld.Thestring = "arm"
	ld.Thelinkarch = &ld.Linkarm

	ld.Thearch.Thechar = thechar
	ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
	ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
	ld.Thearch.Regsize = ld.Thelinkarch.Regsize
	ld.Thearch.Funcalign = FuncAlign
	ld.Thearch.Maxalign = MaxAlign
	ld.Thearch.Minlc = MINLC
	ld.Thearch.Dwarfregsp = DWARFREGSP

	ld.Thearch.Adddynlib = adddynlib
	ld.Thearch.Adddynrel = adddynrel
	ld.Thearch.Adddynsym = adddynsym
	ld.Thearch.Archinit = archinit
	ld.Thearch.Archreloc = archreloc
	ld.Thearch.Archrelocvariant = archrelocvariant
	ld.Thearch.Asmb = asmb
	ld.Thearch.Elfreloc1 = elfreloc1
	ld.Thearch.Elfsetupplt = elfsetupplt
	ld.Thearch.Gentext = gentext
	ld.Thearch.Machoreloc1 = machoreloc1
	ld.Thearch.Lput = ld.Lputl
	ld.Thearch.Wput = ld.Wputl
	ld.Thearch.Vput = ld.Vputl

	ld.Thearch.Linuxdynld = "/lib/ld-linux.so.3" // 2 for OABI, 3 for EABI
	ld.Thearch.Freebsddynld = "/usr/libexec/ld-elf.so.1"
	ld.Thearch.Openbsddynld = "/usr/libexec/ld.so"
	ld.Thearch.Netbsddynld = "/libexec/ld.elf_so"
	ld.Thearch.Dragonflydynld = "XXX"
	ld.Thearch.Solarisdynld = "XXX"
}

func archinit() {
	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
	// Go was built; see ../../make.bash.
	if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
		ld.Linkmode = ld.LinkInternal
	}

	switch ld.HEADTYPE {
	default:
		if ld.Linkmode == ld.LinkAuto {
			ld.Linkmode = ld.LinkInternal
		}
		if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
			log.Fatalf("cannot use -linkmode=external with -H %s", ld.Headstr(int(ld.HEADTYPE)))
		}

	case ld.Hlinux,
		ld.Hfreebsd,
		ld.Hnacl,
		ld.Hdarwin:
		break
	}

	switch ld.HEADTYPE {
	default:
		ld.Diag("unknown -H option")
		ld.Errorexit()
		fallthrough

	case ld.Hplan9: /* plan 9 */
		ld.HEADR = 32

		if ld.INITTEXT == -1 {
			ld.INITTEXT = 4128
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 4096
		}

	case ld.Hlinux, /* arm elf */
		ld.Hfreebsd,
		ld.Hnetbsd,
		ld.Hopenbsd:
		ld.Debug['d'] = 0
		// with dynamic linking
		ld.Elfinit()
		ld.HEADR = ld.ELFRESERVE
		if ld.INITTEXT == -1 {
			ld.INITTEXT = 0x10000 + int64(ld.HEADR)
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 4096
		}

	case ld.Hnacl:
		ld.Elfinit()
		ld.HEADR = 0x10000
		ld.Funcalign = 16
		if ld.INITTEXT == -1 {
			ld.INITTEXT = 0x20000
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 0x10000
		}

	case ld.Hdarwin: /* apple MACH */
		ld.Debug['w'] = 1 // disable DWARF generataion
		ld.Machoinit()
		ld.HEADR = ld.INITIAL_MACHO_HEADR
		if ld.INITTEXT == -1 {
			ld.INITTEXT = 4096 + int64(ld.HEADR)
		}
		if ld.INITDAT == -1 {
			ld.INITDAT = 0
		}
		if ld.INITRND == -1 {
			ld.INITRND = 4096
		}
	}

	if ld.INITDAT != 0 && ld.INITRND != 0 {
		fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(ld.INITDAT), uint32(ld.INITRND))
	}

	// embed goarm to runtime.goarm
	s := ld.Linklookup(ld.Ctxt, "runtime.goarm", 0)

	s.Type = ld.SRODATA
	ld.Adduint8(ld.Ctxt, s, uint8(ld.Ctxt.Goarm))
}
<|endoftext|>


<commit_before>package management

import (
	"fmt"
	"time"
)

// Content Field Types
type FieldType string

// Content Field Type constants
const (
	// ShortText fields do not support ordering or strict equality. 1 to 256 characters.
	ShortText FieldType = "Symbol"
	// LongText can be a maximum length of 50,000 characters
	LongText = "Text"
	Integer  = "Integer"
	Number   = "Number"
	Boolean  = "Boolean"
	// Date must be ISO8601 formatted and do not require a time portion
	Date     = "Date"
	Location = "Location"
	Object   = "Object"
	LinkType = "Link"
	Array    = "Array"
)

// Field describes a single allowed field value of an an entry.
// Each field type corresponds to a JSON type, though there are
// more field types than JSON types.
type Field struct {
	ID       string    `json:"id,omitempty"`
	Name     string    `json:"name,omitempty"`
	LinkType string    `json:"linkType,omitempty"`
	Type     FieldType `json:"type,omitempty"`

	Localized   bool              `json:"localized,omitempty"`
	Required    bool              `json:"required,omitempty"`
	Validations []FieldValidation `json:"validations,omitempty"`
	Disabled    bool              `json:"disabled,omitempty"`

	// Omitted fields will stil be present in CMA APIs but omitted from CDA and CPA APIs
	Omitted bool `json:"omitted,omitempty"`
}

// FieldValidation describes validation rules associated with a field, if any.
type FieldValidation struct {
	Size                 *SizeFieldValidation      `json:"size,omitempty"`
	Range                *RangeFieldValidation     `json:"range,omitempty"`
	DateRange            *DateRangeFieldValidation `json:"dateRange,omitempty"`
	RegularExpression    *RegExFieldValidation     `json:"regexp,omitempty"`
	AssetImageValidation *AssetImageValidation     `json:"assetImageDimensions,omitempty"`

	LinkMIMETypeGroup []string      `json:"linkMimetypeGroup,omitempty"`
	LinkContentTypes  []string      `json:"linkContentType,omitempty"`
	In                []interface{} `json:"in,omitempty"`
	Message           *string       `json:"message,omitempty"`
}

// RegExFieldValidation permits validation with regular expression.
type RegExFieldValidation struct {
	Pattern string `json:"pattern"`
}

// RangeFieldValidation takes optional min and max parameters and validates the range
// of a value.
type RangeFieldValidation struct {
	Min int `json:"min,omitempty"`
	Max int `json:"max,omitempty"`
}

// SizeFieldValidation permits validation with size. You can specify
// either minimum size, maximum size, or both.
type SizeFieldValidation struct {
	Min *float64 `json:"min,omitempty"`
	Max *float64 `json:"max,omitempty"`
}

// AssetImageValidation permits asset validation around size
type AssetImageValidation struct {
	Width  *SizeFieldValidation `json:"width,omitempty"`
	Height *SizeFieldValidation `json:"height,omitempty"`
}

// DateRangeFieldValidation permits validation with date ranges. You can specify
// either minimum date, maximum date, or both.
type DateRangeFieldValidation struct {
	Min *time.Time `json:"min,omitempty"`
	Max *time.Time `json:"max,omitempty"`
}

// ContentType are schemas that define the fields of entries.
// Every entry can only contain values in the fields defined by
// its content type, and the values of those fields must match
// the data type defined in the content type. There is a limit
// of 50 fields per content type.
type ContentType struct {
	System `json:"sys"`

	Name         string  `json:"name"`
	Description  string  `json:"description,omitempty"`
	DisplayField string  `json:"displayField,omitempty"`
	Fields       []Field `json:"fields"`
}

// Validate will validate the content type. An error is returned if the content
// type is not  valid.
func (t *ContentType) Validate() error {
	if len(t.Name) == 0 {
		return fmt.Errorf("Content type name cannot be empty")
	}

	if t.Space == nil || t.Space.ID == "" {
		return fmt.Errorf("Locale must specify valid System.Space.ID!")
	}

	if len(t.ID) == 0 {
		return fmt.Errorf("Content type must specify an identifier!")
	}

	return nil
}

// FetchContentTypes returns all content types for a given space. You can filter
// this further by toggling the published flag
func (c *Client) FetchContentTypes(spaceID string, published bool, limit int, offset int) (contentTypes []*ContentType, pagination *Pagination, err error) {
	if spaceID == "" {
		return nil, nil, fmt.Errorf("FetchContentTypes failed. Space identifier is not valid!")
	}

	if limit <= 0 {
		return nil, nil, fmt.Errorf("FetchContentTypes failed. Limit must be greater than 0")
	}

	if limit > 100 {
		limit = 100
	}

	c.rl.Wait()

	type contentTypesResponse struct {
		*Pagination
		Items []*ContentType `json:"items"`
	}

	results := new(contentTypesResponse)
	contentfulError := new(ContentfulError)
	path := func() string {
		if published {
			return fmt.Sprintf("spaces/%v/public/content_types", spaceID)
		}

		return fmt.Sprintf("spaces/%v/content_types", spaceID)
	}

	req, err := c.sling.New().
		Get(path()).
		Request()

	if err != nil {
		return
	}

	// Add query parameters
	q := req.URL.Query()
	q.Set("skip", fmt.Sprintf("%v", offset))
	q.Set("limit", fmt.Sprintf("%v", limit))
	req.URL.RawQuery = q.Encode()

	_, err = c.sling.Do(req, results, contentfulError)

	return results.Items, results.Pagination, handleError(err, contentfulError)

}

// CreateContentType will create a content type. It's recommended that you
// control the ID of the created content type and associated fields.
func (c *Client) CreateContentType(contentType *ContentType) (created *ContentType, err error) {
	if contentType == nil {
		return nil, fmt.Errorf("CreateContentType failed. Type argument was nil!")
	}

	if err = contentType.Validate(); err != nil {
		return
	}

	c.rl.Wait()

	created = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v", contentType.Space.ID, contentType.ID)
	_, err = c.sling.New().
		Put(path).
		Set("X-Contentful-Version", fmt.Sprintf("%v", contentType.Version)).
		BodyJSON(contentType).
		Receive(created, contentfulError)

	return created, handleError(err, contentfulError)
}

// FetchContentType will return a content type for the specified space and
// content type identifier.
func (c *Client) FetchContentType(spaceID string, contentTypeID string) (contentType *ContentType, err error) {
	if spaceID == "" || contentTypeID == "" {
		err = fmt.Errorf("FetchContentType failed. Invalid spaceID or contentTypeID.")
		return
	}

	c.rl.Wait()

	contentType = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v", spaceID, contentTypeID)
	_, err = c.sling.New().Get(path).Receive(contentType, contentfulError)

	return contentType, handleError(err, contentfulError)
}

// UpdateContentType will update the content type with the specified changes.
func (c *Client) UpdateContentType(contentType *ContentType) (updated *ContentType, err error) {
	return c.CreateContentType(contentType)
}

// DeleteContentType will delete a content type. Before you can delete a content
// type you need to deactivate it.
func (c *Client) DeleteContentType(spaceID string, contentTypeID string) (err error) {
	c.rl.Wait()

	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v", spaceID, contentTypeID)
	_, err = c.sling.New().
		Delete(path).
		Receive(nil, contentfulError)

	return handleError(err, contentfulError)
}

// ActivateContentType makes the content type available for creating entries
func (c *Client) ActivateContentType(contentType *ContentType) (activated *ContentType, err error) {
	if contentType == nil {
		return nil, fmt.Errorf("CreateContentType failed. Type argument was nil!")
	}

	if err = contentType.Validate(); err != nil {
		return
	}

	c.rl.Wait()

	activated = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v/published", contentType.Space.ID, contentType.ID)
	_, err = c.sling.New().
		Put(path).
		Set("X-Contentful-Version", fmt.Sprintf("%v", contentType.Version)).
		Receive(activated, contentfulError)

	return activated, handleError(err, contentfulError)
}

// DeactivateContentType removes the availability for creating entries
func (c *Client) DeactivateContentType(contentType *ContentType) (deactivated *ContentType, err error) {
	if contentType == nil {
		return nil, fmt.Errorf("CreateContentType failed. Type argument was nil!")
	}

	if err = contentType.Validate(); err != nil {
		return
	}

	c.rl.Wait()

	deactivated = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v/published", contentType.Space.ID, contentType.ID)
	_, err = c.sling.New().
		Delete(path).
		Set("X-Contentful-Version", fmt.Sprintf("%v", contentType.Version)).
		Receive(deactivated, contentfulError)

	return deactivated, handleError(err, contentfulError)
}
<commit_msg>Removing pointer value for message<commit_after>package management

import (
	"fmt"
	"time"
)

// Content Field Types
type FieldType string

// Content Field Type constants
const (
	// ShortText fields do not support ordering or strict equality. 1 to 256 characters.
	ShortText FieldType = "Symbol"
	// LongText can be a maximum length of 50,000 characters
	LongText = "Text"
	Integer  = "Integer"
	Number   = "Number"
	Boolean  = "Boolean"
	// Date must be ISO8601 formatted and do not require a time portion
	Date     = "Date"
	Location = "Location"
	Object   = "Object"
	LinkType = "Link"
	Array    = "Array"
)

// Field describes a single allowed field value of an an entry.
// Each field type corresponds to a JSON type, though there are
// more field types than JSON types.
type Field struct {
	ID       string    `json:"id,omitempty"`
	Name     string    `json:"name,omitempty"`
	LinkType string    `json:"linkType,omitempty"`
	Type     FieldType `json:"type,omitempty"`

	Items *Field `json:"items,omitempty"`

	Localized   bool              `json:"localized,omitempty"`
	Required    bool              `json:"required,omitempty"`
	Validations []FieldValidation `json:"validations,omitempty"`
	Disabled    bool              `json:"disabled,omitempty"`

	// Omitted fields will stil be present in CMA APIs but omitted from CDA and CPA APIs
	Omitted bool `json:"omitted,omitempty"`
}

// FieldValidation describes validation rules associated with a field, if any.
type FieldValidation struct {
	Size                 *SizeFieldValidation      `json:"size,omitempty"`
	Range                *RangeFieldValidation     `json:"range,omitempty"`
	DateRange            *DateRangeFieldValidation `json:"dateRange,omitempty"`
	RegularExpression    *RegExFieldValidation     `json:"regexp,omitempty"`
	AssetImageValidation *AssetImageValidation     `json:"assetImageDimensions,omitempty"`

	LinkMIMETypeGroup []string      `json:"linkMimetypeGroup,omitempty"`
	LinkContentTypes  []string      `json:"linkContentType,omitempty"`
	In                []interface{} `json:"in,omitempty"`
	Message           string        `json:"message,omitempty"`
}

// RegExFieldValidation permits validation with regular expression.
type RegExFieldValidation struct {
	Pattern string `json:"pattern"`
}

// RangeFieldValidation takes optional min and max parameters and validates the range
// of a value.
type RangeFieldValidation struct {
	Min int `json:"min,omitempty"`
	Max int `json:"max,omitempty"`
}

// SizeFieldValidation permits validation with size. You can specify
// either minimum size, maximum size, or both.
type SizeFieldValidation struct {
	Min float64 `json:"min,omitempty"`
	Max float64 `json:"max,omitempty"`
}

// AssetImageValidation permits asset validation around size
type AssetImageValidation struct {
	Width  *SizeFieldValidation `json:"width,omitempty"`
	Height *SizeFieldValidation `json:"height,omitempty"`
}

// DateRangeFieldValidation permits validation with date ranges. You can specify
// either minimum date, maximum date, or both.
type DateRangeFieldValidation struct {
	Min *time.Time `json:"min,omitempty"`
	Max *time.Time `json:"max,omitempty"`
}

// ContentType are schemas that define the fields of entries.
// Every entry can only contain values in the fields defined by
// its content type, and the values of those fields must match
// the data type defined in the content type. There is a limit
// of 50 fields per content type.
type ContentType struct {
	System `json:"sys"`

	Name         string  `json:"name"`
	Description  string  `json:"description,omitempty"`
	DisplayField string  `json:"displayField,omitempty"`
	Fields       []Field `json:"fields"`
}

// Validate will validate the content type. An error is returned if the content
// type is not  valid.
func (t *ContentType) Validate() error {
	if len(t.Name) == 0 {
		return fmt.Errorf("Content type name cannot be empty")
	}

	if t.Space == nil || t.Space.ID == "" {
		return fmt.Errorf("Locale must specify valid System.Space.ID!")
	}

	if len(t.ID) == 0 {
		return fmt.Errorf("Content type must specify an identifier!")
	}

	return nil
}

// FetchContentTypes returns all content types for a given space. You can filter
// this further by toggling the published flag
func (c *Client) FetchContentTypes(spaceID string, published bool, limit int, offset int) (contentTypes []*ContentType, pagination *Pagination, err error) {
	if spaceID == "" {
		return nil, nil, fmt.Errorf("FetchContentTypes failed. Space identifier is not valid!")
	}

	if limit <= 0 {
		return nil, nil, fmt.Errorf("FetchContentTypes failed. Limit must be greater than 0")
	}

	if limit > 100 {
		limit = 100
	}

	c.rl.Wait()

	type contentTypesResponse struct {
		*Pagination
		Items []*ContentType `json:"items"`
	}

	results := new(contentTypesResponse)
	contentfulError := new(ContentfulError)
	path := func() string {
		if published {
			return fmt.Sprintf("spaces/%v/public/content_types", spaceID)
		}

		return fmt.Sprintf("spaces/%v/content_types", spaceID)
	}

	req, err := c.sling.New().
		Get(path()).
		Request()

	if err != nil {
		return
	}

	// Add query parameters
	q := req.URL.Query()
	q.Set("skip", fmt.Sprintf("%v", offset))
	q.Set("limit", fmt.Sprintf("%v", limit))
	req.URL.RawQuery = q.Encode()

	_, err = c.sling.Do(req, results, contentfulError)

	return results.Items, results.Pagination, handleError(err, contentfulError)

}

// CreateContentType will create a content type. It's recommended that you
// control the ID of the created content type and associated fields.
func (c *Client) CreateContentType(contentType *ContentType) (created *ContentType, err error) {
	if contentType == nil {
		return nil, fmt.Errorf("CreateContentType failed. Type argument was nil!")
	}

	if err = contentType.Validate(); err != nil {
		return
	}

	c.rl.Wait()

	created = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v", contentType.Space.ID, contentType.ID)
	_, err = c.sling.New().
		Put(path).
		Set("X-Contentful-Version", fmt.Sprintf("%v", contentType.Version)).
		BodyJSON(contentType).
		Receive(created, contentfulError)

	return created, handleError(err, contentfulError)
}

// FetchContentType will return a content type for the specified space and
// content type identifier.
func (c *Client) FetchContentType(spaceID string, contentTypeID string) (contentType *ContentType, err error) {
	if spaceID == "" || contentTypeID == "" {
		err = fmt.Errorf("FetchContentType failed. Invalid spaceID or contentTypeID.")
		return
	}

	c.rl.Wait()

	contentType = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v", spaceID, contentTypeID)
	_, err = c.sling.New().Get(path).Receive(contentType, contentfulError)

	return contentType, handleError(err, contentfulError)
}

// UpdateContentType will update the content type with the specified changes.
func (c *Client) UpdateContentType(contentType *ContentType) (updated *ContentType, err error) {
	return c.CreateContentType(contentType)
}

// DeleteContentType will delete a content type. Before you can delete a content
// type you need to deactivate it.
func (c *Client) DeleteContentType(spaceID string, contentTypeID string) (err error) {
	c.rl.Wait()

	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v", spaceID, contentTypeID)
	_, err = c.sling.New().
		Delete(path).
		Receive(nil, contentfulError)

	return handleError(err, contentfulError)
}

// ActivateContentType makes the content type available for creating entries
func (c *Client) ActivateContentType(contentType *ContentType) (activated *ContentType, err error) {
	if contentType == nil {
		return nil, fmt.Errorf("CreateContentType failed. Type argument was nil!")
	}

	if err = contentType.Validate(); err != nil {
		return
	}

	c.rl.Wait()

	activated = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v/published", contentType.Space.ID, contentType.ID)
	_, err = c.sling.New().
		Put(path).
		Set("X-Contentful-Version", fmt.Sprintf("%v", contentType.Version)).
		Receive(activated, contentfulError)

	return activated, handleError(err, contentfulError)
}

// DeactivateContentType removes the availability for creating entries
func (c *Client) DeactivateContentType(contentType *ContentType) (deactivated *ContentType, err error) {
	if contentType == nil {
		return nil, fmt.Errorf("CreateContentType failed. Type argument was nil!")
	}

	if err = contentType.Validate(); err != nil {
		return
	}

	c.rl.Wait()

	deactivated = new(ContentType)
	contentfulError := new(ContentfulError)
	path := fmt.Sprintf("spaces/%v/content_types/%v/published", contentType.Space.ID, contentType.ID)
	_, err = c.sling.New().
		Delete(path).
		Set("X-Contentful-Version", fmt.Sprintf("%v", contentType.Version)).
		Receive(deactivated, contentfulError)

	return deactivated, handleError(err, contentfulError)
}
<|endoftext|>


<commit_before>package lua

import (
	"errors"
	"fmt"
	"unsafe"
)

var lua_tointegerx = luaDLL.NewProc("lua_tointegerx")

func (this Lua) ToInteger(index int) (int, error) {
	var issucceeded uintptr
	value, _, _ := lua_tointegerx.Call(this.State(), uintptr(index),
		uintptr(unsafe.Pointer(&issucceeded)))
	if issucceeded != 0 {
		return int(value), nil
	} else {
		return 0, errors.New("ToInteger: the value in not integer on the stack")
	}
}

var lua_tolstring = luaDLL.NewProc("lua_tolstring")

func (this Lua) ToAnsiString(index int) []byte {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	if length <= 0 {
		return []byte{}
	} else {
		return CGoBytes(p, length)
	}
}

func (this Lua) ToString(index int) (string, error) {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	return CGoStringN(p, length), nil
}

var lua_touserdata = luaDLL.NewProc("lua_touserdata")

func (this Lua) ToUserData(index int) unsafe.Pointer {
	rv, _, _ := lua_touserdata.Call(this.State(), uintptr(index))
	return unsafe.Pointer(rv)
}

var lua_toboolean = luaDLL.NewProc("lua_toboolean")

func (this Lua) ToBool(index int) bool {
	rv, _, _ := lua_toboolean.Call(this.State(), uintptr(index))
	return rv != 0
}

type TString struct {
	Value []byte
}

func (this *TString) String() (string, error) {
	if len(this.Value) <= 0 {
		return "", nil
	} else {
		return string(this.Value), nil
	}
}

func (this *TString) Push(L Lua) int {
	L.PushAnsiString(this.Value)
	return 1
}

var lua_tocfunction = luaDLL.NewProc("lua_tocfunction")

func (this *Lua) ToCFunction(index int) uintptr {
	rc, _, _ := lua_tocfunction.Call(this.State(), uintptr(index))
	return rc
}

type TFunction struct {
	IsCFunc bool
	Address uintptr
	Chank   []byte
}

func (this TFunction) Push(L Lua) int {
	if this.IsCFunc {
		// CFunction
		L.PushCFunction(this.Address)
	} else {
		// LuaFunction
		err := L.LoadBufferX("(anonymous)", this.Chank, "b")
		if err != nil {
			return 0
		}
	}
	return 1
}

type TLightUserData struct {
	Data unsafe.Pointer
}

func (this TLightUserData) Push(L Lua) int {
	L.PushLightUserData(this.Data)
	return 1
}

type TFullUserData []byte

func (this TFullUserData) Push(L Lua) int {
	size := len([]byte(this))
	p := L.NewUserData(uintptr(size))
	for i := 0; i < size; i++ {
		*(*byte)(unsafe.Pointer(uintptr(p) + uintptr(i))) = this[i]
	}
	return 1
}

var lua_next = luaDLL.NewProc("lua_next")

func (this Lua) Next(index int) int {
	rc, _, _ := lua_next.Call(this.State(), uintptr(index))
	return int(rc)
}

var lua_rawlen = luaDLL.NewProc("lua_rawlen")

func (this Lua) RawLen(index int) uintptr {
	size, _, _ := lua_rawlen.Call(this.State(), uintptr(index))
	return size
}

type MetaTableOwner struct {
	Body interface{}
	Meta *map[string]interface{}
}

func (this *MetaTableOwner) Push(L Lua) int {
	L.Push(this.Body)
	L.Push(this.Meta)
	L.SetMetaTable(-2)
	return 1
}

func (this Lua) ToTable(index int) (*map[string]interface{}, error) {
	top := this.GetTop()
	defer this.SetTop(top)
	table := make(map[string]interface{})
	this.PushNil()
	if index < 0 {
		index--
	}
	for this.Next(index) != 0 {
		key, keyErr := this.ToSomething(-2)
		if keyErr == nil {
			val, valErr := this.ToSomething(-1)
			if valErr != nil {
				return nil, valErr
			} else {
				switch t := key.(type) {
				case string:
					table[t] = val
				case int:
					table[fmt.Sprintf("%d", t)] = val
				case nil:
					table[""] = val
				}
			}
		}
		this.Pop(1)
	}
	return &table, nil
}

func (this Lua) ToSomething(index int) (interface{}, error) {
	var result interface{}
	var err error = nil
	seek_metatable := false

	switch this.GetType(index) {
	case LUA_TBOOLEAN:
		result = this.ToBool(index)
	case LUA_TFUNCTION:
		if p := this.ToCFunction(index); p != 0 {
			// CFunction
			result = TFunction{IsCFunc: true, Address: p}
		} else {
			// LuaFunction
			result = TFunction{IsCFunc: false, Chank: this.Dump()}
		}
	case LUA_TLIGHTUSERDATA:
		result = &TLightUserData{this.ToUserData(index)}
		seek_metatable = true
	case LUA_TNIL:
		result = nil
	case LUA_TNUMBER:
		result, err = this.ToInteger(index)
	case LUA_TSTRING:
		result = TString{this.ToAnsiString(index)}
	case LUA_TTABLE:
		result, err = this.ToTable(index)
		seek_metatable = true
	case LUA_TUSERDATA:
		size := this.RawLen(index)
		ptr := this.ToUserData(index)
		result = TFullUserData(CGoBytes(uintptr(ptr), uintptr(size)))
		seek_metatable = true
	default:
		return nil, errors.New("lua.ToSomeThing: Not supported type found.")
	}
	if err != nil {
		return nil, err
	}
	if seek_metatable && this.GetMetaTable(index) {
		metatable, err := this.ToTable(-1)
		defer this.Pop(1)
		if err != nil {
			return nil, err
		}
		result = &MetaTableOwner{Body: result, Meta: metatable}
	}
	return result, nil
}
<commit_msg>Fixed: virtual table did not support lua.TString as key<commit_after>package lua

import (
	"errors"
	"fmt"
	"unsafe"
)

var lua_tointegerx = luaDLL.NewProc("lua_tointegerx")

func (this Lua) ToInteger(index int) (int, error) {
	var issucceeded uintptr
	value, _, _ := lua_tointegerx.Call(this.State(), uintptr(index),
		uintptr(unsafe.Pointer(&issucceeded)))
	if issucceeded != 0 {
		return int(value), nil
	} else {
		return 0, errors.New("ToInteger: the value in not integer on the stack")
	}
}

var lua_tolstring = luaDLL.NewProc("lua_tolstring")

func (this Lua) ToAnsiString(index int) []byte {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	if length <= 0 {
		return []byte{}
	} else {
		return CGoBytes(p, length)
	}
}

func (this Lua) ToString(index int) (string, error) {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	return CGoStringN(p, length), nil
}

var lua_touserdata = luaDLL.NewProc("lua_touserdata")

func (this Lua) ToUserData(index int) unsafe.Pointer {
	rv, _, _ := lua_touserdata.Call(this.State(), uintptr(index))
	return unsafe.Pointer(rv)
}

var lua_toboolean = luaDLL.NewProc("lua_toboolean")

func (this Lua) ToBool(index int) bool {
	rv, _, _ := lua_toboolean.Call(this.State(), uintptr(index))
	return rv != 0
}

type TString struct {
	Value []byte
}

func (this *TString) String() (string, error) {
	if len(this.Value) <= 0 {
		return "", nil
	} else {
		return string(this.Value), nil
	}
}

func (this TString) Push(L Lua) int {
	L.PushAnsiString(this.Value)
	return 1
}

var lua_tocfunction = luaDLL.NewProc("lua_tocfunction")

func (this *Lua) ToCFunction(index int) uintptr {
	rc, _, _ := lua_tocfunction.Call(this.State(), uintptr(index))
	return rc
}

type TFunction struct {
	IsCFunc bool
	Address uintptr
	Chank   []byte
}

func (this TFunction) Push(L Lua) int {
	if this.IsCFunc {
		// CFunction
		L.PushCFunction(this.Address)
	} else {
		// LuaFunction
		err := L.LoadBufferX("(anonymous)", this.Chank, "b")
		if err != nil {
			return 0
		}
	}
	return 1
}

type TLightUserData struct {
	Data unsafe.Pointer
}

func (this TLightUserData) Push(L Lua) int {
	L.PushLightUserData(this.Data)
	return 1
}

type TFullUserData []byte

func (this TFullUserData) Push(L Lua) int {
	size := len([]byte(this))
	p := L.NewUserData(uintptr(size))
	for i := 0; i < size; i++ {
		*(*byte)(unsafe.Pointer(uintptr(p) + uintptr(i))) = this[i]
	}
	return 1
}

var lua_next = luaDLL.NewProc("lua_next")

func (this Lua) Next(index int) int {
	rc, _, _ := lua_next.Call(this.State(), uintptr(index))
	return int(rc)
}

var lua_rawlen = luaDLL.NewProc("lua_rawlen")

func (this Lua) RawLen(index int) uintptr {
	size, _, _ := lua_rawlen.Call(this.State(), uintptr(index))
	return size
}

type MetaTableOwner struct {
	Body interface{}
	Meta *map[string]interface{}
}

func (this *MetaTableOwner) Push(L Lua) int {
	L.Push(this.Body)
	L.Push(this.Meta)
	L.SetMetaTable(-2)
	return 1
}

func (this Lua) ToTable(index int) (*map[string]interface{}, error) {
	top := this.GetTop()
	defer this.SetTop(top)
	table := make(map[string]interface{})
	this.PushNil()
	if index < 0 {
		index--
	}
	for this.Next(index) != 0 {
		key, keyErr := this.ToSomething(-2)
		if keyErr == nil {
			val, valErr := this.ToSomething(-1)
			if valErr != nil {
				return nil, valErr
			} else {
				switch t := key.(type) {
				case TString:
					table[string(t.Value)] = val
				case string:
					table[t] = val
				case int:
					table[fmt.Sprintf("%d", t)] = val
				case nil:
					table[""] = val
				}
			}
		}
		this.Pop(1)
	}
	return &table, nil
}

func (this Lua) ToSomething(index int) (interface{}, error) {
	var result interface{}
	var err error = nil
	seek_metatable := false

	switch this.GetType(index) {
	case LUA_TBOOLEAN:
		result = this.ToBool(index)
	case LUA_TFUNCTION:
		if p := this.ToCFunction(index); p != 0 {
			// CFunction
			result = TFunction{IsCFunc: true, Address: p}
		} else {
			// LuaFunction
			result = TFunction{IsCFunc: false, Chank: this.Dump()}
		}
	case LUA_TLIGHTUSERDATA:
		result = &TLightUserData{this.ToUserData(index)}
		seek_metatable = true
	case LUA_TNIL:
		result = nil
	case LUA_TNUMBER:
		result, err = this.ToInteger(index)
	case LUA_TSTRING:
		result = TString{this.ToAnsiString(index)}
	case LUA_TTABLE:
		result, err = this.ToTable(index)
		seek_metatable = true
	case LUA_TUSERDATA:
		size := this.RawLen(index)
		ptr := this.ToUserData(index)
		result = TFullUserData(CGoBytes(uintptr(ptr), uintptr(size)))
		seek_metatable = true
	default:
		return nil, errors.New("lua.ToSomeThing: Not supported type found.")
	}
	if err != nil {
		return nil, err
	}
	if seek_metatable && this.GetMetaTable(index) {
		metatable, err := this.ToTable(-1)
		defer this.Pop(1)
		if err != nil {
			return nil, err
		}
		result = &MetaTableOwner{Body: result, Meta: metatable}
	}
	return result, nil
}
<|endoftext|>


<commit_before>package main

import(
  "fmt"
  "os"
  "io/ioutil"
  "path/filepath"
  "os/exec"
  "strings"
)

const(
  LUNCHY_VERSION = "0.1.0"
)

func printUsage() {
  fmt.Printf("Lunchy %s, the friendly launchctl wrapper\n", LUNCHY_VERSION)
  fmt.Println("Usage: lunchy [start|stop|restart|list|status|install|show|edit] [options]")
}

func findPlists(path string) []string {
  result := []string{}
  files, err := ioutil.ReadDir(path)

  if err != nil {
    return result
  }

  for _, file := range files {
    if !file.IsDir() {
      if (filepath.Ext(file.Name())) == ".plist" {
        name := strings.Replace(file.Name(), ".plist", "", -1)
        result = append(result, name)
      }
    }
  }

  return result
}

func getPlists() []string {
  path := fmt.Sprintf("%s/Library/LaunchAgents", os.Getenv("HOME"))
  files := findPlists(path)

  return files
}

func sliceIncludes(slice []string, match string) bool {
  for _, val := range slice {
    if val == match {
      return true
    }
  }

  return false
}

func printList() {
  for _, file := range getPlists() {
    fmt.Println(file)
  }
}

func printStatus(args []string) {
  out, err := exec.Command("launchctl", "list").Output()

  if err != nil {
    fmt.Println("Failed to execute", err)
    os.Exit(1)
  }

  pattern := ""

  if len(args) == 3 {
    pattern = args[2]
  }

  installed := getPlists()
  lines := strings.Split(strings.TrimSpace(string(out)), "\n")

  for _, line := range lines {
    chunks := strings.Split(line, "\t")

    if len(pattern) > 0 {
      if strings.Index(chunks[2], pattern) != -1 {
        if sliceIncludes(installed, chunks[2]) {
          fmt.Println(line)
        }
      }
    } else {
      if sliceIncludes(installed, chunks[2]) {
        fmt.Println(line)
      }
    }
  }
}

func startDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("Pattern required")
    os.Exit(1)
  }

  pattern := args[2]

  for _, name := range getPlists() {
    if strings.Index(name, pattern) != -1 {
      startDaemon(name)
    }
  }
}

func startDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "load", path).Output()

  if err != nil {
    fmt.Println("Failed to load", name, ":", err)
    return
  }

  fmt.Println("started", name)
}

func stopDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("Pattern required")
    os.Exit(1)
  }

  pattern := args[2]

  for _, name := range getPlists() {
    if strings.Index(name, pattern) != -1 {
      stopDaemon(name)
    }
  }
}

func stopDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "unload", path).Output()

  if err != nil {
    fmt.Println("Failed to unload", name, ":", err)
    return
  }

  fmt.Println("stopped", name)
}

func restartDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("Pattern required")
    os.Exit(1)
  }

  pattern := args[2]

  for _, name := range getPlists() {
    if strings.Index(name, pattern) != -1 {
      stopDaemon(name)
      startDaemon(name)
    }
  }
}

func main() {
  args := os.Args

  if (len(args) == 1) {
    printUsage()
    os.Exit(1)
  }

  switch args[1] {
  default:
    printUsage()
    os.Exit(1)
  case "list":
    printList()
    return
  case "status":
    printStatus(args)
    return
  case "start":
    startDaemons(args)
    return
  case "stop":
    stopDaemons(args)
    return
  case "restart":
    restartDaemons(args)
    return
  }
}<commit_msg>Add ls alias to list<commit_after>package main

import(
  "fmt"
  "os"
  "io/ioutil"
  "path/filepath"
  "os/exec"
  "strings"
)

const(
  LUNCHY_VERSION = "0.1.0"
)

func printUsage() {
  fmt.Printf("Lunchy %s, the friendly launchctl wrapper\n", LUNCHY_VERSION)
  fmt.Println("Usage: lunchy [start|stop|restart|list|status|install|show|edit] [options]")
}

func findPlists(path string) []string {
  result := []string{}
  files, err := ioutil.ReadDir(path)

  if err != nil {
    return result
  }

  for _, file := range files {
    if !file.IsDir() {
      if (filepath.Ext(file.Name())) == ".plist" {
        name := strings.Replace(file.Name(), ".plist", "", -1)
        result = append(result, name)
      }
    }
  }

  return result
}

func getPlists() []string {
  path := fmt.Sprintf("%s/Library/LaunchAgents", os.Getenv("HOME"))
  files := findPlists(path)

  return files
}

func sliceIncludes(slice []string, match string) bool {
  for _, val := range slice {
    if val == match {
      return true
    }
  }

  return false
}

func printList() {
  for _, file := range getPlists() {
    fmt.Println(file)
  }
}

func printStatus(args []string) {
  out, err := exec.Command("launchctl", "list").Output()

  if err != nil {
    fmt.Println("Failed to execute", err)
    os.Exit(1)
  }

  pattern := ""

  if len(args) == 3 {
    pattern = args[2]
  }

  installed := getPlists()
  lines := strings.Split(strings.TrimSpace(string(out)), "\n")

  for _, line := range lines {
    chunks := strings.Split(line, "\t")

    if len(pattern) > 0 {
      if strings.Index(chunks[2], pattern) != -1 {
        if sliceIncludes(installed, chunks[2]) {
          fmt.Println(line)
        }
      }
    } else {
      if sliceIncludes(installed, chunks[2]) {
        fmt.Println(line)
      }
    }
  }
}

func startDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("Pattern required")
    os.Exit(1)
  }

  pattern := args[2]

  for _, name := range getPlists() {
    if strings.Index(name, pattern) != -1 {
      startDaemon(name)
    }
  }
}

func startDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "load", path).Output()

  if err != nil {
    fmt.Println("Failed to load", name, ":", err)
    return
  }

  fmt.Println("started", name)
}

func stopDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("Pattern required")
    os.Exit(1)
  }

  pattern := args[2]

  for _, name := range getPlists() {
    if strings.Index(name, pattern) != -1 {
      stopDaemon(name)
    }
  }
}

func stopDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "unload", path).Output()

  if err != nil {
    fmt.Println("Failed to unload", name, ":", err)
    return
  }

  fmt.Println("stopped", name)
}

func restartDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("Pattern required")
    os.Exit(1)
  }

  pattern := args[2]

  for _, name := range getPlists() {
    if strings.Index(name, pattern) != -1 {
      stopDaemon(name)
      startDaemon(name)
    }
  }
}

func main() {
  args := os.Args

  if (len(args) == 1) {
    printUsage()
    os.Exit(1)
  }

  switch args[1] {
  default:
    printUsage()
    os.Exit(1)
  case "list", "ls":
    printList()
    return
  case "status":
    printStatus(args)
    return
  case "start":
    startDaemons(args)
    return
  case "stop":
    stopDaemons(args)
    return
  case "restart":
    restartDaemons(args)
    return
  }
}<|endoftext|>


<commit_before>package mail

import (
	"crypto/tls"
	"net/smtp"

	net_mail "net/mail"

	"fmt"

	"github.com/bborbe/log"
)

var logger = log.DefaultLogger

type Config interface {
	SmtpUser() string
	SmtpPassword() string
	SmtpHost() string
	SmtpPort() int
}
type Message interface {
	Sender() string
	Recipient() string
	Content() string
	Subject() string
}

type mailer struct {
	config Config
}

type Mailer interface {
	Send(message Message) error
}

func New(config Config) *mailer {
	m := new(mailer)
	m.config = config
	return m
}

func (s *mailer) Send(message Message) error {
	logger.Debugf("sendMail to %s", message.Recipient())
	auth := smtp.PlainAuth(
		"",
		s.config.SmtpUser(),
		s.config.SmtpPassword(),
		s.config.SmtpHost(),
	)
	servername := fmt.Sprintf("%s:%d", s.config.SmtpHost(), s.config.SmtpPort())
	logger.Debugf("connect to smtp-server to %s", servername)

	from := net_mail.Address{"", message.Sender()}
	to := net_mail.Address{"", message.Recipient()}

	headers := make(map[string]string)
	headers["From"] = from.String()
	headers["To"] = to.String()
	headers["Subject"] = message.Subject()

	content := ""
	for k, v := range headers {
		content += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	content += "\r\n" + message.Content()

	tlsconfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         servername,
	}

	logger.Tracef("connect to %s", servername)
	conn, err := tls.Dial("tcp", servername, tlsconfig)
	if err != nil {
		return err
	}
	defer conn.Close()

	smtpClient, err := smtp.NewClient(conn, s.config.SmtpHost())
	if err != nil {
		return nil
	}

	err = smtpClient.Hello("localhost")
	if err != nil {
		return err
	}

	err = smtpClient.Auth(auth)
	if err != nil {
		return err
	}

	err = smtpClient.Mail(message.Sender())
	if err != nil {
		return err
	}

	err = smtpClient.Rcpt(message.Recipient())
	if err != nil {
		return err
	}

	data, err := smtpClient.Data()
	if err != nil {
		return err
	}

	logger.Tracef("write message %s", content)
	data.Write([]byte(content))

	err = data.Close()
	if err != nil {
		return err
	}

	return smtpClient.Quit()
}
<commit_msg>format<commit_after>package mail

import (
	"crypto/tls"
	"net/smtp"

	net_mail "net/mail"

	"fmt"

	"github.com/bborbe/log"
)

var logger = log.DefaultLogger

type Config interface {
	SmtpUser() string
	SmtpPassword() string
	SmtpHost() string
	SmtpPort() int
}

type Message interface {
	Sender() string
	Recipient() string
	Content() string
	Subject() string
}

type mailer struct {
	config Config
}

type Mailer interface {
	Send(message Message) error
}

func New(config Config) *mailer {
	m := new(mailer)
	m.config = config
	return m
}

func (s *mailer) Send(message Message) error {
	logger.Debugf("sendMail to %s", message.Recipient())
	auth := smtp.PlainAuth(
		"",
		s.config.SmtpUser(),
		s.config.SmtpPassword(),
		s.config.SmtpHost(),
	)
	servername := fmt.Sprintf("%s:%d", s.config.SmtpHost(), s.config.SmtpPort())
	logger.Debugf("connect to smtp-server to %s", servername)

	from := net_mail.Address{"", message.Sender()}
	to := net_mail.Address{"", message.Recipient()}

	headers := make(map[string]string)
	headers["From"] = from.String()
	headers["To"] = to.String()
	headers["Subject"] = message.Subject()

	content := ""
	for k, v := range headers {
		content += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	content += "\r\n" + message.Content()

	tlsconfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         servername,
	}

	logger.Tracef("connect to %s", servername)
	conn, err := tls.Dial("tcp", servername, tlsconfig)
	if err != nil {
		return err
	}
	defer conn.Close()

	smtpClient, err := smtp.NewClient(conn, s.config.SmtpHost())
	if err != nil {
		return nil
	}

	err = smtpClient.Hello("localhost")
	if err != nil {
		return err
	}

	err = smtpClient.Auth(auth)
	if err != nil {
		return err
	}

	err = smtpClient.Mail(message.Sender())
	if err != nil {
		return err
	}

	err = smtpClient.Rcpt(message.Recipient())
	if err != nil {
		return err
	}

	data, err := smtpClient.Data()
	if err != nil {
		return err
	}

	logger.Tracef("write message %s", content)
	data.Write([]byte(content))

	err = data.Close()
	if err != nil {
		return err
	}

	return smtpClient.Quit()
}
<|endoftext|>


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

package main

import (
	"fmt"
	"os"
	"runtime"
	"strings"
)

var cmdEnv = &Command{
	Run:       runEnv,
	UsageLine: "env [var ...]",
	Short:     "print Go environment information",
	Long: `
Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file).  If one or more variable
names is given as arguments,  env prints the value of
each named variable on its own line.
	`,
}

type envVar struct {
	name, value string
}

func mkEnv() []envVar {
	var b builder
	b.init()

	env := []envVar{
		{"GOARCH", goarch},
		{"GOBIN", gobin},
		{"GOEXE", exeSuffix},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOOS", goos},
		{"GOPATH", os.Getenv("GOPATH")},
		{"GORACE", os.Getenv("GORACE")},
		{"GOROOT", goroot},
		{"GOTOOLDIR", toolDir},
		{"GO15VENDOREXPERIMENT", os.Getenv("GO15VENDOREXPERIMENT")},

		// disable escape codes in clang errors
		{"TERM", "dumb"},
	}

	if goos != "plan9" {
		cmd := b.gccCmd(".")
		env = append(env, envVar{"CC", cmd[0]})
		env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
		cmd = b.gxxCmd(".")
		env = append(env, envVar{"CXX", cmd[0]})
	}

	if buildContext.CgoEnabled {
		env = append(env, envVar{"CGO_ENABLED", "1"})
	} else {
		env = append(env, envVar{"CGO_ENABLED", "0"})
	}

	return env
}

func findEnv(env []envVar, name string) string {
	for _, e := range env {
		if e.name == name {
			return e.value
		}
	}
	return ""
}

func runEnv(cmd *Command, args []string) {
	env := mkEnv()
	if len(args) > 0 {
		for _, name := range args {
			fmt.Printf("%s\n", findEnv(env, name))
		}
		return
	}

	for _, e := range env {
		if e.name != "TERM" {
			switch runtime.GOOS {
			default:
				fmt.Printf("%s=\"%s\"\n", e.name, e.value)
			case "plan9":
				if strings.IndexByte(e.value, '\x00') < 0 {
					fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
				} else {
					v := strings.Split(e.value, "\x00")
					fmt.Printf("%s=(", e.name)
					for x, s := range v {
						if x > 0 {
							fmt.Printf(" ")
						}
						fmt.Printf("%s", s)
					}
					fmt.Printf(")\n")
				}
			case "windows":
				fmt.Printf("set %s=%s\n", e.name, e.value)
			}
		}
	}
}
<commit_msg>cmd/go: always show current value for GO15VENDOREXPERIMENT<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"runtime"
	"strings"
)

var cmdEnv = &Command{
	Run:       runEnv,
	UsageLine: "env [var ...]",
	Short:     "print Go environment information",
	Long: `
Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file).  If one or more variable
names is given as arguments,  env prints the value of
each named variable on its own line.
	`,
}

type envVar struct {
	name, value string
}

func mkEnv() []envVar {
	var b builder
	b.init()

	vendorExpValue := "0"
	if go15VendorExperiment {
		vendorExpValue = "1"
	}

	env := []envVar{
		{"GOARCH", goarch},
		{"GOBIN", gobin},
		{"GOEXE", exeSuffix},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOOS", goos},
		{"GOPATH", os.Getenv("GOPATH")},
		{"GORACE", os.Getenv("GORACE")},
		{"GOROOT", goroot},
		{"GOTOOLDIR", toolDir},
		{"GO15VENDOREXPERIMENT", vendorExpValue},

		// disable escape codes in clang errors
		{"TERM", "dumb"},
	}

	if goos != "plan9" {
		cmd := b.gccCmd(".")
		env = append(env, envVar{"CC", cmd[0]})
		env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
		cmd = b.gxxCmd(".")
		env = append(env, envVar{"CXX", cmd[0]})
	}

	if buildContext.CgoEnabled {
		env = append(env, envVar{"CGO_ENABLED", "1"})
	} else {
		env = append(env, envVar{"CGO_ENABLED", "0"})
	}

	return env
}

func findEnv(env []envVar, name string) string {
	for _, e := range env {
		if e.name == name {
			return e.value
		}
	}
	return ""
}

func runEnv(cmd *Command, args []string) {
	env := mkEnv()
	if len(args) > 0 {
		for _, name := range args {
			fmt.Printf("%s\n", findEnv(env, name))
		}
		return
	}

	for _, e := range env {
		if e.name != "TERM" {
			switch runtime.GOOS {
			default:
				fmt.Printf("%s=\"%s\"\n", e.name, e.value)
			case "plan9":
				if strings.IndexByte(e.value, '\x00') < 0 {
					fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
				} else {
					v := strings.Split(e.value, "\x00")
					fmt.Printf("%s=(", e.name)
					for x, s := range v {
						if x > 0 {
							fmt.Printf(" ")
						}
						fmt.Printf("%s", s)
					}
					fmt.Printf(")\n")
				}
			case "windows":
				fmt.Printf("set %s=%s\n", e.name, e.value)
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Kubernetes Authors.

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 pod

import (
	"flag"
	"fmt"

	"github.com/onsi/gomega"

	v1 "k8s.io/api/core/v1"
	imageutils "k8s.io/kubernetes/test/utils/image"
	psaapi "k8s.io/pod-security-admission/api"
	psapolicy "k8s.io/pod-security-admission/policy"
	"k8s.io/utils/pointer"
)

// NodeOSDistroIs returns true if the distro is the same as `--node-os-distro`
// the package framework/pod can't import the framework package (see #81245)
// we need to check if the --node-os-distro=windows is set and the framework package
// is the one that's parsing the flags, as a workaround this method is looking for the same flag again
// TODO: replace with `framework.NodeOSDistroIs` when #81245 is complete
func NodeOSDistroIs(distro string) bool {
	var nodeOsDistro *flag.Flag = flag.Lookup("node-os-distro")
	if nodeOsDistro != nil && nodeOsDistro.Value.String() == distro {
		return true
	}
	return false
}

// GenerateScriptCmd generates the corresponding command lines to execute a command.
func GenerateScriptCmd(command string) []string {
	var commands []string
	commands = []string{"/bin/sh", "-c", command}
	return commands
}

// GetDefaultTestImage returns the default test image based on OS.
// If the node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
// If the node OS is linux, return busybox image
func GetDefaultTestImage() string {
	return imageutils.GetE2EImage(GetDefaultTestImageID())
}

// GetDefaultTestImageID returns the default test image id based on OS.
// If the node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
// If the node OS is linux, return busybox image
func GetDefaultTestImageID() imageutils.ImageID {
	return GetTestImageID(imageutils.BusyBox)
}

// GetTestImage returns the image name with the given input
// If the Node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
func GetTestImage(id imageutils.ImageID) string {
	if NodeOSDistroIs("windows") {
		return imageutils.GetE2EImage(imageutils.Agnhost)
	}
	return imageutils.GetE2EImage(id)
}

// GetTestImageID returns the image id with the given input
// If the Node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
func GetTestImageID(id imageutils.ImageID) imageutils.ImageID {
	if NodeOSDistroIs("windows") {
		return imageutils.Agnhost
	}
	return id
}

// GeneratePodSecurityContext generates the corresponding pod security context with the given inputs
// If the Node OS is windows, currently we will ignore the inputs and return nil.
// TODO: Will modify it after windows has its own security context
func GeneratePodSecurityContext(fsGroup *int64, seLinuxOptions *v1.SELinuxOptions) *v1.PodSecurityContext {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return &v1.PodSecurityContext{
		FSGroup:        fsGroup,
		SELinuxOptions: seLinuxOptions,
	}
}

// GenerateContainerSecurityContext generates the corresponding container security context with the given inputs
// If the Node OS is windows, currently we will ignore the inputs and return nil.
// TODO: Will modify it after windows has its own security context
func GenerateContainerSecurityContext(privileged bool) *v1.SecurityContext {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return &v1.SecurityContext{
		Privileged: &privileged,
	}
}

// GetLinuxLabel returns the default SELinuxLabel based on OS.
// If the node OS is windows, it will return nil
func GetLinuxLabel() *v1.SELinuxOptions {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return &v1.SELinuxOptions{
		Level: "s0:c0,c1"}
}

// DefaultNonRootUser is the default user ID used for running restricted (non-root) containers.
const DefaultNonRootUser = 1000

// GetRestrictedPodSecurityContext returns a restricted pod security context.
// This includes setting RunAsUser for convenience, to pass the RunAsNonRoot check.
// Tests that require a specific user ID should override this.
func GetRestrictedPodSecurityContext() *v1.PodSecurityContext {
	return &v1.PodSecurityContext{
		RunAsNonRoot:   pointer.BoolPtr(true),
		RunAsUser:      pointer.Int64(DefaultNonRootUser),
		SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault},
	}
}

// GetRestrictedContainerSecurityContext returns a minimal restricted container security context.
func GetRestrictedContainerSecurityContext() *v1.SecurityContext {
	return &v1.SecurityContext{
		AllowPrivilegeEscalation: pointer.BoolPtr(false),
		Capabilities:             &v1.Capabilities{Drop: []v1.Capability{"ALL"}},
	}
}

var psaEvaluator, _ = psapolicy.NewEvaluator(psapolicy.DefaultChecks())

// MustMixinRestrictedPodSecurity makes the given pod compliant with the restricted pod security level.
// If doing so would overwrite existing non-conformant configuration, a test failure is triggered.
func MustMixinRestrictedPodSecurity(pod *v1.Pod) *v1.Pod {
	err := MixinRestrictedPodSecurity(pod)
	gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred())
	return pod
}

// MixinRestrictedPodSecurity makes the given pod compliant with the restricted pod security level.
// If doing so would overwrite existing non-conformant configuration, an error is returned.
// Note that this sets a default RunAsUser. See GetRestrictedPodSecurityContext.
// TODO(#105919): Handle PodOS for windows pods.
func MixinRestrictedPodSecurity(pod *v1.Pod) error {
	if pod.Spec.SecurityContext == nil {
		pod.Spec.SecurityContext = GetRestrictedPodSecurityContext()
	} else {
		if pod.Spec.SecurityContext.RunAsNonRoot == nil {
			pod.Spec.SecurityContext.RunAsNonRoot = pointer.BoolPtr(true)
		}
		if pod.Spec.SecurityContext.RunAsUser == nil {
			pod.Spec.SecurityContext.RunAsUser = pointer.Int64Ptr(DefaultNonRootUser)
		}
		if pod.Spec.SecurityContext.SeccompProfile == nil {
			pod.Spec.SecurityContext.SeccompProfile = &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}
		}
	}
	for i := range pod.Spec.Containers {
		mixinRestrictedContainerSecurityContext(&pod.Spec.Containers[i])
	}
	for i := range pod.Spec.InitContainers {
		mixinRestrictedContainerSecurityContext(&pod.Spec.InitContainers[i])
	}

	// Validate the resulting pod against the restricted profile.
	restricted := psaapi.LevelVersion{
		Level:   psaapi.LevelRestricted,
		Version: psaapi.LatestVersion(),
	}
	if agg := psapolicy.AggregateCheckResults(psaEvaluator.EvaluatePod(restricted, &pod.ObjectMeta, &pod.Spec)); !agg.Allowed {
		return fmt.Errorf("failed to make pod %s restricted: %s", pod.Name, agg.ForbiddenDetail())
	}

	return nil
}

// mixinRestrictedContainerSecurityContext adds the required container security context options to
// be compliant with the restricted pod security level. Non-conformance checking is handled by the
// caller.
func mixinRestrictedContainerSecurityContext(container *v1.Container) {
	if container.SecurityContext == nil {
		container.SecurityContext = GetRestrictedContainerSecurityContext()
	} else {
		if container.SecurityContext.AllowPrivilegeEscalation == nil {
			container.SecurityContext.AllowPrivilegeEscalation = pointer.Bool(false)
		}
		if container.SecurityContext.Capabilities == nil {
			container.SecurityContext.Capabilities = &v1.Capabilities{}
		}
		if len(container.SecurityContext.Capabilities.Drop) == 0 {
			container.SecurityContext.Capabilities.Drop = []v1.Capability{"ALL"}
		}
	}
}
<commit_msg>RunAsUser causes pods to not start on Windows<commit_after>/*
Copyright 2021 The Kubernetes Authors.

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 pod

import (
	"flag"
	"fmt"

	"github.com/onsi/gomega"

	v1 "k8s.io/api/core/v1"
	imageutils "k8s.io/kubernetes/test/utils/image"
	psaapi "k8s.io/pod-security-admission/api"
	psapolicy "k8s.io/pod-security-admission/policy"
	"k8s.io/utils/pointer"
)

// NodeOSDistroIs returns true if the distro is the same as `--node-os-distro`
// the package framework/pod can't import the framework package (see #81245)
// we need to check if the --node-os-distro=windows is set and the framework package
// is the one that's parsing the flags, as a workaround this method is looking for the same flag again
// TODO: replace with `framework.NodeOSDistroIs` when #81245 is complete
func NodeOSDistroIs(distro string) bool {
	var nodeOsDistro *flag.Flag = flag.Lookup("node-os-distro")
	if nodeOsDistro != nil && nodeOsDistro.Value.String() == distro {
		return true
	}
	return false
}

// GenerateScriptCmd generates the corresponding command lines to execute a command.
func GenerateScriptCmd(command string) []string {
	var commands []string
	commands = []string{"/bin/sh", "-c", command}
	return commands
}

// GetDefaultTestImage returns the default test image based on OS.
// If the node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
// If the node OS is linux, return busybox image
func GetDefaultTestImage() string {
	return imageutils.GetE2EImage(GetDefaultTestImageID())
}

// GetDefaultTestImageID returns the default test image id based on OS.
// If the node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
// If the node OS is linux, return busybox image
func GetDefaultTestImageID() imageutils.ImageID {
	return GetTestImageID(imageutils.BusyBox)
}

// GetTestImage returns the image name with the given input
// If the Node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
func GetTestImage(id imageutils.ImageID) string {
	if NodeOSDistroIs("windows") {
		return imageutils.GetE2EImage(imageutils.Agnhost)
	}
	return imageutils.GetE2EImage(id)
}

// GetTestImageID returns the image id with the given input
// If the Node OS is windows, currently we return Agnhost image for Windows node
// due to the issue of #https://github.com/kubernetes-sigs/windows-testing/pull/35.
func GetTestImageID(id imageutils.ImageID) imageutils.ImageID {
	if NodeOSDistroIs("windows") {
		return imageutils.Agnhost
	}
	return id
}

// GetDefaultNonRootUser returns default non root user
// If the Node OS is windows, we return nill due to issue with invalid permissions set on projected volumes
// https://github.com/kubernetes/kubernetes/issues/102849
func GetDefaultNonRootUser() *int64 {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return pointer.Int64(DefaultNonRootUser)
}

// GeneratePodSecurityContext generates the corresponding pod security context with the given inputs
// If the Node OS is windows, currently we will ignore the inputs and return nil.
// TODO: Will modify it after windows has its own security context
func GeneratePodSecurityContext(fsGroup *int64, seLinuxOptions *v1.SELinuxOptions) *v1.PodSecurityContext {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return &v1.PodSecurityContext{
		FSGroup:        fsGroup,
		SELinuxOptions: seLinuxOptions,
	}
}

// GenerateContainerSecurityContext generates the corresponding container security context with the given inputs
// If the Node OS is windows, currently we will ignore the inputs and return nil.
// TODO: Will modify it after windows has its own security context
func GenerateContainerSecurityContext(privileged bool) *v1.SecurityContext {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return &v1.SecurityContext{
		Privileged: &privileged,
	}
}

// GetLinuxLabel returns the default SELinuxLabel based on OS.
// If the node OS is windows, it will return nil
func GetLinuxLabel() *v1.SELinuxOptions {
	if NodeOSDistroIs("windows") {
		return nil
	}
	return &v1.SELinuxOptions{
		Level: "s0:c0,c1"}
}

// DefaultNonRootUser is the default user ID used for running restricted (non-root) containers.
const DefaultNonRootUser = 1000

// DefaultNonRootUserName is the default username in Windows used for running restricted (non-root) containers
const DefaultNonRootUserName = "ContainerUser"

// GetRestrictedPodSecurityContext returns a restricted pod security context.
// This includes setting RunAsUser for convenience, to pass the RunAsNonRoot check.
// Tests that require a specific user ID should override this.
func GetRestrictedPodSecurityContext() *v1.PodSecurityContext {
	psc := &v1.PodSecurityContext{
		RunAsNonRoot:   pointer.BoolPtr(true),
		RunAsUser:      GetDefaultNonRootUser(),
		SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault},
	}

	if NodeOSDistroIs("windows") {
		psc.WindowsOptions = &v1.WindowsSecurityContextOptions{}
		psc.WindowsOptions.RunAsUserName = pointer.StringPtr(DefaultNonRootUserName)
	}

	return psc
}

// GetRestrictedContainerSecurityContext returns a minimal restricted container security context.
func GetRestrictedContainerSecurityContext() *v1.SecurityContext {
	return &v1.SecurityContext{
		AllowPrivilegeEscalation: pointer.BoolPtr(false),
		Capabilities:             &v1.Capabilities{Drop: []v1.Capability{"ALL"}},
	}
}

var psaEvaluator, _ = psapolicy.NewEvaluator(psapolicy.DefaultChecks())

// MustMixinRestrictedPodSecurity makes the given pod compliant with the restricted pod security level.
// If doing so would overwrite existing non-conformant configuration, a test failure is triggered.
func MustMixinRestrictedPodSecurity(pod *v1.Pod) *v1.Pod {
	err := MixinRestrictedPodSecurity(pod)
	gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred())
	return pod
}

// MixinRestrictedPodSecurity makes the given pod compliant with the restricted pod security level.
// If doing so would overwrite existing non-conformant configuration, an error is returned.
// Note that this sets a default RunAsUser. See GetRestrictedPodSecurityContext.
// TODO(#105919): Handle PodOS for windows pods.
func MixinRestrictedPodSecurity(pod *v1.Pod) error {
	if pod.Spec.SecurityContext == nil {
		pod.Spec.SecurityContext = GetRestrictedPodSecurityContext()
	} else {
		if pod.Spec.SecurityContext.RunAsNonRoot == nil {
			pod.Spec.SecurityContext.RunAsNonRoot = pointer.BoolPtr(true)
		}
		if pod.Spec.SecurityContext.RunAsUser == nil {
			pod.Spec.SecurityContext.RunAsUser = GetDefaultNonRootUser()
		}
		if pod.Spec.SecurityContext.SeccompProfile == nil {
			pod.Spec.SecurityContext.SeccompProfile = &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}
		}
		if NodeOSDistroIs("windows") && pod.Spec.SecurityContext.WindowsOptions == nil {
			pod.Spec.SecurityContext.WindowsOptions = &v1.WindowsSecurityContextOptions{}
			pod.Spec.SecurityContext.WindowsOptions.RunAsUserName = pointer.StringPtr(DefaultNonRootUserName)
		}
	}
	for i := range pod.Spec.Containers {
		mixinRestrictedContainerSecurityContext(&pod.Spec.Containers[i])
	}
	for i := range pod.Spec.InitContainers {
		mixinRestrictedContainerSecurityContext(&pod.Spec.InitContainers[i])
	}

	// Validate the resulting pod against the restricted profile.
	restricted := psaapi.LevelVersion{
		Level:   psaapi.LevelRestricted,
		Version: psaapi.LatestVersion(),
	}
	if agg := psapolicy.AggregateCheckResults(psaEvaluator.EvaluatePod(restricted, &pod.ObjectMeta, &pod.Spec)); !agg.Allowed {
		return fmt.Errorf("failed to make pod %s restricted: %s", pod.Name, agg.ForbiddenDetail())
	}

	return nil
}

// mixinRestrictedContainerSecurityContext adds the required container security context options to
// be compliant with the restricted pod security level. Non-conformance checking is handled by the
// caller.
func mixinRestrictedContainerSecurityContext(container *v1.Container) {
	if container.SecurityContext == nil {
		container.SecurityContext = GetRestrictedContainerSecurityContext()
	} else {
		if container.SecurityContext.AllowPrivilegeEscalation == nil {
			container.SecurityContext.AllowPrivilegeEscalation = pointer.Bool(false)
		}
		if container.SecurityContext.Capabilities == nil {
			container.SecurityContext.Capabilities = &v1.Capabilities{}
		}
		if len(container.SecurityContext.Capabilities.Drop) == 0 {
			container.SecurityContext.Capabilities.Drop = []v1.Capability{"ALL"}
		}
	}
}
<|endoftext|>


<commit_before>package integration

import (
	"fmt"
	"net/http"

	"github.com/jinzhu/gorm"
	_ "github.com/mattn/go-sqlite3"
	"github.com/qor/qor"
	"github.com/qor/qor/admin"
)

type User struct {
	gorm.Model
	Name string
}

type Product struct {
	gorm.Model
	Name        string
	Description string
}

func Start(port int) {
	DB, _ := gorm.Open("sqlite3", "demo.db")
	DB.AutoMigrate(&User{}, &Product{})

	Admin := admin.New(&qor.Config{DB: &DB})
	Admin.AddResource(&User{}, &admin.Config{Menu: []string{"User Management"}})
	Admin.AddResource(&Product{}, &admin.Config{Menu: []string{"Product Management"}})

	mux := http.NewServeMux()
	Admin.MountTo("/admin", mux)
	http.ListenAndServe(fmt.Sprintf(":%v", port), mux)
}
<commit_msg>Change integration test db driver to mysql.<commit_after>package integration

import (
	"fmt"
	"net/http"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
	"github.com/qor/qor"
	"github.com/qor/qor/admin"
)

type User struct {
	gorm.Model
	Name string
}

type Product struct {
	gorm.Model
	Name        string
	Description string
}

var DB gorm.DB

func Start(port int) {
	var err error
	// CREATE USER 'qor'@'localhost' IDENTIFIED BY 'qor';
	// CREATE DATABASE qor_integration_test;
	// GRANT ALL PRIVILEGES ON qor_integration_test.* TO 'qor'@'localhost';
	dbuser, dbpwd, dbname := "qor", "qor", "qor_integration_test"

	DB, err = gorm.Open("mysql", fmt.Sprintf("%s:%s@/%s?charset=utf8&parseTime=True&loc=Local", dbuser, dbpwd, dbname))
	if err != nil {
		panic(err)
	}

	setupDb()

	Admin := admin.New(&qor.Config{DB: &DB})
	Admin.AddResource(&User{}, &admin.Config{Menu: []string{"User Management"}})
	Admin.AddResource(&Product{}, &admin.Config{Menu: []string{"Product Management"}})

	mux := http.NewServeMux()
	Admin.MountTo("/admin", mux)
	http.ListenAndServe(fmt.Sprintf(":%v", port), mux)
}

func getTables() []interface{} {
	return []interface{}{
		&User{},
		&Product{},
	}
}

func setupDb() {
	tables := getTables()

	for _, table := range tables {
		if err := DB.DropTableIfExists(table).Error; err != nil {
			panic(err)
		}

		if err := DB.AutoMigrate(table).Error; err != nil {
			panic(err)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Adam Shannon
//
// 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.

// +build darwin

package test

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

	"github.com/adamdecaf/cert-manage/pkg/certutil"
	"github.com/adamdecaf/cert-manage/pkg/file"
	"github.com/adamdecaf/cert-manage/pkg/store"
)

var (
	// used to serialize _add and whitelist/restore tests
	// _add goes first, followed by whitelist/restore test,
	// but this serializes access
	darwinKeychainWG = sync.WaitGroup{}
)

func init() {
	darwinKeychainWG.Add(1)
}

func TestIntegration__date(t *testing.T) {
	cmd := Command("date", "-u", "-r", "0").Trim()
	cmd.EqualT(t, "Thu Jan  1 00:00:00 UTC 1970")

	ans := `Command:
  date -u -r 0
Output:
  Thu Jan  1 00:00:00 UTC 1970`
	if cmd.String() != ans {
		t.Errorf("cmd.String() = %q", cmd.String())
	}
}

func TestIntegration__unknown(t *testing.T) {
	cmd := CertManage("other").Trim()
	cmd.FailedT(t)
}

func TestIntegration__list(t *testing.T) {
	t.Skip("darwin support is wip")

	cmd := CertManage("list", "-count").Trim()
	cmd.CmpIntF(t, func(i int) bool { return i > 1 })
}

func TestIntegration__listFromFile(t *testing.T) {
	cmd := CertManage("list", "-file", "../testdata/lots.crt", "-count").Trim()
	cmd.CmpIntF(t, func(i int) bool { return i == 5 })
}

func TestIntegration__add(t *testing.T) {
	// don't signal we're done until this test completes
	defer darwinKeychainWG.Done()

	if !inCI() {
		t.Skip("not mutating non-CI login keychain")
	}
	if os.Getenv("INTEGRATION") == "" {
		t.Skip("delaying darwin integration tests, since we're running all tests right now")
	}
	setupKeychain(t)

	where := "../testdata/example.crt"
	certs, err := certutil.FromFile(where)
	if err != nil {
		t.Fatal(err)
	}
	if len(certs) != 1 {
		t.Fatalf("got %d certs", len(certs))
	}
	fp := certutil.GetHexSHA256Fingerprint(*certs[0])

	// verify cert doesn't exist already
	if inPlatformStore(t, fp) {
		name := certutil.StringifyPKIXName(certs[0].Subject)
		t.Fatalf("cert already in our store, please remove, %s", name)
	}

	// add cert and verify
	CertManage("add", "-file", where).SuccessT(t)
	if !inPlatformStore(t, fp) {
		t.Errorf("didn't find added cert, fp=%q", fp)
	}
}

func inPlatformStore(t *testing.T, fp string) bool {
	t.Helper()

	// Grab platform certs and verify ours is added
	found, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}
	for i := range found {
		ffp := certutil.GetHexSHA256Fingerprint(*found[i])
		if fp == ffp {
			return true
		}
	}
	return false
}

// Create a 'login.keychain' if it doesn't exist, only in CI
func setupKeychain(t *testing.T) {
	if !inCI() {
		return
	}
	t.Helper()

	// Copy our 'empty.keychain' over to the path..
	// I've tried creating it, but runnint into an error
	//
	// exec.Command("security", "create-keychain", "-p", `''`).CombinedOutput()
	//
	// The error is: 'Error exit status 255'
	// I think this is a problem where the security cli is trying to find a TTY

	where := filepath.Join(file.HomeDir(), "/Library/Keychains/login.keychain")
	if !file.Exists(where) {
		src := "../testdata/empty.keychain"
		if err := file.CopyFile(src, where); err != nil {
			t.Error(err)
		}
	}
}

// Don't run this test byitself, there's a .Wait()
// instead call `go test ... -run TestIntegration__`
func TestIntegration__WhitelistAndRemove(t *testing.T) {
	// wait until _add test finishes, so we don't clobber the keychain
	darwinKeychainWG.Wait()

	// only run if we're on CI
	if !inCI() {
		t.Skip("not mutating non-CI login keychain")
	}
	if os.Getenv("INTEGRATION") == "" {
		t.Skip("delaying darwin integration tests, since we're running all tests right now")
	}
	t.Helper()

	// get cert count
	certsBefore, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}

	// verify we can load google
	if err := loadGoogle(t); online(t) && err != nil {
		t.Fatalf("expected to be able to load google, err=%v", err)
	}

	// take a backup
	cmd := CertManage("backup").Trim()
	cmd.EqualT(t, "Backup completed successfully")

	// whitelist
	cmd = CertManage("whitelist", "-file", "../testdata/test-whitelist.json")
	cmd.SuccessT(t)

	// verify cert count
	certsAfter, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}
	if len(certsBefore) <= len(certsAfter) {
		t.Fatalf("certsBefore=%d, certsAfter=%d", len(certsBefore), len(certsAfter))
	}

	// verify we can't load google
	if err := loadGoogle(t); online(t) && err == nil {
		t.Fatal("expected to not load google")
	}

	// restore
	cmd = CertManage("restore").Trim()
	cmd.EqualT(t, "Restore completed successfully")
	cmd.SuccessT(t)

	// verify cert count
	certsAfterRestore, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}
	if len(certsBefore) != len(certsAfterRestore) {
		t.Fatalf("certsBefore=%d, certsAfter=%d, certsAfterRestore=%d", len(certsBefore), len(certsAfter), len(certsAfterRestore))
	}

	// verify we can load google
	if err := loadGoogle(t); online(t) && err != nil {
		t.Fatalf("expected to be able to load google, err=%v", err)
	}
}

var loadGoogleSourceCode = []byte(`package main
import "net/http"

func main() {
	resp, err := http.DefaultClient.Get("https://www.google.com")
	if err != nil {
		defer panic("A: " + err.Error())
	}
	if resp != nil && resp.Body != nil {
		if err := resp.Body.Close(); err != nil {
			panic("B: " + err.Error())
		}
	}
}`)

// loadGoogle needs to drop down back into a shell and then run some Go code,
// which on darwin uses the platform certs (Keychain), to attempt a connection
// against the target host.
//
// We can't just call `x509.SystemCertPool()` again, because under the hood it
// is protected by a `sync.Once`, so our changes aren't reflected until the next run.
func loadGoogle(t *testing.T) error {
	t.Helper()

	// render our Go code to another file and then `go run` it.
	tmp, err := ioutil.TempFile("", "load-google")
	if err != nil {
		t.Fatalf("error creating temp dir for loadGoogle, err=%v", err)
	}
	err = ioutil.WriteFile(tmp.Name(), loadGoogleSourceCode, 0644)
	if err != nil {
		t.Fatalf("error writing loadGoogle source code to %s, err=%v", tmp.Name(), err)
	}
	if err := tmp.Sync(); err != nil {
		t.Fatalf("error syncing loadGoogle source code to %s, err=%v", tmp.Name(), err)
	}
	// go requires files have a .go suffix, but symlinks work just as fine too
	dir, _ := filepath.Split(tmp.Name())
	filename := filepath.Join(dir, fmt.Sprintf("google%d.go", time.Now().Unix()))
	err = os.Symlink(tmp.Name(), filename)
	if err != nil {
		t.Fatalf("error symlinking google source file, err=%v", err)
	}
	defer os.Remove(filename)

	cmd := exec.Command("go", "run", filename)
	cmd.Env = []string{
		// Running this with cgo doesn't seem to work because of a cache around the trustd deamon.
		// Chrome doesn't seem to have the same problem, but I haven't tracked down what they're doing.
		//
		// I looked into clearing this cache with a cgo specific wrapper (i.e. SecTrustSettingsPurgeUserAdminCertsCache)
		// but couldn't get it working. There are some Sec*Priv.h header files which don't seem to be symlinked in with the
		// rest of #include <Security/Security.h> files.
		//
		// Either way we compile cert-manage without cgo so it doesn't seem like a big leap to run this test without cgo.
		//
		// https://github.com/practicalswift/osx/blob/27f6b27ca6e76018240c126c94059d859760981d/src/security/OSX/trustd/trustd.c#L628
		// https://github.com/practicalswift/osx/blob/27f6b27ca6e76018240c126c94059d859760981d/src/security/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp#L936-L940
		"CGO_ENABLED=0",
	}
	if debug {
		cmd.Env = append(cmd.Env, "GODEBUG=x509roots=1")
	}
	out, err := cmd.CombinedOutput()
	if debug {
		fmt.Printf(`Command: %s
Output:
%s`, strings.Join(cmd.Args, " "), string(out))
	}
	if err != nil {
		return fmt.Errorf("error running loadGoogle code, err=%v, output=%s", err, strings.TrimSpace(string(out)))
	}
	return nil
}

func TestIntegration__loadGoogle(t *testing.T) {
	if online(t) {
		if err := loadGoogle(t); err != nil {
			t.Fatal(err)
		}
	}
}

// Firefox tests
// func TestIntegration__firefox(t *testing.T) {
// 	if !online(t) {
// 		t.Skip("offline, can't run firefox tests (no NSS setup)")
// 	}

// 	// Make a request using the Keychain to get it ready
// 	// travis needs this
// 	cmd := Command("timeout", strings.Split("15s firefox --headless https://google.com 2>&1 >> /var/log/firefox.log", " ")...)
// 	cmd.SuccessT(t)

// 	// Verify firefox has found certificates
// 	cmd = CertManage("list", "-app", "firefox", "-count").Trim()
// 	cmd.SuccessT(t)
// 	cmd.CmpIntF(t, func(i int) bool { return i > 1 })
// }
<commit_msg>test/darwin: TODO for later<commit_after>// Copyright 2018 Adam Shannon
//
// 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.

// +build darwin

package test

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

	"github.com/adamdecaf/cert-manage/pkg/certutil"
	"github.com/adamdecaf/cert-manage/pkg/file"
	"github.com/adamdecaf/cert-manage/pkg/store"
)

var (
	// used to serialize _add and whitelist/restore tests
	// _add goes first, followed by whitelist/restore test,
	// but this serializes access
	darwinKeychainWG = sync.WaitGroup{}
)

func init() {
	darwinKeychainWG.Add(1)
}

func TestIntegration__date(t *testing.T) {
	cmd := Command("date", "-u", "-r", "0").Trim()
	cmd.EqualT(t, "Thu Jan  1 00:00:00 UTC 1970")

	ans := `Command:
  date -u -r 0
Output:
  Thu Jan  1 00:00:00 UTC 1970`
	if cmd.String() != ans {
		t.Errorf("cmd.String() = %q", cmd.String())
	}
}

func TestIntegration__unknown(t *testing.T) {
	cmd := CertManage("other").Trim()
	cmd.FailedT(t)
}

func TestIntegration__list(t *testing.T) {
	t.Skip("darwin support is wip")

	cmd := CertManage("list", "-count").Trim()
	cmd.CmpIntF(t, func(i int) bool { return i > 1 })
}

func TestIntegration__listFromFile(t *testing.T) {
	cmd := CertManage("list", "-file", "../testdata/lots.crt", "-count").Trim()
	cmd.CmpIntF(t, func(i int) bool { return i == 5 })
}

func TestIntegration__add(t *testing.T) {
	// don't signal we're done until this test completes
	defer darwinKeychainWG.Done()

	if !inCI() {
		t.Skip("not mutating non-CI login keychain")
	}
	if os.Getenv("INTEGRATION") == "" {
		t.Skip("delaying darwin integration tests, since we're running all tests right now")
	}
	setupKeychain(t)

	where := "../testdata/example.crt"
	certs, err := certutil.FromFile(where)
	if err != nil {
		t.Fatal(err)
	}
	if len(certs) != 1 {
		t.Fatalf("got %d certs", len(certs))
	}
	fp := certutil.GetHexSHA256Fingerprint(*certs[0])

	// verify cert doesn't exist already
	if inPlatformStore(t, fp) {
		name := certutil.StringifyPKIXName(certs[0].Subject)
		t.Fatalf("cert already in our store, please remove, %s", name)
	}

	// add cert and verify
	CertManage("add", "-file", where).SuccessT(t)
	if !inPlatformStore(t, fp) {
		t.Errorf("didn't find added cert, fp=%q", fp)
	}

	// TODO(adam): delete the certificate we added
}

func inPlatformStore(t *testing.T, fp string) bool {
	t.Helper()

	// Grab platform certs and verify ours is added
	found, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}
	for i := range found {
		ffp := certutil.GetHexSHA256Fingerprint(*found[i])
		if fp == ffp {
			return true
		}
	}
	return false
}

// Create a 'login.keychain' if it doesn't exist, only in CI
func setupKeychain(t *testing.T) {
	if !inCI() {
		return
	}
	t.Helper()

	// Copy our 'empty.keychain' over to the path..
	// I've tried creating it, but runnint into an error
	//
	// exec.Command("security", "create-keychain", "-p", `''`).CombinedOutput()
	//
	// The error is: 'Error exit status 255'
	// I think this is a problem where the security cli is trying to find a TTY

	where := filepath.Join(file.HomeDir(), "/Library/Keychains/login.keychain")
	if !file.Exists(where) {
		src := "../testdata/empty.keychain"
		if err := file.CopyFile(src, where); err != nil {
			t.Error(err)
		}
	}
}

// Don't run this test byitself, there's a .Wait()
// instead call `go test ... -run TestIntegration__`
func TestIntegration__WhitelistAndRemove(t *testing.T) {
	// wait until _add test finishes, so we don't clobber the keychain
	darwinKeychainWG.Wait()

	// only run if we're on CI
	if !inCI() {
		t.Skip("not mutating non-CI login keychain")
	}
	if os.Getenv("INTEGRATION") == "" {
		t.Skip("delaying darwin integration tests, since we're running all tests right now")
	}
	t.Helper()

	// get cert count
	certsBefore, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}

	// verify we can load google
	if err := loadGoogle(t); online(t) && err != nil {
		t.Fatalf("expected to be able to load google, err=%v", err)
	}

	// take a backup
	cmd := CertManage("backup").Trim()
	cmd.EqualT(t, "Backup completed successfully")

	// whitelist
	cmd = CertManage("whitelist", "-file", "../testdata/test-whitelist.json")
	cmd.SuccessT(t)

	// verify cert count
	certsAfter, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}
	if len(certsBefore) <= len(certsAfter) {
		t.Fatalf("certsBefore=%d, certsAfter=%d", len(certsBefore), len(certsAfter))
	}

	// verify we can't load google
	if err := loadGoogle(t); online(t) && err == nil {
		t.Fatal("expected to not load google")
	}

	// restore
	cmd = CertManage("restore").Trim()
	cmd.EqualT(t, "Restore completed successfully")
	cmd.SuccessT(t)

	// verify cert count
	certsAfterRestore, err := store.Platform().List()
	if err != nil {
		t.Fatal(err)
	}
	if len(certsBefore) != len(certsAfterRestore) {
		t.Fatalf("certsBefore=%d, certsAfter=%d, certsAfterRestore=%d", len(certsBefore), len(certsAfter), len(certsAfterRestore))
	}

	// verify we can load google
	if err := loadGoogle(t); online(t) && err != nil {
		t.Fatalf("expected to be able to load google, err=%v", err)
	}
}

var loadGoogleSourceCode = []byte(`package main
import "net/http"

func main() {
	resp, err := http.DefaultClient.Get("https://www.google.com")
	if err != nil {
		defer panic("A: " + err.Error())
	}
	if resp != nil && resp.Body != nil {
		if err := resp.Body.Close(); err != nil {
			panic("B: " + err.Error())
		}
	}
}`)

// loadGoogle needs to drop down back into a shell and then run some Go code,
// which on darwin uses the platform certs (Keychain), to attempt a connection
// against the target host.
//
// We can't just call `x509.SystemCertPool()` again, because under the hood it
// is protected by a `sync.Once`, so our changes aren't reflected until the next run.
func loadGoogle(t *testing.T) error {
	t.Helper()

	// render our Go code to another file and then `go run` it.
	tmp, err := ioutil.TempFile("", "load-google")
	if err != nil {
		t.Fatalf("error creating temp dir for loadGoogle, err=%v", err)
	}
	err = ioutil.WriteFile(tmp.Name(), loadGoogleSourceCode, 0644)
	if err != nil {
		t.Fatalf("error writing loadGoogle source code to %s, err=%v", tmp.Name(), err)
	}
	if err := tmp.Sync(); err != nil {
		t.Fatalf("error syncing loadGoogle source code to %s, err=%v", tmp.Name(), err)
	}
	// go requires files have a .go suffix, but symlinks work just as fine too
	dir, _ := filepath.Split(tmp.Name())
	filename := filepath.Join(dir, fmt.Sprintf("google%d.go", time.Now().Unix()))
	err = os.Symlink(tmp.Name(), filename)
	if err != nil {
		t.Fatalf("error symlinking google source file, err=%v", err)
	}
	defer os.Remove(filename)

	cmd := exec.Command("go", "run", filename)
	cmd.Env = []string{
		// Running this with cgo doesn't seem to work because of a cache around the trustd deamon.
		// Chrome doesn't seem to have the same problem, but I haven't tracked down what they're doing.
		//
		// I looked into clearing this cache with a cgo specific wrapper (i.e. SecTrustSettingsPurgeUserAdminCertsCache)
		// but couldn't get it working. There are some Sec*Priv.h header files which don't seem to be symlinked in with the
		// rest of #include <Security/Security.h> files.
		//
		// Either way we compile cert-manage without cgo so it doesn't seem like a big leap to run this test without cgo.
		//
		// https://github.com/practicalswift/osx/blob/27f6b27ca6e76018240c126c94059d859760981d/src/security/OSX/trustd/trustd.c#L628
		// https://github.com/practicalswift/osx/blob/27f6b27ca6e76018240c126c94059d859760981d/src/security/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp#L936-L940
		"CGO_ENABLED=0",
	}
	if debug {
		cmd.Env = append(cmd.Env, "GODEBUG=x509roots=1")
	}
	out, err := cmd.CombinedOutput()
	if debug {
		fmt.Printf(`Command: %s
Output:
%s`, strings.Join(cmd.Args, " "), string(out))
	}
	if err != nil {
		return fmt.Errorf("error running loadGoogle code, err=%v, output=%s", err, strings.TrimSpace(string(out)))
	}
	return nil
}

func TestIntegration__loadGoogle(t *testing.T) {
	if online(t) {
		if err := loadGoogle(t); err != nil {
			t.Fatal(err)
		}
	}
}

// Firefox tests
// func TestIntegration__firefox(t *testing.T) {
// 	if !online(t) {
// 		t.Skip("offline, can't run firefox tests (no NSS setup)")
// 	}

// 	// Make a request using the Keychain to get it ready
// 	// travis needs this
// 	cmd := Command("timeout", strings.Split("15s firefox --headless https://google.com 2>&1 >> /var/log/firefox.log", " ")...)
// 	cmd.SuccessT(t)

// 	// Verify firefox has found certificates
// 	cmd = CertManage("list", "-app", "firefox", "-count").Trim()
// 	cmd.SuccessT(t)
// 	cmd.CmpIntF(t, func(i int) bool { return i > 1 })
// }
<|endoftext|>


<commit_before>package kvite

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

func withDB(t *testing.T, fn func(db *DB, t *testing.T)) {
	file := tempfile()
	db, err := Open(file)

	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file)
	defer db.Close()

	fn(db, t)

}

func TestOpen(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
	})
}

func TestBegin(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
	})
}

func TestRollback(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Rollback()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestCommit(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestCreateBucket(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		_, err = tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestPut(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		b, err := tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}

		err = b.Put("foo", []byte("bar"))
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestGet(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		b, err := tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}

		err = b.Put("foo", []byte("bar"))
		if err != nil {
			t.Fatal(err)
		}

		val, err := b.Get("foo")
		if err != nil {
			t.Fatal(err)
		}

		if string(val) != "bar" {
			t.Fatalf("values fo not match")
		}

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

func TestDelete(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		b, err := tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}

		err = b.Put("foo", []byte("bar"))
		if err != nil {
			t.Fatal(err)
		}

		val, err := b.Get("foo")
		if err != nil {
			t.Fatal(err)
		}

		if string(val) != "bar" {
			t.Fatalf("values fo not match")
		}

		err = b.Delete("foo")
		if err != nil {
			t.Fatal(err)
		}

		val, err = b.Get("foo")
		if val != nil {
			t.Fatalf("got a value when should have been nil")
		}

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

func TestTransaction(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		err := db.Transaction(func(tx *Tx) error {
			b, err := tx.CreateBucket("test")
			return err

			err = b.Put("foo", []byte("bar"))
			if err != nil {
				return err
			}

			val, err := b.Get("foo")
			if err != nil {
				return err
			}

			if string(val) != "bar" {
				return fmt.Errorf("values fo not match")
			}
			return nil
		})

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

// tempfile returns a temporary file path.
func tempfile() string {
	f, _ := ioutil.TempFile("", "kvite-")
	f.Close()
	os.Remove(f.Name())
	return f.Name()
}
<commit_msg>Add test for CreateBucketIfNotExists<commit_after>package kvite

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

func withDB(t *testing.T, fn func(db *DB, t *testing.T)) {
	file := tempfile()
	db, err := Open(file)

	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file)
	defer db.Close()

	fn(db, t)

}

func TestOpen(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
	})
}

func TestBegin(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
	})
}

func TestRollback(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Rollback()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestCommit(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestCreateBucket(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		_, err = tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestCreateBucketIfNotExists(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		_, err = tx.CreateBucketIfNotExists("test")
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestPut(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		b, err := tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}

		err = b.Put("foo", []byte("bar"))
		if err != nil {
			t.Fatal(err)
		}
		err = tx.Commit()
		if err != nil {
			t.Fatal(err)
		}
	})
}

func TestGet(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		b, err := tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}

		err = b.Put("foo", []byte("bar"))
		if err != nil {
			t.Fatal(err)
		}

		val, err := b.Get("foo")
		if err != nil {
			t.Fatal(err)
		}

		if string(val) != "bar" {
			t.Fatalf("values fo not match")
		}

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

func TestDelete(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatal(err)
		}
		defer tx.Rollback()
		b, err := tx.CreateBucket("test")
		if err != nil {
			t.Fatal(err)
		}

		err = b.Put("foo", []byte("bar"))
		if err != nil {
			t.Fatal(err)
		}

		val, err := b.Get("foo")
		if err != nil {
			t.Fatal(err)
		}

		if string(val) != "bar" {
			t.Fatalf("values fo not match")
		}

		err = b.Delete("foo")
		if err != nil {
			t.Fatal(err)
		}

		val, err = b.Get("foo")
		if val != nil {
			t.Fatalf("got a value when should have been nil")
		}

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

func TestTransaction(t *testing.T) {
	withDB(t, func(db *DB, t *testing.T) {
		err := db.Transaction(func(tx *Tx) error {
			b, err := tx.CreateBucket("test")
			return err

			err = b.Put("foo", []byte("bar"))
			if err != nil {
				return err
			}

			val, err := b.Get("foo")
			if err != nil {
				return err
			}

			if string(val) != "bar" {
				return fmt.Errorf("values fo not match")
			}
			return nil
		})

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

// tempfile returns a temporary file path.
func tempfile() string {
	f, _ := ioutil.TempFile("", "kvite-")
	f.Close()
	os.Remove(f.Name())
	return f.Name()
}
<|endoftext|>