<commit_before>package configschema

import (
	"github.com/zclconf/go-cty/cty"
)

// Block represents a configuration block.
//
// "Block" here is a logical grouping construct, though it happens to map
// directly onto the physical block syntax of Terraform's native configuration
// syntax. It may be a more a matter of convention in other syntaxes, such as
// JSON.
//
// When converted to a value, a Block always becomes an instance of an object
// type derived from its defined attributes and nested blocks
type Block struct {
	// Attributes describes any attributes that may appear directly inside
	// the block.
	Attributes map[string]*Attribute

	// BlockTypes describes any nested block types that may appear directly
	// inside the block.
	BlockTypes map[string]*NestedBlock
}

// Attribute represents a configuration attribute, within a block.
type Attribute struct {
	// Type is a type specification that the attribute's value must conform to.
	Type cty.Type

	// Required, if set to true, specifies that an omitted or null value is
	// not permitted.
	Required bool

	// Optional, if set to true, specifies that an omitted or null value is
	// permitted. This field conflicts with Required.
	Optional bool

	// Computed, if set to true, specifies that the value comes from the
	// provider rather than from configuration. If combined with Optional,
	// then the config may optionally provide an overridden value.
	Computed bool
}

// NestedBlock represents the embedding of one block within another.
type NestedBlock struct {
	// Block is the description of the block that's nested.
	Block

	// Nesting provides the nesting mode for the child block, which determines
	// how many instances of the block are allowed, how many labels it expects,
	// and how the resulting data will be converted into a data structure.
	Nesting NestingMode
}

// NestingMode is an enumeration of modes for nesting blocks inside other
// blocks.
type NestingMode int

//go:generate stringer -type=NestingMode

const (
	nestingModeInvalid NestingMode = iota

	// NestingSingle indicates that only a single instance of a given
	// block type is permitted, with no labels, and its content should be
	// provided directly as an object value.
	NestingSingle

	// NestingList indicates that multiple blocks of the given type are
	// permitted, with no labels, and that their corresponding objects should
	// be provided in a list.
	NestingList

	// NestingSet indicates that multiple blocks of the given type are
	// permitted, with no labels, and that their corresponding objects should
	// be provided in a set.
	NestingSet

	// NestingMap indicates that multiple blocks of the given type are
	// permitted, each with a single label, and that their corresponding
	// objects should be provided in a map whose keys are the labels.
	//
	// It's an error, therefore, to use the same label value on multiple
	// blocks.
	NestingMap
)
<commit_msg>config/configschema: MinItems and MaxItems for nested blocks<commit_after>package configschema

import (
	"github.com/zclconf/go-cty/cty"
)

// Block represents a configuration block.
//
// "Block" here is a logical grouping construct, though it happens to map
// directly onto the physical block syntax of Terraform's native configuration
// syntax. It may be a more a matter of convention in other syntaxes, such as
// JSON.
//
// When converted to a value, a Block always becomes an instance of an object
// type derived from its defined attributes and nested blocks
type Block struct {
	// Attributes describes any attributes that may appear directly inside
	// the block.
	Attributes map[string]*Attribute

	// BlockTypes describes any nested block types that may appear directly
	// inside the block.
	BlockTypes map[string]*NestedBlock
}

// Attribute represents a configuration attribute, within a block.
type Attribute struct {
	// Type is a type specification that the attribute's value must conform to.
	Type cty.Type

	// Required, if set to true, specifies that an omitted or null value is
	// not permitted.
	Required bool

	// Optional, if set to true, specifies that an omitted or null value is
	// permitted. This field conflicts with Required.
	Optional bool

	// Computed, if set to true, specifies that the value comes from the
	// provider rather than from configuration. If combined with Optional,
	// then the config may optionally provide an overridden value.
	Computed bool
}

// NestedBlock represents the embedding of one block within another.
type NestedBlock struct {
	// Block is the description of the block that's nested.
	Block

	// Nesting provides the nesting mode for the child block, which determines
	// how many instances of the block are allowed, how many labels it expects,
	// and how the resulting data will be converted into a data structure.
	Nesting NestingMode

	// MinItems and MaxItems set, for the NestingList and NestingSet nesting
	// modes, lower and upper limits on the number of child blocks allowed
	// of the given type. If both are left at zero, no limit is applied.
	//
	// As a special case, both values can be set to 1 for NestingSingle in
	// order to indicate that a particular single block is required.
	//
	// These fields are ignored for other nesting modes and must both be left
	// at zero.
	MinItems, MaxItems int
}

// NestingMode is an enumeration of modes for nesting blocks inside other
// blocks.
type NestingMode int

//go:generate stringer -type=NestingMode

const (
	nestingModeInvalid NestingMode = iota

	// NestingSingle indicates that only a single instance of a given
	// block type is permitted, with no labels, and its content should be
	// provided directly as an object value.
	NestingSingle

	// NestingList indicates that multiple blocks of the given type are
	// permitted, with no labels, and that their corresponding objects should
	// be provided in a list.
	NestingList

	// NestingSet indicates that multiple blocks of the given type are
	// permitted, with no labels, and that their corresponding objects should
	// be provided in a set.
	NestingSet

	// NestingMap indicates that multiple blocks of the given type are
	// permitted, each with a single label, and that their corresponding
	// objects should be provided in a map whose keys are the labels.
	//
	// It's an error, therefore, to use the same label value on multiple
	// blocks.
	NestingMap
)
<|endoftext|>


<commit_before>package jira

import (
	"fmt"
	"net/http"
)

const (
	// AssigneeAutomatic represents the value of the "Assignee: Automatic" of JIRA
	AssigneeAutomatic = "-1"
)

// IssueService handles Issues for the JIRA instance / API.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#d2e2279
type IssueService struct {
	client *Client
}

// Issue represents a JIRA issue.
type Issue struct {
	Expand string       `json:"expand,omitempty"`
	ID     string       `json:"id,omitempty"`
	Self   string       `json:"self,omitempty"`
	Key    string       `json:"key,omitempty"`
	Fields *IssueFields `json:"fields,omitempty"`
}

// IssueFields represents single fields of a JIRA issue.
// Every JIRA issue has several fields attached.
type IssueFields struct {
	// TODO Missing fields
	//	* "timespent": null,
	//	* "fixVersions": [],
	//	* "aggregatetimespent": null,
	//	* "workratio": -1,
	//	* "lastViewed": null,
	//	* "labels": [],
	//	* "timeestimate": null,
	//	* "aggregatetimeoriginalestimate": null,
	//	* "timeoriginalestimate": null,
	//	* "timetracking": {},
	//	* "attachment": [],
	//	* "aggregatetimeestimate": null,
	//	* "subtasks": [],
	//	* "environment": null,
	//	* "duedate": null,
	Type              IssueType    `json:"issuetype"`
	Project           Project      `json:"project,omitempty"`
	Resolution        *Resolution  `json:"resolution,omitempty"`
	Priority          *Priority    `json:"priority,omitempty"`
	Resolutiondate    string       `json:"resolutiondate,omitempty"`
	Created           string       `json:"created,omitempty"`
	Watches           *Watches     `json:"watches,omitempty"`
	Assignee          *Assignee    `json:"assignee,omitempty"`
	Updated           int          `json:"updated,omitempty"`
	Description       string       `json:"description,omitempty"`
	Summary           string       `json:"summary"`
	Creator           *Assignee    `json:"Creator,omitempty"`
	Reporter          *Assignee    `json:"reporter,omitempty"`
	Components        []*Component `json:"components,omitempty"`
	Status            *Status      `json:"status,omitempty"`
	Progress          *Progress    `json:"progress,omitempty"`
	AggregateProgress *Progress    `json:"aggregateprogress,omitempty"`
	Worklog           []*Worklog   `json:"worklog,omitempty"`
	IssueLinks        []*IssueLink `json:"issuelinks,omitempty"`
	Comments          []*Comment   `json:"comment,omitempty"`
}

// IssueType represents a type of a JIRA issue.
// Typical types are "Request", "Bug", "Story", ...
type IssueType struct {
	Self        string `json:"self,omitempty"`
	ID          string `json:"id,omitempty"`
	Description string `json:"description,omitempty"`
	IconURL     string `json:"iconUrl,omitempty"`
	Name        string `json:"name,omitempty"`
	Subtask     bool   `json:"subtask,omitempty"`
}

// Project represents a JIRA Project.
type Project struct {
	Self       string            `json:"self,omitempty"`
	ID         string            `json:"id,omitempty"`
	Key        string            `json:"key,omitempty"`
	Name       string            `json:"name,omitempty"`
	AvatarURLs map[string]string `json:"avatarUrls,omitempty"`
}

// Resolution represents a resolution of a JIRA issue.
// Typical types are "Fixed", "Suspended", "Won't Fix", ...
type Resolution struct {
	Self        string `json:"self"`
	ID          string `json:"id"`
	Description string `json:"description"`
	Name        string `json:"name"`
}

// Priority represents a priority of a JIRA issue.
// Typical types are "Normal", "Moderate", "Urgent", ...
type Priority struct {
	Self    string `json:"self,omitempty"`
	IconURL string `json:"iconUrl,omitempty"`
	Name    string `json:"name,omitempty"`
	ID      string `json:"id,omitempty"`
}

// Watches represents a type of how many user are "observing" a JIRA issue to track the status / updates.
type Watches struct {
	Self       string `json:"self,omitempty"`
	WatchCount int    `json:"watchCount,omitempty"`
	IsWatching bool   `json:"isWatching,omitempty"`
}

// Assignee represents a user who is this JIRA issue assigned to.
type Assignee struct {
	Self         string            `json:"self,omitempty"`
	Name         string            `json:"name,omitempty"`
	EmailAddress string            `json:"emailAddress,omitempty"`
	AvatarURLs   map[string]string `json:"avatarUrls,omitempty"`
	DisplayName  string            `json:"displayName,omitempty"`
	Active       bool              `json:"active,omitempty"`
}

// Component represents a "component" of a JIRA issue.
// Components can be user defined in every JIRA instance.
type Component struct {
	Self string `json:"self,omitempty"`
	ID   string `json:"id,omitempty"`
	Name string `json:"name,omitempty"`
}

// Status represents the current status of a JIRA issue.
// Typical status are "Open", "In Progress", "Closed", ...
// Status can be user defined in every JIRA instance.
type Status struct {
	Self           string         `json:"self"`
	Description    string         `json:"description"`
	IconURL        string         `json:"iconUrl"`
	Name           string         `json:"name"`
	ID             string         `json:"id"`
	StatusCategory StatusCategory `json:"statusCategory"`
}

// StatusCategory represents the category a status belongs to.
// Those categories can be user defined in every JIRA instance.
type StatusCategory struct {
	Self      string `json:"self"`
	ID        int    `json:"id"`
	Name      string `json:"name"`
	Key       string `json:"key"`
	ColorName string `json:"colorName"`
}

// Progress represents the progress of a JIRA issue.
type Progress struct {
	Progress int `json:"progress"`
	Total    int `json:"total"`
}

// Worklog represents the work log of a JIRA issue.
// JIRA Wiki: https://confluence.atlassian.com/jira/logging-work-on-an-issue-185729605.html
type Worklog struct {
	// TODO Add Worklogs
}

// IssueLink represents a link between two issues in JIRA.
type IssueLink struct {
	ID           string        `json:"id"`
	Self         string        `json:"self"`
	Type         IssueLinkType `json:"type"`
	OutwardIssue Issue         `json:"outwardIssue"`
	InwardIssue  Issue         `json:"inwardIssue"`
}

// IssueLinkType represents a type of a link between to issues in JIRA.
// Typical issue link types are "Related to", "Duplicate", "Is blocked by", etc.
type IssueLinkType struct {
	ID      string `json:"id"`
	Self    string `json:"self"`
	Name    string `json:"name"`
	Inward  string `json:"inward"`
	Outward string `json:"outward"`
}

// Comment represents a comment by a person to an issue in JIRA.
type Comment struct {
	Self         string   `json:"self"`
	Name         string   `json:"name"`
	Author       Assignee `json:"author"`
	Body         string   `json:"body"`
	UpdateAuthor Assignee `json:"updateAuthor"`
	Updated      string   `json:"updated"`
	Created      string   `json:"created"`
}

// Get returns a full representation of the issue for the given issue key.
// JIRA will attempt to identify the issue by the issueIdOrKey path parameter.
// This can be an issue id, or an issue key.
// If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#d2e2609
func (s *IssueService) Get(issueID string) (*Issue, *http.Response, error) {
	apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID)
	req, err := s.client.NewRequest("GET", apiEndpoint, nil)
	if err != nil {
		return nil, nil, err
	}

	issue := new(Issue)
	resp, err := s.client.Do(req, issue)
	if err != nil {
		return nil, resp, err
	}

	return issue, resp, nil
}

// Create creates an issue or a sub-task from a JSON representation.
// Creating a sub-task is similar to creating a regular issue, with two important differences:
// The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#d2e2280
func (s *IssueService) Create(issue *Issue) (*Issue, *http.Response, error) {
	apiEndpoint := "rest/api/2/issue/"
	req, err := s.client.NewRequest("POST", apiEndpoint, issue)
	if err != nil {
		return nil, nil, err
	}

	responseIssue := new(Issue)
	resp, err := s.client.Do(req, responseIssue)
	if err != nil {
		return nil, resp, err
	}

	return responseIssue, resp, nil
}
<commit_msg>Add FixVersions to IssueFields - Thanks to @dimfeld<commit_after>package jira

import (
	"fmt"
	"net/http"
)

const (
	// AssigneeAutomatic represents the value of the "Assignee: Automatic" of JIRA
	AssigneeAutomatic = "-1"
)

// IssueService handles Issues for the JIRA instance / API.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#d2e2279
type IssueService struct {
	client *Client
}

// Issue represents a JIRA issue.
type Issue struct {
	Expand string       `json:"expand,omitempty"`
	ID     string       `json:"id,omitempty"`
	Self   string       `json:"self,omitempty"`
	Key    string       `json:"key,omitempty"`
	Fields *IssueFields `json:"fields,omitempty"`
}

// IssueFields represents single fields of a JIRA issue.
// Every JIRA issue has several fields attached.
type IssueFields struct {
	// TODO Missing fields
	//	* "timespent": null,
	//	* "aggregatetimespent": null,
	//	* "workratio": -1,
	//	* "lastViewed": null,
	//	* "labels": [],
	//	* "timeestimate": null,
	//	* "aggregatetimeoriginalestimate": null,
	//	* "timeoriginalestimate": null,
	//	* "timetracking": {},
	//	* "attachment": [],
	//	* "aggregatetimeestimate": null,
	//	* "subtasks": [],
	//	* "environment": null,
	//	* "duedate": null,
	Type              IssueType    `json:"issuetype"`
	Project           Project      `json:"project,omitempty"`
	Resolution        *Resolution  `json:"resolution,omitempty"`
	Priority          *Priority    `json:"priority,omitempty"`
	Resolutiondate    string       `json:"resolutiondate,omitempty"`
	Created           string       `json:"created,omitempty"`
	Watches           *Watches     `json:"watches,omitempty"`
	Assignee          *Assignee    `json:"assignee,omitempty"`
	Updated           int          `json:"updated,omitempty"`
	Description       string       `json:"description,omitempty"`
	Summary           string       `json:"summary"`
	Creator           *Assignee    `json:"Creator,omitempty"`
	Reporter          *Assignee    `json:"reporter,omitempty"`
	Components        []*Component `json:"components,omitempty"`
	Status            *Status      `json:"status,omitempty"`
	Progress          *Progress    `json:"progress,omitempty"`
	AggregateProgress *Progress    `json:"aggregateprogress,omitempty"`
	Worklog           []*Worklog   `json:"worklog,omitempty"`
	IssueLinks        []*IssueLink `json:"issuelinks,omitempty"`
	Comments          []*Comment   `json:"comment,omitempty"`
	FixVersions       []*FixVersion `json:"fixVersions,omitempty"`
}

// IssueType represents a type of a JIRA issue.
// Typical types are "Request", "Bug", "Story", ...
type IssueType struct {
	Self        string `json:"self,omitempty"`
	ID          string `json:"id,omitempty"`
	Description string `json:"description,omitempty"`
	IconURL     string `json:"iconUrl,omitempty"`
	Name        string `json:"name,omitempty"`
	Subtask     bool   `json:"subtask,omitempty"`
}

// Project represents a JIRA Project.
type Project struct {
	Self       string            `json:"self,omitempty"`
	ID         string            `json:"id,omitempty"`
	Key        string            `json:"key,omitempty"`
	Name       string            `json:"name,omitempty"`
	AvatarURLs map[string]string `json:"avatarUrls,omitempty"`
}

// Resolution represents a resolution of a JIRA issue.
// Typical types are "Fixed", "Suspended", "Won't Fix", ...
type Resolution struct {
	Self        string `json:"self"`
	ID          string `json:"id"`
	Description string `json:"description"`
	Name        string `json:"name"`
}

// Priority represents a priority of a JIRA issue.
// Typical types are "Normal", "Moderate", "Urgent", ...
type Priority struct {
	Self    string `json:"self,omitempty"`
	IconURL string `json:"iconUrl,omitempty"`
	Name    string `json:"name,omitempty"`
	ID      string `json:"id,omitempty"`
}

// Watches represents a type of how many user are "observing" a JIRA issue to track the status / updates.
type Watches struct {
	Self       string `json:"self,omitempty"`
	WatchCount int    `json:"watchCount,omitempty"`
	IsWatching bool   `json:"isWatching,omitempty"`
}

// Assignee represents a user who is this JIRA issue assigned to.
type Assignee struct {
	Self         string            `json:"self,omitempty"`
	Name         string            `json:"name,omitempty"`
	EmailAddress string            `json:"emailAddress,omitempty"`
	AvatarURLs   map[string]string `json:"avatarUrls,omitempty"`
	DisplayName  string            `json:"displayName,omitempty"`
	Active       bool              `json:"active,omitempty"`
}

// Component represents a "component" of a JIRA issue.
// Components can be user defined in every JIRA instance.
type Component struct {
	Self string `json:"self,omitempty"`
	ID   string `json:"id,omitempty"`
	Name string `json:"name,omitempty"`
}

// Status represents the current status of a JIRA issue.
// Typical status are "Open", "In Progress", "Closed", ...
// Status can be user defined in every JIRA instance.
type Status struct {
	Self           string         `json:"self"`
	Description    string         `json:"description"`
	IconURL        string         `json:"iconUrl"`
	Name           string         `json:"name"`
	ID             string         `json:"id"`
	StatusCategory StatusCategory `json:"statusCategory"`
}

// StatusCategory represents the category a status belongs to.
// Those categories can be user defined in every JIRA instance.
type StatusCategory struct {
	Self      string `json:"self"`
	ID        int    `json:"id"`
	Name      string `json:"name"`
	Key       string `json:"key"`
	ColorName string `json:"colorName"`
}

// Progress represents the progress of a JIRA issue.
type Progress struct {
	Progress int `json:"progress"`
	Total    int `json:"total"`
}

// Worklog represents the work log of a JIRA issue.
// JIRA Wiki: https://confluence.atlassian.com/jira/logging-work-on-an-issue-185729605.html
type Worklog struct {
	// TODO Add Worklogs
}

// IssueLink represents a link between two issues in JIRA.
type IssueLink struct {
	ID           string        `json:"id"`
	Self         string        `json:"self"`
	Type         IssueLinkType `json:"type"`
	OutwardIssue Issue         `json:"outwardIssue"`
	InwardIssue  Issue         `json:"inwardIssue"`
}

// IssueLinkType represents a type of a link between to issues in JIRA.
// Typical issue link types are "Related to", "Duplicate", "Is blocked by", etc.
type IssueLinkType struct {
	ID      string `json:"id"`
	Self    string `json:"self"`
	Name    string `json:"name"`
	Inward  string `json:"inward"`
	Outward string `json:"outward"`
}

// Comment represents a comment by a person to an issue in JIRA.
type Comment struct {
	Self         string   `json:"self"`
	Name         string   `json:"name"`
	Author       Assignee `json:"author"`
	Body         string   `json:"body"`
	UpdateAuthor Assignee `json:"updateAuthor"`
	Updated      string   `json:"updated"`
	Created      string   `json:"created"`
}

// FixVersion represents a software release in which an issue is fixed.
type FixVersion struct {
	Archived        *bool  `json:"archived,omitempty"`
	ID              string `json:"id,omitempty"`
	Name            string `json:"name,omitempty"`
	ProjectID       int    `json:"projectId,omitempty"`
	ReleaseDate     string `json:"releaseDate,omitempty"`
	Released        *bool  `json:"released,omitempty"`
	Self            string `json:"self,omitempty"`
	UserReleaseDate string `json:"userReleaseDate,omitempty"`
}

// Get returns a full representation of the issue for the given issue key.
// JIRA will attempt to identify the issue by the issueIdOrKey path parameter.
// This can be an issue id, or an issue key.
// If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#d2e2609
func (s *IssueService) Get(issueID string) (*Issue, *http.Response, error) {
	apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID)
	req, err := s.client.NewRequest("GET", apiEndpoint, nil)
	if err != nil {
		return nil, nil, err
	}

	issue := new(Issue)
	resp, err := s.client.Do(req, issue)
	if err != nil {
		return nil, resp, err
	}

	return issue, resp, nil
}

// Create creates an issue or a sub-task from a JSON representation.
// Creating a sub-task is similar to creating a regular issue, with two important differences:
// The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#d2e2280
func (s *IssueService) Create(issue *Issue) (*Issue, *http.Response, error) {
	apiEndpoint := "rest/api/2/issue/"
	req, err := s.client.NewRequest("POST", apiEndpoint, issue)
	if err != nil {
		return nil, nil, err
	}

	responseIssue := new(Issue)
	resp, err := s.client.Do(req, responseIssue)
	if err != nil {
		return nil, resp, err
	}

	return responseIssue, resp, nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"log"
	"os/user"
	"path/filepath"
	"time"

	"github.com/ecc1/dexcom"
	_ "github.com/mattn/go-sqlite3"
)

const (
	dbName = "glucose.db"
)

func main() {
	err := dexcom.Open()
	if err != nil {
		log.Fatal(err)
	}
	db := OpenDB()
	xact, err := db.Begin()
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	stmt, err := xact.Prepare("insert into glucose values (?, ?)")
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	n := 0
	proc := func(v []byte, _ dexcom.RecordContext) error {
		r := dexcom.EGVRecord{}
		err := r.Unmarshal(v)
		if err != nil {
			return err
		}
		_, err = stmt.Exec(glucoseRow(r))
		if err != nil {
			return err
		}
		fmt.Print(".")
		n++
		if n%80 == 0 {
			fmt.Println()
		}
		return nil
	}
	err = dexcom.ReadRecords(dexcom.EGV_DATA, proc)
	if n%80 != 0 {
		fmt.Println()
	}
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	xact.Commit()
	db.Close()
}

func OpenDB() *sql.DB {
	u, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	home := u.HomeDir
	db, err := sql.Open("sqlite3", filepath.Join(home, dbName))
	if err != nil {
		log.Fatal(err)
	}
	// use integer (Unix time); datetime type stores value as a string
	stmt := `
	  create table if not exists glucose
	    (time integer primary key on conflict ignore,
	     value integer)
	`
	_, err = db.Exec(stmt)
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	return db
}

// glucoseRow returns the time and glucose value from an EGVRecord
// suitable for inserting into the database.
func glucoseRow(egv dexcom.EGVRecord) (int64, uint16) {
	return egv.Timestamp.DisplayTime.Round(time.Second).Unix(), egv.Glucose
}
<commit_msg>Use ReadEgvRecords function<commit_after>package main

import (
	"database/sql"
	"log"
	"os/user"
	"path/filepath"
	"time"

	"github.com/ecc1/dexcom"
	_ "github.com/mattn/go-sqlite3"
)

const (
	dbName = "glucose.db"
)

func main() {
	db := OpenDB()
	xact, err := db.Begin()
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	err = dexcom.Open()
	if err != nil {
		log.Fatal(err)
	}
	egv, err := dexcom.ReadEgvRecords(time.Time{})
	if err != nil {
		log.Fatal(err)
	}
	stmt, err := xact.Prepare("insert into glucose values (?, ?)")
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	for _, r := range egv {
		_, err = stmt.Exec(glucoseRow(r))
		if err != nil {
			db.Close()
			log.Fatal(err)
		}
	}
	xact.Commit()
	db.Close()
}

func OpenDB() *sql.DB {
	u, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	home := u.HomeDir
	db, err := sql.Open("sqlite3", filepath.Join(home, dbName))
	if err != nil {
		log.Fatal(err)
	}
	// use integer (Unix time); datetime type stores value as a string
	stmt := `
	  create table if not exists glucose
	    (time integer primary key on conflict ignore,
	     value integer)
	`
	_, err = db.Exec(stmt)
	if err != nil {
		db.Close()
		log.Fatal(err)
	}
	return db
}

// glucoseRow returns the time and glucose value from an EGVRecord
// suitable for inserting into the database.
func glucoseRow(egv dexcom.EgvRecord) (int64, uint16) {
	t := egv.Timestamp.DisplayTime
	return t.Unix(), egv.Glucose
}
<|endoftext|>


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

package maas

import (
	"net/http"

	"github.com/juju/errors"
	"github.com/juju/gomaasapi"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

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

type fakeController struct {
	gomaasapi.Controller
}

func (fakeController) BootResources() ([]gomaasapi.BootResource, error) {
	return nil, errors.New("Something terrible!")
}

type maas2EnvironSuite struct {
	controllerSuite
}

var _ = gc.Suite(&maas2EnvironSuite{})

func makeEnviron(c *gc.C) *maasEnviron {
	testAttrs := coretesting.Attrs{}
	for k, v := range maasEnvAttrs {
		testAttrs[k] = v
	}
	testAttrs["maas-server"] = "http://any-old-junk.invalid/"
	attrs := coretesting.FakeConfig().Merge(testAttrs)
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, jc.ErrorIsNil)
	env, err := NewEnviron(cfg)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(env, gc.NotNil)
	return env
}

func (suite *maas2EnvironSuite) TestNewEnvironWithController(c *gc.C) {
	testServer := gomaasapi.NewSimpleServer()
	testServer.AddResponse("/api/2.0/version/", http.StatusOK, maas2VersionResponse)
	testServer.Start()
	defer testServer.Close()
	testAttrs := coretesting.Attrs{}
	for k, v := range maasEnvAttrs {
		testAttrs[k] = v
	}
	testAttrs["maas-server"] = testServer.Server.URL
	attrs := coretesting.FakeConfig().Merge(testAttrs)
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, jc.ErrorIsNil)
	env, err := NewEnviron(cfg)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(env, gc.NotNil)
}

func (suite *maas2EnvironSuite) TestSupportedArchitectures(c *gc.C) {
}

func (suite *maas2EnvironSuite) TestSupportedArchitecturesError(c *gc.C) {
	mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) {
		return fakeController{}, nil
	}
	suite.PatchValue(&GetMAAS2Controller, mockGetController)
	env := makeEnviron(c)
	_, err := env.SupportedArchitectures()
	c.Assert(err, gc.ErrorMatches, "Something terrible!")
}
<commit_msg>Add test for maasEnviron.SupportedArchitectures with MAAS 2<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package maas

import (
	"net/http"

	"github.com/juju/errors"
	"github.com/juju/gomaasapi"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

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

type fakeController struct {
	gomaasapi.Controller
	bootResources      []gomaasapi.BootResource
	bootResourcesError error
}

func (c *fakeController) BootResources() ([]gomaasapi.BootResource, error) {
	if c.bootResourcesError != nil {
		return nil, c.bootResourcesError
	}
	return c.bootResources, nil
}

type fakeBootResource struct {
	gomaasapi.BootResource
	name         string
	architecture string
}

func (r *fakeBootResource) Name() string {
	return r.name
}

func (r *fakeBootResource) Architecture() string {
	return r.architecture
}

type maas2EnvironSuite struct {
	controllerSuite
}

var _ = gc.Suite(&maas2EnvironSuite{})

func makeEnviron(c *gc.C) *maasEnviron {
	testAttrs := coretesting.Attrs{}
	for k, v := range maasEnvAttrs {
		testAttrs[k] = v
	}
	testAttrs["maas-server"] = "http://any-old-junk.invalid/"
	attrs := coretesting.FakeConfig().Merge(testAttrs)
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, jc.ErrorIsNil)
	env, err := NewEnviron(cfg)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(env, gc.NotNil)
	return env
}

func (suite *maas2EnvironSuite) TestNewEnvironWithController(c *gc.C) {
	testServer := gomaasapi.NewSimpleServer()
	testServer.AddResponse("/api/2.0/version/", http.StatusOK, maas2VersionResponse)
	testServer.Start()
	defer testServer.Close()
	testAttrs := coretesting.Attrs{}
	for k, v := range maasEnvAttrs {
		testAttrs[k] = v
	}
	testAttrs["maas-server"] = testServer.Server.URL
	attrs := coretesting.FakeConfig().Merge(testAttrs)
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, jc.ErrorIsNil)
	env, err := NewEnviron(cfg)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(env, gc.NotNil)
}

func (suite *maas2EnvironSuite) TestSupportedArchitectures(c *gc.C) {
	mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) {
		controller := fakeController{
			bootResources: []gomaasapi.BootResource{
				&fakeBootResource{name: "wily", architecture: "amd64/blah"},
				&fakeBootResource{name: "wily", architecture: "amd64/something"},
				&fakeBootResource{name: "xenial", architecture: "arm/somethingelse"},
			},
		}
		return &controller, nil
	}
	suite.PatchValue(&GetMAAS2Controller, mockGetController)
	env := makeEnviron(c)
	result, err := env.SupportedArchitectures()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, []string{"amd64", "arm"})
}

func (suite *maas2EnvironSuite) TestSupportedArchitecturesError(c *gc.C) {
	mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) {
		return &fakeController{bootResourcesError: errors.New("Something terrible!")}, nil
	}
	suite.PatchValue(&GetMAAS2Controller, mockGetController)
	env := makeEnviron(c)
	_, err := env.SupportedArchitectures()
	c.Assert(err, gc.ErrorMatches, "Something terrible!")
}
<|endoftext|>


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

package lib

import (
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"time"

	"crypto/tls"

	"github.com/fatih/color"
	"golang.org/x/crypto/ocsp"
)

type simpleVerifyCert struct {
	Name               string `json:"name"`
	IsSelfSigned       bool   `json:"is_self_signed"`
	PEM                string `json:"pem"`
	signatureAlgorithm x509.SignatureAlgorithm
}

type SimpleVerification struct {
	Error      string               `json:"error,omitempty"`
	OCSPStatus *ocsp.Response       `json:"ocsp_response,omitempty"`
	OCSPError  string               `json:"ocsp_error,omitempty"`
	Chains     [][]simpleVerifyCert `json:"chains"`
}

type SimpleResult struct {
	Certificates           []*x509.Certificate `json:"certificates"`
	VerifyResult           *SimpleVerification `json:"verify_result,omitempty"`
	TLSConnectionState     *tls.ConnectionState
	CertificateRequestInfo *tls.CertificateRequestInfo
}

func (s SimpleResult) MarshalJSON() ([]byte, error) {
	certs := make([]interface{}, len(s.Certificates))
	for i, c := range s.Certificates {
		certs[i] = EncodeX509ToObject(c)
	}

	out := map[string]interface{}{}
	out["certificates"] = certs
	if s.VerifyResult != nil {
		out["verify_result"] = s.VerifyResult
	}
	if s.TLSConnectionState != nil {
		out["tls_connection"] = EncodeTLSToObject(s.TLSConnectionState)
	}
	if s.CertificateRequestInfo != nil {
		encoded, err := EncodeCRIToObject(s.CertificateRequestInfo)
		if err != nil {
			return nil, err
		}
		out["certificate_request_info"] = encoded
	}
	return json.Marshal(out)
}

func caBundle(caPath string) *x509.CertPool {
	if caPath == "" {
		return nil
	}

	bundleBytes, err := ioutil.ReadFile(caPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error reading CA bundle: %s\n", err)
		os.Exit(1)
	}

	bundle := x509.NewCertPool()
	bundle.AppendCertsFromPEM(bundleBytes)
	return bundle
}

func VerifyChain(certs []*x509.Certificate, ocspStaple []byte, dnsName, caPath string) SimpleVerification {
	result := SimpleVerification{
		Chains: [][]simpleVerifyCert{},
	}

	intermediates := x509.NewCertPool()
	for i := 1; i < len(certs); i++ {
		intermediates.AddCert(certs[i])
	}

	opts := x509.VerifyOptions{
		DNSName:       dnsName,
		Roots:         caBundle(caPath),
		Intermediates: intermediates,
	}

	chains, err := certs[0].Verify(opts)
	if err != nil {
		result.Error = fmt.Sprintf("%s", err)
		return result
	}

	for _, chain := range chains {
		status, err := checkOCSP(chain, ocspStaple)
		if err == nil {
			result.OCSPStatus = status
		}
		if err != nil && err != skippedRevocationCheck {
			result.OCSPError = err.Error()
		}

		aChain := []simpleVerifyCert{}
		for _, cert := range chain {
			aCert := simpleVerifyCert{
				IsSelfSigned:       IsSelfSigned(cert),
				signatureAlgorithm: cert.SignatureAlgorithm,
				PEM:                string(pem.EncodeToMemory(EncodeX509ToPEM(cert, nil))),
			}

			aCert.Name = PrintCommonName(cert.Subject)
			aChain = append(aChain, aCert)
		}
		result.Chains = append(result.Chains, aChain)
	}
	return result
}

func fmtCert(cert simpleVerifyCert) string {
	name := cert.Name
	if cert.IsSelfSigned {
		name += green.SprintfFunc()(" [self-signed]")
	}
	for _, alg := range badSignatureAlgorithms {
		if cert.signatureAlgorithm == alg {
			name += red.SprintfFunc()(" [%s]", algString(alg))
			break
		}
	}
	return name
}

func PrintVerifyResult(out io.Writer, result SimpleVerification) {
	if result.Error != "" {
		fmt.Fprintf(out, red.SprintfFunc()("Failed to verify certificate chain:\n"))
		fmt.Fprintf(out, "\t%s\n", result.Error)
		return
	}
	if result.OCSPError != "" {
		fmt.Fprintf(out, red.SprintfFunc()("Certificate has OCSP servers, but was unable to check status:\n"))
		fmt.Fprintf(out, "\t%s\n\n", result.OCSPError)
	} else if result.OCSPStatus != nil {
		var text string
		var color *color.Color
		switch result.OCSPStatus.Status {
		case ocsp.Good:
			text = "Good"
			color = green
		case ocsp.Revoked:
			text = "Revoked"
			color = red
		default:
			text = "Unknown"
			color = yellow
		}
		fmt.Fprintf(out, color.SprintfFunc()("Checked OCSP status for certificate, got status:"))
		fmt.Fprintf(out, "\n\t%s (last update: %s)\n\n", text, result.OCSPStatus.ProducedAt.Format(time.UnixDate))
	}
	fmt.Fprintf(out, green.SprintfFunc()("Found %d valid certificate chain(s):\n", len(result.Chains)))
	for i, chain := range result.Chains {
		fmt.Fprintf(out, "[%d] %s\n", i, fmtCert(chain[0]))
		for j, cert := range chain {
			if j == 0 {
				continue
			}
			fmt.Fprintf(out, "\t=> %s\n", fmtCert(cert))
		}
	}
}
<commit_msg>Support any format certigo does for CAs.<commit_after>/*-
 * Copyright 2016 Square Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package lib

import (
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"io"
	"os"
	"time"

	"crypto/tls"

	"github.com/fatih/color"
	"golang.org/x/crypto/ocsp"
)

type simpleVerifyCert struct {
	Name               string `json:"name"`
	IsSelfSigned       bool   `json:"is_self_signed"`
	PEM                string `json:"pem"`
	signatureAlgorithm x509.SignatureAlgorithm
}

type SimpleVerification struct {
	Error      string               `json:"error,omitempty"`
	OCSPStatus *ocsp.Response       `json:"ocsp_response,omitempty"`
	OCSPError  string               `json:"ocsp_error,omitempty"`
	Chains     [][]simpleVerifyCert `json:"chains"`
}

type SimpleResult struct {
	Certificates           []*x509.Certificate `json:"certificates"`
	VerifyResult           *SimpleVerification `json:"verify_result,omitempty"`
	TLSConnectionState     *tls.ConnectionState
	CertificateRequestInfo *tls.CertificateRequestInfo
}

func (s SimpleResult) MarshalJSON() ([]byte, error) {
	certs := make([]interface{}, len(s.Certificates))
	for i, c := range s.Certificates {
		certs[i] = EncodeX509ToObject(c)
	}

	out := map[string]interface{}{}
	out["certificates"] = certs
	if s.VerifyResult != nil {
		out["verify_result"] = s.VerifyResult
	}
	if s.TLSConnectionState != nil {
		out["tls_connection"] = EncodeTLSToObject(s.TLSConnectionState)
	}
	if s.CertificateRequestInfo != nil {
		encoded, err := EncodeCRIToObject(s.CertificateRequestInfo)
		if err != nil {
			return nil, err
		}
		out["certificate_request_info"] = encoded
	}
	return json.Marshal(out)
}

func caBundle(caPath string) *x509.CertPool {
	if caPath == "" {
		return nil
	}

	caFile, err := os.Open(caPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error opening CA bundle %s: %s\n", caPath, err)
		os.Exit(1)
	}

	bundle := x509.NewCertPool()
	err = ReadAsX509FromFiles(
		[]*os.File{caFile},
		"",
		func(prompt string) string {
			// TODO: The JDK trust store ships with this password.
			return "changeit"
		},
		func(cert *x509.Certificate, err error) {
			if err != nil {
				fmt.Fprintf(os.Stderr, "error parsing CA bundle: %s\n", err)
			} else {
				bundle.AddCert(cert)
			}
		})
	if err != nil {
		fmt.Fprintf(os.Stderr, "error parsing CA bundle: %s\n", err)
		os.Exit(1)
	}
	return bundle
}

func VerifyChain(certs []*x509.Certificate, ocspStaple []byte, dnsName, caPath string) SimpleVerification {
	result := SimpleVerification{
		Chains: [][]simpleVerifyCert{},
	}

	intermediates := x509.NewCertPool()
	for i := 1; i < len(certs); i++ {
		intermediates.AddCert(certs[i])
	}

	opts := x509.VerifyOptions{
		DNSName:       dnsName,
		Roots:         caBundle(caPath),
		Intermediates: intermediates,
	}

	chains, err := certs[0].Verify(opts)
	if err != nil {
		result.Error = fmt.Sprintf("%s", err)
		return result
	}

	for _, chain := range chains {
		status, err := checkOCSP(chain, ocspStaple)
		if err == nil {
			result.OCSPStatus = status
		}
		if err != nil && err != skippedRevocationCheck {
			result.OCSPError = err.Error()
		}

		aChain := []simpleVerifyCert{}
		for _, cert := range chain {
			aCert := simpleVerifyCert{
				IsSelfSigned:       IsSelfSigned(cert),
				signatureAlgorithm: cert.SignatureAlgorithm,
				PEM:                string(pem.EncodeToMemory(EncodeX509ToPEM(cert, nil))),
			}

			aCert.Name = PrintCommonName(cert.Subject)
			aChain = append(aChain, aCert)
		}
		result.Chains = append(result.Chains, aChain)
	}
	return result
}

func fmtCert(cert simpleVerifyCert) string {
	name := cert.Name
	if cert.IsSelfSigned {
		name += green.SprintfFunc()(" [self-signed]")
	}
	for _, alg := range badSignatureAlgorithms {
		if cert.signatureAlgorithm == alg {
			name += red.SprintfFunc()(" [%s]", algString(alg))
			break
		}
	}
	return name
}

func PrintVerifyResult(out io.Writer, result SimpleVerification) {
	if result.Error != "" {
		fmt.Fprintf(out, red.SprintfFunc()("Failed to verify certificate chain:\n"))
		fmt.Fprintf(out, "\t%s\n", result.Error)
		return
	}
	if result.OCSPError != "" {
		fmt.Fprintf(out, red.SprintfFunc()("Certificate has OCSP servers, but was unable to check status:\n"))
		fmt.Fprintf(out, "\t%s\n\n", result.OCSPError)
	} else if result.OCSPStatus != nil {
		var text string
		var color *color.Color
		switch result.OCSPStatus.Status {
		case ocsp.Good:
			text = "Good"
			color = green
		case ocsp.Revoked:
			text = "Revoked"
			color = red
		default:
			text = "Unknown"
			color = yellow
		}
		fmt.Fprintf(out, color.SprintfFunc()("Checked OCSP status for certificate, got status:"))
		fmt.Fprintf(out, "\n\t%s (last update: %s)\n\n", text, result.OCSPStatus.ProducedAt.Format(time.UnixDate))
	}
	fmt.Fprintf(out, green.SprintfFunc()("Found %d valid certificate chain(s):\n", len(result.Chains)))
	for i, chain := range result.Chains {
		fmt.Fprintf(out, "[%d] %s\n", i, fmtCert(chain[0]))
		for j, cert := range chain {
			if j == 0 {
				continue
			}
			fmt.Fprintf(out, "\t=> %s\n", fmtCert(cert))
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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 !js

package oto

import (
	"errors"
	"runtime"
	"unsafe"
)

type header struct {
	buffer  []byte
	waveHdr *wavehdr
}

func newHeader(waveOut uintptr, bufferSize int) (*header, error) {
	h := &header{
		buffer: make([]byte, bufferSize),
	}
	h.waveHdr = &wavehdr{
		lpData:         uintptr(unsafe.Pointer(&h.buffer[0])),
		dwBufferLength: uint32(bufferSize),
	}
	if err := waveOutPrepareHeader(waveOut, h.waveHdr); err != nil {
		return nil, err
	}
	return h, nil
}

func (h *header) Write(waveOut uintptr, data []byte) error {
	if len(data) != len(h.buffer) {
		return errors.New("oto: len(data) must equal to len(h.buffer)")
	}
	copy(h.buffer, data)
	if err := waveOutWrite(waveOut, h.waveHdr); err != nil {
		return err
	}
	return nil
}

type player struct {
	out        uintptr
	headers    []*header
	tmp        []byte
	bufferSize int
}

func newPlayer(sampleRate, channelNum, bytesPerSample, bufferSizeInBytes int) (*player, error) {
	numBlockAlign := channelNum * bytesPerSample
	f := &waveformatex{
		wFormatTag:      waveFormatPCM,
		nChannels:       uint16(channelNum),
		nSamplesPerSec:  uint32(sampleRate),
		nAvgBytesPerSec: uint32(sampleRate * numBlockAlign),
		wBitsPerSample:  uint16(bytesPerSample * 8),
		nBlockAlign:     uint16(numBlockAlign),
	}
	w, err := waveOutOpen(f)
	if err != nil {
		return nil, err
	}

	const numBufs = 2
	p := &player{
		out:        w,
		headers:    make([]*header, numBufs),
		bufferSize: bufferSizeInBytes,
	}
	runtime.SetFinalizer(p, (*player).Close)
	for i := range p.headers {
		var err error
		p.headers[i], err = newHeader(w, p.bufferSize)
		if err != nil {
			return nil, err
		}
	}
	return p, nil
}

func (p *player) TryWrite(data []byte) (int, error) {
	n := min(len(data), max(0, p.bufferSize-len(p.tmp)))
	p.tmp = append(p.tmp, data[:n]...)
	if len(p.tmp) < p.bufferSize {
		return n, nil
	}

	var headerToWrite *header
	for _, h := range p.headers {
		// TODO: Need to check WHDR_DONE?
		if h.waveHdr.dwFlags&whdrInqueue == 0 {
			headerToWrite = h
			break
		}
	}
	if headerToWrite == nil {
		return n, nil
	}

	if err := headerToWrite.Write(p.out, p.tmp); err != nil {
		return 0, err
	}

	p.tmp = nil
	return n, nil
}

func (p *player) Close() error {
	runtime.SetFinalizer(p, nil)
	// TODO: Call waveOutUnprepareHeader here
	if err := waveOutClose(p.out); err != nil {
		return err
	}
	return nil
}
<commit_msg>windows: Ignore waveoutWrite's not-found error<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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 !js

package oto

import (
	"errors"
	"runtime"
	"unsafe"
)

type header struct {
	buffer  []byte
	waveHdr *wavehdr
}

func newHeader(waveOut uintptr, bufferSize int) (*header, error) {
	h := &header{
		buffer: make([]byte, bufferSize),
	}
	h.waveHdr = &wavehdr{
		lpData:         uintptr(unsafe.Pointer(&h.buffer[0])),
		dwBufferLength: uint32(bufferSize),
	}
	if err := waveOutPrepareHeader(waveOut, h.waveHdr); err != nil {
		return nil, err
	}
	return h, nil
}

func (h *header) Write(waveOut uintptr, data []byte) error {
	if len(data) != len(h.buffer) {
		return errors.New("oto: len(data) must equal to len(h.buffer)")
	}
	copy(h.buffer, data)
	if err := waveOutWrite(waveOut, h.waveHdr); err != nil {
		return err
	}
	return nil
}

type player struct {
	out        uintptr
	headers    []*header
	tmp        []byte
	bufferSize int
}

func newPlayer(sampleRate, channelNum, bytesPerSample, bufferSizeInBytes int) (*player, error) {
	numBlockAlign := channelNum * bytesPerSample
	f := &waveformatex{
		wFormatTag:      waveFormatPCM,
		nChannels:       uint16(channelNum),
		nSamplesPerSec:  uint32(sampleRate),
		nAvgBytesPerSec: uint32(sampleRate * numBlockAlign),
		wBitsPerSample:  uint16(bytesPerSample * 8),
		nBlockAlign:     uint16(numBlockAlign),
	}
	w, err := waveOutOpen(f)
	if err != nil {
		return nil, err
	}

	const numBufs = 2
	p := &player{
		out:        w,
		headers:    make([]*header, numBufs),
		bufferSize: bufferSizeInBytes,
	}
	runtime.SetFinalizer(p, (*player).Close)
	for i := range p.headers {
		var err error
		p.headers[i], err = newHeader(w, p.bufferSize)
		if err != nil {
			return nil, err
		}
	}
	return p, nil
}

func (p *player) TryWrite(data []byte) (int, error) {
	n := min(len(data), max(0, p.bufferSize-len(p.tmp)))
	p.tmp = append(p.tmp, data[:n]...)
	if len(p.tmp) < p.bufferSize {
		return n, nil
	}

	var headerToWrite *header
	for _, h := range p.headers {
		// TODO: Need to check WHDR_DONE?
		if h.waveHdr.dwFlags&whdrInqueue == 0 {
			headerToWrite = h
			break
		}
	}
	if headerToWrite == nil {
		return n, nil
	}

	if err := headerToWrite.Write(p.out, p.tmp); err != nil {
		// This error can happen when e.g. a new HDMI connection is detected (#51).
		const errorNotFound = 1168
		werr := err.(*winmmError)
		if werr.fname == "waveOutWrite" && werr.errno == errorNotFound {
			return 0, nil
		}
		return 0, err
	}

	p.tmp = nil
	return n, nil
}

func (p *player) Close() error {
	runtime.SetFinalizer(p, nil)
	// TODO: Call waveOutUnprepareHeader here
	if err := waveOutClose(p.out); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package plugin

import (
	"crypto/rand"
	"encoding/json"
	"fmt"
	"net"
	"os"

	"github.com/containernetworking/cni/pkg/ipam"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	weaveapi "github.com/weaveworks/weave/api"
	weavenet "github.com/weaveworks/weave/net"
	ipamplugin "github.com/weaveworks/weave/plugin/ipam"
)

var (
	zeroNetwork = net.IPNet{IP: net.IPv4zero, Mask: net.IPv4Mask(0, 0, 0, 0)}
	mask32      = net.IPv4Mask(0xff, 0xff, 0xff, 0xff)
)

type CNIPlugin struct {
	weave *weaveapi.Client
}

func NewCNIPlugin(weave *weaveapi.Client) *CNIPlugin {
	return &CNIPlugin{weave: weave}
}

func loadNetConf(bytes []byte) (*NetConf, error) {
	n := &NetConf{
		BrName:      weavenet.WeaveBridgeName,
		HairpinMode: true,
	}
	if err := json.Unmarshal(bytes, n); err != nil {
		return nil, fmt.Errorf("failed to load netconf: %v", err)
	}
	return n, nil
}

func (c *CNIPlugin) getIP(ipamType string, args *skel.CmdArgs) (newResult *current.Result, err error) {
	var result types.Result
	// Default IPAM is Weave's own
	if ipamType == "" {
		result, err = ipamplugin.NewIpam(c.weave).Allocate(args)
	} else {
		result, err = ipam.ExecAdd(ipamType, args.StdinData)
	}
	if err != nil {
		return nil, err
	}
	if result == nil {
		return nil, fmt.Errorf("Received no usable result from IPAM plugin")
	}
	newResult, err = current.NewResultFromResult(result)
	// Check if ipam returned no results without error
	if err == nil && len(newResult.IPs) == 0 {
		return nil, fmt.Errorf("IPAM plugin failed to allocate IP address")
	}
	return newResult, err
}

func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
	conf, err := loadNetConf(args.StdinData)
	if err != nil {
		return err
	}

	if conf.IsGW {
		return fmt.Errorf("Gateway functionality not supported")
	}
	if conf.IPMasq {
		return fmt.Errorf("IP Masquerading functionality not supported")
	}

	result, err := c.getIP(conf.IPAM.Type, args)
	if err != nil {
		return fmt.Errorf("unable to allocate IP address: %s", err)
	}
	// Only expecting one address
	ip := result.IPs[0]

	// If config says nothing about routes or gateway, default one will be via the bridge
	if len(result.Routes) == 0 && ip.Gateway == nil {
		bridgeIP, err := weavenet.FindBridgeIP(conf.BrName, &ip.Address)
		if err == weavenet.ErrBridgeNoIP {
			bridgeArgs := *args
			bridgeArgs.ContainerID = "weave:expose"
			// It would be better if libcni let us send just the desired parameters,
			// but there is a bug: https://github.com/containernetworking/cni/issues/410
			// so just blank out the one we want to change
			os.Setenv("CNI_CONTAINERID", bridgeArgs.ContainerID)
			bridgeIPResult, err := c.getIP(conf.IPAM.Type, &bridgeArgs)
			if err != nil {
				return fmt.Errorf("unable to allocate IP address for bridge: %s", err)
			}
			bridgeCIDR := bridgeIPResult.IPs[0].Address

			if err := c.weave.Expose(&bridgeCIDR); err != nil {
				return fmt.Errorf("unable to expose bridge %q: %s", conf.BrName, err)
			}

			bridgeIP = bridgeCIDR.IP
		} else if err != nil {
			return err
		}
		result.IPs[0].Gateway = bridgeIP
	}

	ns, err := netns.GetFromPath(args.Netns)
	if err != nil {
		return fmt.Errorf("error accessing namespace %q: %s", args.Netns, err)
	}
	defer ns.Close()

	hostNs, err := netns.Get()
	if err != nil {
		return fmt.Errorf("error accessing host network namespace: %s", err)
	}
	defer hostNs.Close()

	if ns.Equal(hostNs) {
		return fmt.Errorf("can not specify host network namespace as network namespace to which container should be added")
	}

	id := args.ContainerID
	if len(id) < 5 {
		data := make([]byte, 5)
		_, err := rand.Reader.Read(data)
		if err != nil {
			return err
		}
		id = fmt.Sprintf("%x", data)
	}

	if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false, conf.HairpinMode); err != nil {
		return err
	}
	if err := weavenet.WithNetNSLink(ns, args.IfName, func(link netlink.Link) error {
		return setupRoutes(link, args.IfName, ip.Address, ip.Gateway, result.Routes)
	}); err != nil {
		return fmt.Errorf("error setting up routes: %s", err)
	}

	result.DNS = conf.DNS
	return types.PrintResult(result, conf.CNIVersion)
}

func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, routes []*types.Route) error {
	var err error
	if routes == nil { // If config says nothing about routes, add a default one
		if !ipnet.Contains(gw) {
			// The bridge IP is not on the same subnet; add a specific route to it
			gw32 := &net.IPNet{IP: gw, Mask: mask32}
			if err = weavenet.AddRoute(link, netlink.SCOPE_LINK, gw32, nil); err != nil {
				return err
			}
		}
		routes = []*types.Route{{Dst: zeroNetwork}}
	}
	for _, r := range routes {
		if r.GW != nil {
			err = weavenet.AddRoute(link, netlink.SCOPE_UNIVERSE, &r.Dst, r.GW)
		} else {
			err = weavenet.AddRoute(link, netlink.SCOPE_UNIVERSE, &r.Dst, gw)
		}
		if err != nil {
			return fmt.Errorf("failed to add route '%v via %v dev %v': %v", r.Dst, gw, name, err)
		}
	}
	return nil
}

// As of CNI 0.5 spec:
//   "Plugins should generally complete a DEL action without error even if some resources are missing"
// this method should therefore return nil in most, if not all, cases.
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
	conf, err := loadNetConf(args.StdinData)
	if err != nil {
		logOnStderr(err)
		return nil
	}

	// As of CNI 0.3 spec, runtimes can send blank if they just want the address deallocated
	if args.Netns != "" {
		if err = weavenet.WithNetNSByPath(args.Netns, func() error {
			link, err := netlink.LinkByName(args.IfName)
			if err != nil {
				return err
			}
			return netlink.LinkDel(link)
		}); err != nil {
			// We log the error and carry on instead of returning nil, as there may still be resources to free in IPAM.
			logOnStderr(fmt.Errorf("error removing interface %q: %s", args.IfName, err))
		}
	}

	// Default IPAM is Weave's own
	if conf.IPAM.Type == "" {
		err = ipamplugin.NewIpam(c.weave).Release(args)
	} else {
		err = ipam.ExecDel(conf.IPAM.Type, args.StdinData)
	}
	if err != nil {
		logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
	}
	return nil
}

// Standard error is inherited from the caller (e.g. Kubelet, when running Weave Net's CNI plugin
// under Kubernetes) hence provided errors should eventually appear in the caller's log files.
func logOnStderr(err error) {
	fmt.Fprintln(os.Stderr, "weave-cni:", err)
}

type NetConf struct {
	types.NetConf
	BrName      string `json:"bridge"`
	IsGW        bool   `json:"isGateway"`
	IPMasq      bool   `json:"ipMasq"`
	MTU         int    `json:"mtu"`
	HairpinMode bool   `json:"hairpinMode"`
}
<commit_msg>ignore the error on IPAM delete for the container with 0 addresses<commit_after>package plugin

import (
	"crypto/rand"
	"encoding/json"
	"fmt"
	"net"
	"os"
	"strings"

	"github.com/containernetworking/cni/pkg/ipam"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	weaveapi "github.com/weaveworks/weave/api"
	weavenet "github.com/weaveworks/weave/net"
	ipamplugin "github.com/weaveworks/weave/plugin/ipam"
)

var (
	zeroNetwork = net.IPNet{IP: net.IPv4zero, Mask: net.IPv4Mask(0, 0, 0, 0)}
	mask32      = net.IPv4Mask(0xff, 0xff, 0xff, 0xff)
)

type CNIPlugin struct {
	weave *weaveapi.Client
}

func NewCNIPlugin(weave *weaveapi.Client) *CNIPlugin {
	return &CNIPlugin{weave: weave}
}

func loadNetConf(bytes []byte) (*NetConf, error) {
	n := &NetConf{
		BrName:      weavenet.WeaveBridgeName,
		HairpinMode: true,
	}
	if err := json.Unmarshal(bytes, n); err != nil {
		return nil, fmt.Errorf("failed to load netconf: %v", err)
	}
	return n, nil
}

func (c *CNIPlugin) getIP(ipamType string, args *skel.CmdArgs) (newResult *current.Result, err error) {
	var result types.Result
	// Default IPAM is Weave's own
	if ipamType == "" {
		result, err = ipamplugin.NewIpam(c.weave).Allocate(args)
	} else {
		result, err = ipam.ExecAdd(ipamType, args.StdinData)
	}
	if err != nil {
		return nil, err
	}
	if result == nil {
		return nil, fmt.Errorf("Received no usable result from IPAM plugin")
	}
	newResult, err = current.NewResultFromResult(result)
	// Check if ipam returned no results without error
	if err == nil && len(newResult.IPs) == 0 {
		return nil, fmt.Errorf("IPAM plugin failed to allocate IP address")
	}
	return newResult, err
}

func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
	conf, err := loadNetConf(args.StdinData)
	if err != nil {
		return err
	}

	if conf.IsGW {
		return fmt.Errorf("Gateway functionality not supported")
	}
	if conf.IPMasq {
		return fmt.Errorf("IP Masquerading functionality not supported")
	}

	result, err := c.getIP(conf.IPAM.Type, args)
	if err != nil {
		return fmt.Errorf("unable to allocate IP address: %s", err)
	}
	// Only expecting one address
	ip := result.IPs[0]

	// If config says nothing about routes or gateway, default one will be via the bridge
	if len(result.Routes) == 0 && ip.Gateway == nil {
		bridgeIP, err := weavenet.FindBridgeIP(conf.BrName, &ip.Address)
		if err == weavenet.ErrBridgeNoIP {
			bridgeArgs := *args
			bridgeArgs.ContainerID = "weave:expose"
			// It would be better if libcni let us send just the desired parameters,
			// but there is a bug: https://github.com/containernetworking/cni/issues/410
			// so just blank out the one we want to change
			os.Setenv("CNI_CONTAINERID", bridgeArgs.ContainerID)
			bridgeIPResult, err := c.getIP(conf.IPAM.Type, &bridgeArgs)
			if err != nil {
				return fmt.Errorf("unable to allocate IP address for bridge: %s", err)
			}
			bridgeCIDR := bridgeIPResult.IPs[0].Address

			if err := c.weave.Expose(&bridgeCIDR); err != nil {
				return fmt.Errorf("unable to expose bridge %q: %s", conf.BrName, err)
			}

			bridgeIP = bridgeCIDR.IP
		} else if err != nil {
			return err
		}
		result.IPs[0].Gateway = bridgeIP
	}

	ns, err := netns.GetFromPath(args.Netns)
	if err != nil {
		return fmt.Errorf("error accessing namespace %q: %s", args.Netns, err)
	}
	defer ns.Close()

	hostNs, err := netns.Get()
	if err != nil {
		return fmt.Errorf("error accessing host network namespace: %s", err)
	}
	defer hostNs.Close()

	if ns.Equal(hostNs) {
		return fmt.Errorf("can not specify host network namespace as network namespace to which container should be added")
	}

	id := args.ContainerID
	if len(id) < 5 {
		data := make([]byte, 5)
		_, err := rand.Reader.Read(data)
		if err != nil {
			return err
		}
		id = fmt.Sprintf("%x", data)
	}

	if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false, conf.HairpinMode); err != nil {
		return err
	}
	if err := weavenet.WithNetNSLink(ns, args.IfName, func(link netlink.Link) error {
		return setupRoutes(link, args.IfName, ip.Address, ip.Gateway, result.Routes)
	}); err != nil {
		return fmt.Errorf("error setting up routes: %s", err)
	}

	result.DNS = conf.DNS
	return types.PrintResult(result, conf.CNIVersion)
}

func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, routes []*types.Route) error {
	var err error
	if routes == nil { // If config says nothing about routes, add a default one
		if !ipnet.Contains(gw) {
			// The bridge IP is not on the same subnet; add a specific route to it
			gw32 := &net.IPNet{IP: gw, Mask: mask32}
			if err = weavenet.AddRoute(link, netlink.SCOPE_LINK, gw32, nil); err != nil {
				return err
			}
		}
		routes = []*types.Route{{Dst: zeroNetwork}}
	}
	for _, r := range routes {
		if r.GW != nil {
			err = weavenet.AddRoute(link, netlink.SCOPE_UNIVERSE, &r.Dst, r.GW)
		} else {
			err = weavenet.AddRoute(link, netlink.SCOPE_UNIVERSE, &r.Dst, gw)
		}
		if err != nil {
			return fmt.Errorf("failed to add route '%v via %v dev %v': %v", r.Dst, gw, name, err)
		}
	}
	return nil
}

// As of CNI 0.5 spec:
//   "Plugins should generally complete a DEL action without error even if some resources are missing"
// this method should therefore return nil in most, if not all, cases.
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
	conf, err := loadNetConf(args.StdinData)
	if err != nil {
		logOnStderr(err)
		return nil
	}

	// As of CNI 0.3 spec, runtimes can send blank if they just want the address deallocated
	if args.Netns != "" {
		if err = weavenet.WithNetNSByPath(args.Netns, func() error {
			link, err := netlink.LinkByName(args.IfName)
			if err != nil {
				return err
			}
			return netlink.LinkDel(link)
		}); err != nil {
			// We log the error and carry on instead of returning nil, as there may still be resources to free in IPAM.
			logOnStderr(fmt.Errorf("error removing interface %q: %s", args.IfName, err))
		}
	}

	// Default IPAM is Weave's own
	if conf.IPAM.Type == "" {
		err = ipamplugin.NewIpam(c.weave).Release(args)
	} else {
		err = ipam.ExecDel(conf.IPAM.Type, args.StdinData)
	}
	if err != nil {
		if strings.Contains(err.Error(), fmt.Sprintf("Delete: no addresses for %s", args.ContainerID)) {
			// ignore the error in the case where there are no IP addresses associated with container
			fmt.Fprintln(os.Stderr, "weave-cni:", fmt.Sprintf("Delete: no addresses for %s", args.ContainerID))
			return nil
		}
		logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
		return err
	}
	return nil
}

// Standard error is inherited from the caller (e.g. Kubelet, when running Weave Net's CNI plugin
// under Kubernetes) hence provided errors should eventually appear in the caller's log files.
func logOnStderr(err error) {
	fmt.Fprintln(os.Stderr, "weave-cni:", err)
}

type NetConf struct {
	types.NetConf
	BrName      string `json:"bridge"`
	IsGW        bool   `json:"isGateway"`
	IPMasq      bool   `json:"ipMasq"`
	MTU         int    `json:"mtu"`
	HairpinMode bool   `json:"hairpinMode"`
}
<|endoftext|>


<commit_before>package main

func leadingZeroBits(c uint) func([]byte) bool {
	cd8:=c>>3
	emcm8:=(8-c%8)
	if c%8 == 0 {
		return leadingZeroBytes(cd8)
	}
	return func(t []byte) bool {
		return leadingZeroBytes(cd8)(t) && t[cd8]>>emcm8 == 0
	}
}

func leadingZeroBytes(c uint) func([]byte) bool {
	return func(t []byte) bool {
		switch c {
		case 16:
			if t[15] != 0 {
				return false
			}
			fallthrough
		case 15:
			if t[14] != 0 {
				return false
			}
			fallthrough
		case 14:
			if t[13] != 0 {
				return false
			}
			fallthrough
		case 13:
			if t[12] != 0 {
				return false
			}
			fallthrough
		case 12:
			if t[11] != 0 {
				return false
			}
			fallthrough
		case 11:
			if t[10] != 0 {
				return false
			}
			fallthrough
		case 10:
			if t[9] != 0 {
				return false
			}
			fallthrough
		case 9:
			if t[8] != 0 {
				return false
			}
			fallthrough
		case 8:
			if t[7] != 0 {
				return false
			}
			fallthrough
		case 7:
			if t[6] != 0 {
				return false
			}
			fallthrough
		case 6:
			if t[5] != 0 {
				return false
			}
			fallthrough
		case 5:
			if t[4] != 0 {
				return false
			}
			fallthrough
		case 4:
			if t[3] != 0 {
				return false
			}
			fallthrough
		case 3:
			if t[2] != 0 {
				return false
			}
			fallthrough
		case 2:
			if t[1] != 0 {
				return false
			}
			fallthrough
		case 1:
			if t[0] != 0 {
				return false
			}
			fallthrough
		default:
			return true
		}
	}
}

func leadingSetBits(c uint) func([]byte) bool {
	cd8:=c>>3
	cm8:=(8-c%8)
	if c%8 == 0 {
		return leadingSetBytes(cd8)
	}
	return func(t []byte) bool {
		return leadingSetBytes(cd8)(t) && ^t[cd8]>>cm8 ==0
	}
}

func leadingSetBytes(c uint) func([]byte) bool {
	return func(t []byte) bool {
		switch c {
		case 16:
			if t[15] != 0xff {
				return false
			}
			fallthrough
		case 15:
			if t[14] != 0xff {
				return false
			}
			fallthrough
		case 14:
			if t[13] != 0xff {
				return false
			}
			fallthrough
		case 13:
			if t[12] != 0xff {
				return false
			}
			fallthrough
		case 12:
			if t[11] != 0xff {
				return false
			}
			fallthrough
		case 11:
			if t[10] != 0xff {
				return false
			}
			fallthrough
		case 10:
			if t[9] != 0xff {
				return false
			}
			fallthrough
		case 9:
			if t[8] != 0xff {
				return false
			}
			fallthrough
		case 8:
			if t[7] != 0xff {
				return false
			}
			fallthrough
		case 7:
			if t[6] != 0xff {
				return false
			}
			fallthrough
		case 6:
			if t[5] != 0xff {
				return false
			}
			fallthrough
		case 5:
			if t[4] != 0xff {
				return false
			}
			fallthrough
		case 4:
			if t[3] != 0xff {
				return false
			}
			fallthrough
		case 3:
			if t[2] != 0xff {
				return false
			}
			fallthrough
		case 2:
			if t[1] != 0xff {
				return false
			}
			fallthrough
		case 1:
			if t[0] != 0xff {
				return false
			}
			fallthrough
		default:
			return true
		}
	}
}

<commit_msg>optimise<commit_after>package main

func leadingZeroBits(c uint) func([]byte) bool {
	cd8,emcm8:=c>>3,8-c%8
	if emcm8 == 8 {
		return leadingZeroBytes(cd8)
	}
	return func(t []byte) bool {
		return leadingZeroBytes(cd8)(t) && t[cd8]>>emcm8 == 0
	}
}

func leadingZeroBytes(c uint) func([]byte) bool {
	return func(t []byte) bool {
		switch c {
		case 16:
			if t[15] != 0 {
				return false
			}
			fallthrough
		case 15:
			if t[14] != 0 {
				return false
			}
			fallthrough
		case 14:
			if t[13] != 0 {
				return false
			}
			fallthrough
		case 13:
			if t[12] != 0 {
				return false
			}
			fallthrough
		case 12:
			if t[11] != 0 {
				return false
			}
			fallthrough
		case 11:
			if t[10] != 0 {
				return false
			}
			fallthrough
		case 10:
			if t[9] != 0 {
				return false
			}
			fallthrough
		case 9:
			if t[8] != 0 {
				return false
			}
			fallthrough
		case 8:
			if t[7] != 0 {
				return false
			}
			fallthrough
		case 7:
			if t[6] != 0 {
				return false
			}
			fallthrough
		case 6:
			if t[5] != 0 {
				return false
			}
			fallthrough
		case 5:
			if t[4] != 0 {
				return false
			}
			fallthrough
		case 4:
			if t[3] != 0 {
				return false
			}
			fallthrough
		case 3:
			if t[2] != 0 {
				return false
			}
			fallthrough
		case 2:
			if t[1] != 0 {
				return false
			}
			fallthrough
		case 1:
			if t[0] != 0 {
				return false
			}
			fallthrough
		default:
			return true
		}
	}
}

func leadingSetBits(c uint) func([]byte) bool {
	cd8,emcm8:=c>>3,8-c%8
	if emcm8 == 8 {
		return leadingSetBytes(cd8)
	}
	return func(t []byte) bool {
		return leadingSetBytes(cd8)(t) && ^t[cd8]>>emcm8 ==0
	}
}

func leadingSetBytes(c uint) func([]byte) bool {
	return func(t []byte) bool {
		switch c {
		case 16:
			if t[15] != 0xff {
				return false
			}
			fallthrough
		case 15:
			if t[14] != 0xff {
				return false
			}
			fallthrough
		case 14:
			if t[13] != 0xff {
				return false
			}
			fallthrough
		case 13:
			if t[12] != 0xff {
				return false
			}
			fallthrough
		case 12:
			if t[11] != 0xff {
				return false
			}
			fallthrough
		case 11:
			if t[10] != 0xff {
				return false
			}
			fallthrough
		case 10:
			if t[9] != 0xff {
				return false
			}
			fallthrough
		case 9:
			if t[8] != 0xff {
				return false
			}
			fallthrough
		case 8:
			if t[7] != 0xff {
				return false
			}
			fallthrough
		case 7:
			if t[6] != 0xff {
				return false
			}
			fallthrough
		case 6:
			if t[5] != 0xff {
				return false
			}
			fallthrough
		case 5:
			if t[4] != 0xff {
				return false
			}
			fallthrough
		case 4:
			if t[3] != 0xff {
				return false
			}
			fallthrough
		case 3:
			if t[2] != 0xff {
				return false
			}
			fallthrough
		case 2:
			if t[1] != 0xff {
				return false
			}
			fallthrough
		case 1:
			if t[0] != 0xff {
				return false
			}
			fallthrough
		default:
			return true
		}
	}
}

<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/dbus"
	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/updateengine"
)

var (
	cmdDaemon = &Command{
		Name:        "daemon",
		Summary:     "Daemon for reboot needed signal and if reboot able.",
		Description: `Daemon waits for the reboot needed signal coming out of update engine and attempts to acquire the reboot lock. If the reboot lock is acquired then the machine will reboot.`,
		Run:         runDaemon,
	}
)

const (
	initialInterval = time.Second * 5
	maxInterval     = time.Minute * 5
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
)

func expBackoff(interval time.Duration) time.Duration {
	interval = interval * 2
	if interval > maxInterval {
		interval = maxInterval
	}
	return interval
}

func rebootAndSleep(lgn *login1.Conn) {
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func (r rebooter) lockAndReboot(lck *lock.Lock) {
	interval := initialInterval
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			interval = expBackoff(interval)
			fmt.Printf("Retrying in %v. Error locking: %v\n", interval, err)
			time.Sleep(interval)

			continue
		}

		rebootAndSleep(r.lgn)

		return
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := lock.NewEtcdLockClient(nil)
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (running bool, err error) {
	sys, err := dbus.New()
	if err != nil {
		return false, err
	}

	prop, err := sys.GetUnitProperty("etcd.service", "ActiveState")
	if err != nil {
		return false, fmt.Errorf("Error getting etcd.service ActiveState: %v", err)
	}

	if prop.Value.Value().(string) == "inactive" {
		return false, nil
	}

	return true, nil
}

type rebooter struct {
	strategy string
	lgn      *login1.Conn
}

func (r rebooter) useLock() (useLock bool, err error) {
	switch r.strategy {
	case StrategyBestEffort:
		running, err := etcdActive()
		if err != nil {
			return false, err
		}
		if running {
			fmt.Println("etcd.service is active")
			useLock = true
		} else {
			fmt.Println("etcd.service is inactive")
			useLock = false
		}
	case StrategyEtcdLock:
		useLock = true
	case StrategyReboot:
		useLock = false
	default:
		return false, fmt.Errorf("Unknown strategy: %s", r.strategy)
	}

	return useLock, nil
}

func (r rebooter) reboot() int {
	useLock, err := r.useLock()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if useLock {
		lck, err := setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		err = unlockIfHeld(lck)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		r.lockAndReboot(lck)
	}

	rebootAndSleep(r.lgn)
	fmt.Println("Error: reboot attempt never finished")
	return 1
}

// unlockIfHeld will unlock a lock, if it is held by this machine, or return an error.
func unlockIfHeld(lck *lock.Lock) error {
	err := lck.Unlock()
	if err == lock.ErrNotExist {
		return nil
	} else if err == nil {
		fmt.Println("Unlocked existing lock for this machine")
		return nil
	}

	return err
}

// unlockHeldLock will loop until it can confirm that any held locks are
// released or a stop signal is sent.
func unlockHeldLocks(stop chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	interval := initialInterval
	for {
		var reason string
		select {
		case <-stop:
			return
		case <-time.After(interval):
			active, err := etcdActive()
			if err != nil {
				reason = "error checking on etcd.service"
				break
			}
			if !active {
				reason = "etcd.service is inactive"
				break
			}

			lck, err := setupLock()
			if err != nil {
				reason = "error setting up lock"
				break
			}

			err = unlockIfHeld(lck)
			if err == nil {
				return
			}
			reason = err.Error()
		}

		interval = expBackoff(interval)
		fmt.Printf("Unlocking old locks failed: %v. Retrying in %v.\n", reason, interval)
	}
}

func runDaemon(args []string) int {
	shutdown := make(chan os.Signal, 1)
	stop := make(chan struct{}, 1)
	go func() {
		<-shutdown
		fmt.Fprintln(os.Stderr, "Received interrupt/termination signal - shutting down.")
		close(stop)
		os.Exit(0)
	}()
	signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM)

	strategy := os.ExpandEnv("${REBOOT_STRATEGY}")
	if strategy == "" {
		strategy = StrategyBestEffort
	}

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	var wg sync.WaitGroup
	if strategy != StrategyReboot {
		wg.Add(1)
		go unlockHeldLocks(stop, &wg)
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch, stop)

	r := rebooter{strategy, lgn}

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n",
		result.CurrentOperation,
		strategy,
	)

	if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot {
		<-ch
	}

	close(stop)
	wg.Wait()

	return r.reboot()
}
<commit_msg>daemon: avoid double close<commit_after>package main

import (
	"fmt"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/dbus"
	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/updateengine"
)

var (
	cmdDaemon = &Command{
		Name:        "daemon",
		Summary:     "Daemon for reboot needed signal and if reboot able.",
		Description: `Daemon waits for the reboot needed signal coming out of update engine and attempts to acquire the reboot lock. If the reboot lock is acquired then the machine will reboot.`,
		Run:         runDaemon,
	}
)

const (
	initialInterval = time.Second * 5
	maxInterval     = time.Minute * 5
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
)

func expBackoff(interval time.Duration) time.Duration {
	interval = interval * 2
	if interval > maxInterval {
		interval = maxInterval
	}
	return interval
}

func rebootAndSleep(lgn *login1.Conn) {
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func (r rebooter) lockAndReboot(lck *lock.Lock) {
	interval := initialInterval
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			interval = expBackoff(interval)
			fmt.Printf("Retrying in %v. Error locking: %v\n", interval, err)
			time.Sleep(interval)

			continue
		}

		rebootAndSleep(r.lgn)

		return
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := lock.NewEtcdLockClient(nil)
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (running bool, err error) {
	sys, err := dbus.New()
	if err != nil {
		return false, err
	}

	prop, err := sys.GetUnitProperty("etcd.service", "ActiveState")
	if err != nil {
		return false, fmt.Errorf("Error getting etcd.service ActiveState: %v", err)
	}

	if prop.Value.Value().(string) == "inactive" {
		return false, nil
	}

	return true, nil
}

type rebooter struct {
	strategy string
	lgn      *login1.Conn
}

func (r rebooter) useLock() (useLock bool, err error) {
	switch r.strategy {
	case StrategyBestEffort:
		running, err := etcdActive()
		if err != nil {
			return false, err
		}
		if running {
			fmt.Println("etcd.service is active")
			useLock = true
		} else {
			fmt.Println("etcd.service is inactive")
			useLock = false
		}
	case StrategyEtcdLock:
		useLock = true
	case StrategyReboot:
		useLock = false
	default:
		return false, fmt.Errorf("Unknown strategy: %s", r.strategy)
	}

	return useLock, nil
}

func (r rebooter) reboot() int {
	useLock, err := r.useLock()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if useLock {
		lck, err := setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		err = unlockIfHeld(lck)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		r.lockAndReboot(lck)
	}

	rebootAndSleep(r.lgn)
	fmt.Println("Error: reboot attempt never finished")
	return 1
}

// unlockIfHeld will unlock a lock, if it is held by this machine, or return an error.
func unlockIfHeld(lck *lock.Lock) error {
	err := lck.Unlock()
	if err == lock.ErrNotExist {
		return nil
	} else if err == nil {
		fmt.Println("Unlocked existing lock for this machine")
		return nil
	}

	return err
}

// unlockHeldLock will loop until it can confirm that any held locks are
// released or a stop signal is sent.
func unlockHeldLocks(stop chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	interval := initialInterval
	for {
		var reason string
		select {
		case <-stop:
			return
		case <-time.After(interval):
			active, err := etcdActive()
			if err != nil {
				reason = "error checking on etcd.service"
				break
			}
			if !active {
				reason = "etcd.service is inactive"
				break
			}

			lck, err := setupLock()
			if err != nil {
				reason = "error setting up lock"
				break
			}

			err = unlockIfHeld(lck)
			if err == nil {
				return
			}
			reason = err.Error()
		}

		interval = expBackoff(interval)
		fmt.Printf("Unlocking old locks failed: %v. Retrying in %v.\n", reason, interval)
	}
}

func runDaemon(args []string) int {
	shutdown := make(chan os.Signal, 1)
	stop := make(chan struct{}, 1)
	go func() {
		<-shutdown
		fmt.Fprintln(os.Stderr, "Received interrupt/termination signal - shutting down.")
		os.Exit(0)
	}()
	signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM)

	strategy := os.ExpandEnv("${REBOOT_STRATEGY}")
	if strategy == "" {
		strategy = StrategyBestEffort
	}

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	var wg sync.WaitGroup
	if strategy != StrategyReboot {
		wg.Add(1)
		go unlockHeldLocks(stop, &wg)
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch, stop)

	r := rebooter{strategy, lgn}

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n",
		result.CurrentOperation,
		strategy,
	)

	if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot {
		<-ch
	}

	close(stop)
	wg.Wait()

	return r.reboot()
}
<|endoftext|>


<commit_before>package github

import (
	"errors"
	"github.com/andygrunwald/gotrap/gerrit"
	"github.com/google/go-github/github"
	"strings"
)

// createPullRequestForPatchset will create a new Pull Request at Github
// All information (like base and target branch) are received by the message by Gerrit
func (c GithubClient) CreatePullRequestForPatchset(m *gerrit.Message) (*github.PullRequest, error) {

	// Remove "refs/" from the patchset reference,
	// because if this patchset is synced to Github
	// the branch is named without "refs/" as prefix.
	baseRef := m.Patchset.Ref
	if strings.HasPrefix(baseRef, "refs/") {
		baseRef = baseRef[5:]
	}

	// Start polling until the branch is synced
	// We have to wait, because after this we are able to continue
	err := c.waitUntilBranchisSynced(baseRef)

	if err != nil {
		return nil, errors.New("Max loop reached for branch")
	}

	title := c.Conf.PRTemplate.Title
	title = strings.Replace(title, "%title%", m.Change.Subject, 1)

	body := strings.Join(c.Conf.PRTemplate.Body, "\n")
	body = strings.Replace(body, "%commit-msg%", m.Change.CommitMessage, 1)
	body = strings.Replace(body, "%url%", m.Change.URL, 1)

	pr := &github.NewPullRequest{
		Title: &title,
		Head:  &baseRef,
		Base:  &m.Change.Branch,
		Body:  &body,
	}

	// Do the pull request itself
	prResult, resp, err := c.Client.PullRequests.Create(c.Conf.Organisation, c.Conf.Repository, pr)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return prResult, nil
}

func (c GithubClient) AddCommentToPullRequest(pr *github.PullRequest, message string) (bool, error) {
	comment := &github.IssueComment{
		Body: &message,
	}
	_, resp, err := c.Client.Issues.CreateComment(c.Conf.Organisation, c.Conf.Repository, *pr.Number, comment)

	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	return true, nil
}

func (c GithubClient) ClosePullRequest(pr *github.PullRequest) (bool, error) {
	state := "closed"
	updatePr := &github.PullRequest{
		State: &state,
	}

	_, resp, err := c.Client.PullRequests.Edit(c.Conf.Organisation, c.Conf.Repository, *pr.Number, updatePr)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	return true, nil
}
<commit_msg>Added generation of Pull Request title through text/template<commit_after>package github

import (
	"bytes"
	"errors"
	"github.com/andygrunwald/gotrap/gerrit"
	"github.com/google/go-github/github"
	"strings"
	"text/template"
)

// createPullRequestForPatchset will create a new Pull Request at Github
// All information (like base and target branch) are received by the message by Gerrit
func (c GithubClient) CreatePullRequestForPatchset(m *gerrit.Message) (*github.PullRequest, error) {

	// Remove "refs/" from the patchset reference,
	// because if this patchset is synced to Github
	// the branch is named without "refs/" as prefix.
	baseRef := m.Patchset.Ref
	if strings.HasPrefix(baseRef, "refs/") {
		baseRef = baseRef[5:]
	}

	// Start polling until the branch is synced
	// We have to wait, because after this we are able to continue
	err := c.waitUntilBranchisSynced(baseRef)

	if err != nil {
		return nil, errors.New("Max loop reached for branch")
	}

	// Build title for Pull Request
	titleBuffer := new(bytes.Buffer)
	var titleTemplate = template.Must(template.New("pull-request-title").Parse(c.Conf.PRTemplate.Title))
	err = titleTemplate.Execute(titleBuffer, m)
	if err != nil {
		return nil, err
	}
	title := titleBuffer.String()

	body := strings.Join(c.Conf.PRTemplate.Body, "\n")
	body = strings.Replace(body, "%commit-msg%", m.Change.CommitMessage, 1)
	body = strings.Replace(body, "%url%", m.Change.URL, 1)

	pr := &github.NewPullRequest{
		Title: &title,
		Head:  &baseRef,
		Base:  &m.Change.Branch,
		Body:  &body,
	}

	// Do the pull request itself
	prResult, resp, err := c.Client.PullRequests.Create(c.Conf.Organisation, c.Conf.Repository, pr)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return prResult, nil
}

func (c GithubClient) AddCommentToPullRequest(pr *github.PullRequest, message string) (bool, error) {
	comment := &github.IssueComment{
		Body: &message,
	}
	_, resp, err := c.Client.Issues.CreateComment(c.Conf.Organisation, c.Conf.Repository, *pr.Number, comment)

	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	return true, nil
}

func (c GithubClient) ClosePullRequest(pr *github.PullRequest) (bool, error) {
	state := "closed"
	updatePr := &github.PullRequest{
		State: &state,
	}

	_, resp, err := c.Client.PullRequests.Edit(c.Conf.Organisation, c.Conf.Repository, *pr.Number, updatePr)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	return true, nil
}
<|endoftext|>


<commit_before>package migration

func (m *MigrationHeader) GetRsyncFeaturesSlice() []string {
	features := []string{}
	if m == nil {
		return features
	}

	if m.RsyncFeatures != nil {
		if m.RsyncFeatures.Xattrs != nil && *m.RsyncFeatures.Xattrs == true {
			features = append(features, "xattrs")
		}

		if m.RsyncFeatures.Delete != nil && *m.RsyncFeatures.Delete == true {
			features = append(features, "delete")
		}

		if m.RsyncFeatures.Compress != nil && *m.RsyncFeatures.Compress == true {
			features = append(features, "compress")
		}

		if m.RsyncFeatures.Bidirectional != nil && *m.RsyncFeatures.Bidirectional == true {
			features = append(features, "bidirectional")
		}
	}

	return features
}

func (m *MigrationHeader) GetZfsFeaturesSlice() []string {
	features := []string{}
	if m == nil {
		return features
	}

	if m.ZfsFeatures != nil {
		if m.ZfsFeatures.Compress != nil && *m.ZfsFeatures.Compress == true {
			features = append(features, "compress")
		}
	}

	return features
}
<commit_msg>lxd/migration: golint fixes<commit_after>package migration

// GetRsyncFeaturesSlice returns a slice of strings representing the supported RSYNC features
func (m *MigrationHeader) GetRsyncFeaturesSlice() []string {
	features := []string{}
	if m == nil {
		return features
	}
	if m.RsyncFeatures != nil {
		if m.RsyncFeatures.Xattrs != nil && *m.RsyncFeatures.Xattrs == true {
			features = append(features, "xattrs")
		}

		if m.RsyncFeatures.Delete != nil && *m.RsyncFeatures.Delete == true {
			features = append(features, "delete")
		}

		if m.RsyncFeatures.Compress != nil && *m.RsyncFeatures.Compress == true {
			features = append(features, "compress")
		}

		if m.RsyncFeatures.Bidirectional != nil && *m.RsyncFeatures.Bidirectional == true {
			features = append(features, "bidirectional")
		}
	}

	return features
}

// GetZfsFeaturesSlice returns a slice of strings representing the supported ZFS features
func (m *MigrationHeader) GetZfsFeaturesSlice() []string {
	features := []string{}
	if m == nil {
		return features
	}

	if m.ZfsFeatures != nil {
		if m.ZfsFeatures.Compress != nil && *m.ZfsFeatures.Compress == true {
			features = append(features, "compress")
		}
	}

	return features
}
<|endoftext|>


<commit_before>package project

import (
	"fmt"
	"strings"
)

// Default is the string used for a default project.
const Default = "default"

// separator is used to delimit the project name from the suffix.
const separator = "_"

// Instance adds the "<project>_" prefix to instance name when the given project name is not "default".
func Instance(projectName string, instanceName string) string {
	if projectName != Default {
		return fmt.Sprintf("%s%s%s", projectName, separator, instanceName)
	}

	return instanceName
}

// InstanceParts takes a project prefixed Instance name string and returns the project and instance name.
// If a non-project prefixed Instance name is supplied, then the project is returned as "default" and the instance
// name is returned unmodified in the 2nd return value. This is suitable for passing back into Prefix().
// Note: This should only be used with Instance names (because they cannot contain the project separator) and this
// function relies on this rule as project names can contain the project separator.
func InstanceParts(projectInstanceName string) (string, string) {
	i := strings.LastIndex(projectInstanceName, separator)
	if i < 0 {
		// This string is not project prefixed or is part of default project.
		return Default, projectInstanceName
	}

	// As project names can container separator, we effectively split once from the right hand side as
	// Instance names are not allowed to container the separator value.
	return projectInstanceName[0:i], projectInstanceName[i+1:]
}
<commit_msg>lxd/project/project: Adds StorageVolume()<commit_after>package project

import (
	"fmt"
	"strings"
)

// Default is the string used for a default project.
const Default = "default"

// separator is used to delimit the project name from the suffix.
const separator = "_"

// Instance adds the "<project>_" prefix to instance name when the given project name is not "default".
func Instance(projectName string, instanceName string) string {
	if projectName != Default {
		return fmt.Sprintf("%s%s%s", projectName, separator, instanceName)
	}

	return instanceName
}

// InstanceParts takes a project prefixed Instance name string and returns the project and instance name.
// If a non-project prefixed Instance name is supplied, then the project is returned as "default" and the instance
// name is returned unmodified in the 2nd return value. This is suitable for passing back into Prefix().
// Note: This should only be used with Instance names (because they cannot contain the project separator) and this
// function relies on this rule as project names can contain the project separator.
func InstanceParts(projectInstanceName string) (string, string) {
	i := strings.LastIndex(projectInstanceName, separator)
	if i < 0 {
		// This string is not project prefixed or is part of default project.
		return Default, projectInstanceName
	}

	// As project names can container separator, we effectively split once from the right hand side as
	// Instance names are not allowed to container the separator value.
	return projectInstanceName[0:i], projectInstanceName[i+1:]
}

// StorageVolume adds the "<project>_prefix" to the storage volume name. Even if the project name is "default".
func StorageVolume(projectName string, storageVolumeName string) string {
	return fmt.Sprintf("%s%s%s", projectName, separator, storageVolumeName)
}
<|endoftext|>