<commit_before>package stripe

import (
	"encoding/json"
)

// SubscriptionScheduleStatus is the list of allowed values for the schedule's status.
type SubscriptionScheduleStatus string

// List of values that SubscriptionScheduleStatus can take.
const (
	SubscriptionScheduleStatusActive    SubscriptionScheduleStatus = "active"
	SubscriptionScheduleStatusCanceled  SubscriptionScheduleStatus = "canceled"
	SubscriptionScheduleStatusCompleted SubscriptionScheduleStatus = "completed"
	SubscriptionScheduleStatusPastDue   SubscriptionScheduleStatus = "not_started"
	SubscriptionScheduleStatusTrialing  SubscriptionScheduleStatus = "released"
)

// SubscriptionScheduleRenewalBehavior describe what happens to a schedule when it ends.
type SubscriptionScheduleRenewalBehavior string

// List of values that SubscriptionScheduleRenewalBehavior can take.
const (
	SubscriptionScheduleRenewalBehaviorNone    SubscriptionScheduleRenewalBehavior = "none"
	SubscriptionScheduleRenewalBehaviorRenew   SubscriptionScheduleRenewalBehavior = "release"
	SubscriptionScheduleRenewalBehaviorRelease SubscriptionScheduleRenewalBehavior = "renew"
)

// SubscriptionScheduleInvoiceSettingsParams is a structure representing the parameters allowed to
// control invoice settings on invoices associated with a subscription schedule.
type SubscriptionScheduleInvoiceSettingsParams struct {
	DaysUntilDue *int64 `form:"days_until_due"`
}

// SubscriptionSchedulePhaseItemParams is a structure representing the parameters allowed to control
// a specic plan on a phase on a subscription schedule.
type SubscriptionSchedulePhaseItemParams struct {
	BillingThresholds *SubscriptionItemBillingThresholdsParams `form:"billing_thresholds"`
	Plan              *string                                  `form:"plan"`
	Quantity          *int64                                   `form:"quantity"`
	TaxRates          []*string                                `form:"tax_rates"`
}

// SubscriptionSchedulePhaseParams is a structure representing the parameters allowed to control
// a phase on a subscription schedule.
type SubscriptionSchedulePhaseParams struct {
	ApplicationFeePercent *int64                                     `form:"application_fee_percent"`
	BillingThresholds     *SubscriptionBillingThresholdsParams       `form:"billing_thresholds"`
	CollectionMethod      *string                                    `form:"collection_method"`
	Coupon                *string                                    `form:"coupon"`
	DefaultPaymentMethod  *string                                    `form:"default_payment_method"`
	DefaultTaxRates       []*string                                  `form:"default_tax_rates"`
	EndDate               *int64                                     `form:"end_date"`
	InvoiceSettings       *SubscriptionScheduleInvoiceSettingsParams `form:"invoice_settings"`
	Iterations            *int64                                     `form:"iterations"`
	Plans                 []*SubscriptionSchedulePhaseItemParams     `form:"plans"`
	StartDate             *int64                                     `form:"start_date"`
	Trial                 *bool                                      `form:"trial"`
	TrialEnd              *int64                                     `form:"trial_end"`

	// This parameter is deprecated and we recommend that you use TaxRates instead.
	TaxPercent *float64 `form:"tax_percent"`
}

// SubscriptionScheduleRenewalIntervalParams is a structure representing the renewal interval
// for a given subscription schedule.
type SubscriptionScheduleRenewalIntervalParams struct {
	Interval *string `form:"interval"`
	Length   *int64  `form:"length"`
}

// SubscriptionScheduleParams is the set of parameters that can be used when creating or updating a
// subscription schedule.
type SubscriptionScheduleParams struct {
	Params               `form:"*"`
	BillingThresholds    *SubscriptionBillingThresholdsParams       `form:"billing_thresholds"`
	CollectionMethod     *string                                    `form:"collection_method"`
	Customer             *string                                    `form:"customer"`
	DefaultPaymentMethod *string                                    `form:"default_payment_method"`
	DefaultSource        *string                                    `form:"default_source"`
	FromSubscription     *string                                    `form:"from_subscription"`
	InvoiceSettings      *SubscriptionScheduleInvoiceSettingsParams `form:"invoice_settings"`
	Phases               []*SubscriptionSchedulePhaseParams         `form:"phases"`
	Prorate              *bool                                      `form:"prorate"`
	RenewalBehavior      *string                                    `form:"renewal_behavior"`
	RenewalInterval      *SubscriptionScheduleRenewalIntervalParams `form:"renewal_interval"`
	StartDate            *int64                                     `form:"start_date"`

	// This parameter is deprecated and we recommend that you use CollectionMethod instead.
	Billing *string `form:"billing"`
}

// SubscriptionScheduleCancelParams is the set of parameters that can be used when canceling a
// subscription schedule.
type SubscriptionScheduleCancelParams struct {
	Params     `form:"*"`
	InvoiceNow *bool `form:"invoice_now"`
	Prorate    *bool `form:"prorate"`
}

// SubscriptionScheduleReleaseParams is the set of parameters that can be used when releasing a
// subscription schedule.
type SubscriptionScheduleReleaseParams struct {
	Params             `form:"*"`
	PreserveCancelDate *bool `form:"preserve_cancel_date"`
}

// SubscriptionScheduleListParams is the set of parameters that can be used when listing
// subscription schedules.
type SubscriptionScheduleListParams struct {
	ListParams       `form:"*"`
	CanceledAt       int64             `form:"canceled_at"`
	CanceledAtRange  *RangeQueryParams `form:"canceled_at"`
	CompletedAt      int64             `form:"completed_at"`
	CompletedAtRange *RangeQueryParams `form:"completed_at"`
	Created          int64             `form:"created"`
	CreatedRange     *RangeQueryParams `form:"created"`
	Customer         string            `form:"customer"`
	ReleasedAt       int64             `form:"released_at"`
	ReleasedAtRange  *RangeQueryParams `form:"released_at"`
	Scheduled        *bool             `form:"scheduled"`
}

// SubscriptionScheduleCurrentPhase is a structure the current phase's period.
type SubscriptionScheduleCurrentPhase struct {
	EndDate   int64 `json:"end_date"`
	StartDate int64 `json:"start_date"`
}

// SubscriptionScheduleInvoiceSettings is a structure representing the settings applied to invoices
// associated with a subscription schedule.
type SubscriptionScheduleInvoiceSettings struct {
	DaysUntilDue int64 `json:"days_until_due"`
}

// SubscriptionSchedulePhaseItem represents plan details for a given phase
type SubscriptionSchedulePhaseItem struct {
	BillingThresholds *SubscriptionItemBillingThresholds `json:"billing_thresholds"`
	Plan              *Plan                              `json:"plan"`
	Quantity          int64                              `json:"quantity"`
	TaxRates          []*TaxRate                         `json:"tax_rates"`
}

// SubscriptionSchedulePhase is a structure a phase of a subscription schedule.
type SubscriptionSchedulePhase struct {
	ApplicationFeePercent float64                              `json:"application_fee_percent"`
	BillingThresholds     *SubscriptionBillingThresholds       `json:"billing_thresholds"`
	CollectionMethod      SubscriptionCollectionMethod         `json:"collection_method"`
	Coupon                *Coupon                              `json:"coupon"`
	DefaultPaymentMethod  *PaymentMethod                       `json:"default_payment_method"`
	DefaultTaxRates       []*TaxRate                           `json:"default_tax_rates"`
	EndDate               int64                                `json:"end_date"`
	InvoiceSettings       *SubscriptionScheduleInvoiceSettings `json:"invoice_settings"`
	Plans                 []*SubscriptionSchedulePhaseItem     `json:"plans"`
	StartDate             int64                                `json:"start_date"`
	TrialEnd              int64                                `json:"trial_end"`

	// This field is deprecated and we recommend that you use TaxRates instead.
	TaxPercent float64 `json:"tax_percent"`
}

// SubscriptionScheduleRenewalInterval represents the interval and duration of a schedule.
type SubscriptionScheduleRenewalInterval struct {
	Interval PlanInterval `form:"interval"`
	Length   int64        `form:"length"`
}

// SubscriptionSchedule is the resource representing a Stripe subscription schedule.
type SubscriptionSchedule struct {
	BillingThresholds    *SubscriptionBillingThresholds       `json:"billing_thresholds"`
	CanceledAt           int64                                `json:"canceled_at"`
	CollectionMethod     SubscriptionCollectionMethod         `json:"collection_method"`
	CompletedAt          int64                                `json:"completed_at"`
	Created              int64                                `json:"created"`
	CurrentPhase         *SubscriptionScheduleCurrentPhase    `json:"current_phase"`
	Customer             *Customer                            `json:"customer"`
	DefaultPaymentMethod *PaymentMethod                       `json:"default_payment_method"`
	DefaultSource        *PaymentSource                       `json:"default_source"`
	ID                   string                               `json:"id"`
	InvoiceSettings      *SubscriptionScheduleInvoiceSettings `json:"invoice_settings"`
	Livemode             bool                                 `json:"livemode"`
	Metadata             map[string]string                    `json:"metadata"`
	Object               string                               `json:"object"`
	Phases               []*SubscriptionSchedulePhase         `json:"phases"`
	ReleasedSubscription *Subscription                        `json:"released_subscription"`
	RenewalBehavior      SubscriptionScheduleRenewalBehavior  `json:"renewal_behavior"`
	RenewalInterval      *SubscriptionScheduleRenewalInterval `json:"renewal_interval"`
	Status               SubscriptionScheduleStatus           `json:"status"`
	Subscription         *Subscription                        `json:"subscription"`

	// This field is deprecated and we recommend that you use CollectionMethod instead.
	Billing SubscriptionBilling `json:"billing"`
}

// SubscriptionScheduleList is a list object for subscription schedules.
type SubscriptionScheduleList struct {
	ListMeta
	Data []*SubscriptionSchedule `json:"data"`
}

// UnmarshalJSON handles deserialization of a SubscriptionSchedule.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (s *SubscriptionSchedule) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		s.ID = id
		return nil
	}

	type schedule SubscriptionSchedule
	var v schedule
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*s = SubscriptionSchedule(v)
	return nil
}
<commit_msg>Add support for `EndBehavior` on `SubscriptionSchedule`<commit_after>package stripe

import (
	"encoding/json"
)

// SubscriptionScheduleEndBehavior describe what happens to a schedule when it ends.
type SubscriptionScheduleEndBehavior string

// List of values that SubscriptionScheduleEndBehavior can take.
const (
	SubscriptionScheduleEndBehaviorCancel  SubscriptionScheduleEndBehavior = "cancel"
	SubscriptionScheduleEndBehaviorNone    SubscriptionScheduleEndBehavior = "none"
	SubscriptionScheduleEndBehaviorRenew   SubscriptionScheduleEndBehavior = "release"
	SubscriptionScheduleEndBehaviorRelease SubscriptionScheduleEndBehavior = "renew"
)

// SubscriptionScheduleStatus is the list of allowed values for the schedule's status.
type SubscriptionScheduleStatus string

// List of values that SubscriptionScheduleStatus can take.
const (
	SubscriptionScheduleStatusActive    SubscriptionScheduleStatus = "active"
	SubscriptionScheduleStatusCanceled  SubscriptionScheduleStatus = "canceled"
	SubscriptionScheduleStatusCompleted SubscriptionScheduleStatus = "completed"
	SubscriptionScheduleStatusPastDue   SubscriptionScheduleStatus = "not_started"
	SubscriptionScheduleStatusTrialing  SubscriptionScheduleStatus = "released"
)

// SubscriptionScheduleRenewalBehavior describe what happens to a schedule when it ends.
type SubscriptionScheduleRenewalBehavior string

// List of values that SubscriptionScheduleRenewalBehavior can take.
const (
	SubscriptionScheduleRenewalBehaviorCancel  SubscriptionScheduleRenewalBehavior = "cancel"
	SubscriptionScheduleRenewalBehaviorNone    SubscriptionScheduleRenewalBehavior = "none"
	SubscriptionScheduleRenewalBehaviorRenew   SubscriptionScheduleRenewalBehavior = "release"
	SubscriptionScheduleRenewalBehaviorRelease SubscriptionScheduleRenewalBehavior = "renew"
)

// SubscriptionScheduleInvoiceSettingsParams is a structure representing the parameters allowed to
// control invoice settings on invoices associated with a subscription schedule.
type SubscriptionScheduleInvoiceSettingsParams struct {
	DaysUntilDue *int64 `form:"days_until_due"`
}

// SubscriptionSchedulePhaseItemParams is a structure representing the parameters allowed to control
// a specic plan on a phase on a subscription schedule.
type SubscriptionSchedulePhaseItemParams struct {
	BillingThresholds *SubscriptionItemBillingThresholdsParams `form:"billing_thresholds"`
	Plan              *string                                  `form:"plan"`
	Quantity          *int64                                   `form:"quantity"`
	TaxRates          []*string                                `form:"tax_rates"`
}

// SubscriptionSchedulePhaseParams is a structure representing the parameters allowed to control
// a phase on a subscription schedule.
type SubscriptionSchedulePhaseParams struct {
	ApplicationFeePercent *int64                                     `form:"application_fee_percent"`
	BillingThresholds     *SubscriptionBillingThresholdsParams       `form:"billing_thresholds"`
	CollectionMethod      *string                                    `form:"collection_method"`
	Coupon                *string                                    `form:"coupon"`
	DefaultPaymentMethod  *string                                    `form:"default_payment_method"`
	DefaultTaxRates       []*string                                  `form:"default_tax_rates"`
	EndDate               *int64                                     `form:"end_date"`
	InvoiceSettings       *SubscriptionScheduleInvoiceSettingsParams `form:"invoice_settings"`
	Iterations            *int64                                     `form:"iterations"`
	Plans                 []*SubscriptionSchedulePhaseItemParams     `form:"plans"`
	StartDate             *int64                                     `form:"start_date"`
	Trial                 *bool                                      `form:"trial"`
	TrialEnd              *int64                                     `form:"trial_end"`

	// This parameter is deprecated and we recommend that you use TaxRates instead.
	TaxPercent *float64 `form:"tax_percent"`
}

// SubscriptionScheduleRenewalIntervalParams is a structure representing the renewal interval
// for a given subscription schedule.
type SubscriptionScheduleRenewalIntervalParams struct {
	Interval *string `form:"interval"`
	Length   *int64  `form:"length"`
}

// SubscriptionScheduleParams is the set of parameters that can be used when creating or updating a
// subscription schedule.
type SubscriptionScheduleParams struct {
	Params               `form:"*"`
	BillingThresholds    *SubscriptionBillingThresholdsParams       `form:"billing_thresholds"`
	CollectionMethod     *string                                    `form:"collection_method"`
	Customer             *string                                    `form:"customer"`
	DefaultPaymentMethod *string                                    `form:"default_payment_method"`
	DefaultSource        *string                                    `form:"default_source"`
	EndBehavior          *string                                    `form:"end_behavior"`
	FromSubscription     *string                                    `form:"from_subscription"`
	InvoiceSettings      *SubscriptionScheduleInvoiceSettingsParams `form:"invoice_settings"`
	Phases               []*SubscriptionSchedulePhaseParams         `form:"phases"`
	Prorate              *bool                                      `form:"prorate"`
	RenewalBehavior      *string                                    `form:"renewal_behavior"`
	RenewalInterval      *SubscriptionScheduleRenewalIntervalParams `form:"renewal_interval"`
	StartDate            *int64                                     `form:"start_date"`

	// This parameter is deprecated and we recommend that you use CollectionMethod instead.
	Billing *string `form:"billing"`
}

// SubscriptionScheduleCancelParams is the set of parameters that can be used when canceling a
// subscription schedule.
type SubscriptionScheduleCancelParams struct {
	Params     `form:"*"`
	InvoiceNow *bool `form:"invoice_now"`
	Prorate    *bool `form:"prorate"`
}

// SubscriptionScheduleReleaseParams is the set of parameters that can be used when releasing a
// subscription schedule.
type SubscriptionScheduleReleaseParams struct {
	Params             `form:"*"`
	PreserveCancelDate *bool `form:"preserve_cancel_date"`
}

// SubscriptionScheduleListParams is the set of parameters that can be used when listing
// subscription schedules.
type SubscriptionScheduleListParams struct {
	ListParams       `form:"*"`
	CanceledAt       int64             `form:"canceled_at"`
	CanceledAtRange  *RangeQueryParams `form:"canceled_at"`
	CompletedAt      int64             `form:"completed_at"`
	CompletedAtRange *RangeQueryParams `form:"completed_at"`
	Created          int64             `form:"created"`
	CreatedRange     *RangeQueryParams `form:"created"`
	Customer         string            `form:"customer"`
	ReleasedAt       int64             `form:"released_at"`
	ReleasedAtRange  *RangeQueryParams `form:"released_at"`
	Scheduled        *bool             `form:"scheduled"`
}

// SubscriptionScheduleCurrentPhase is a structure the current phase's period.
type SubscriptionScheduleCurrentPhase struct {
	EndDate   int64 `json:"end_date"`
	StartDate int64 `json:"start_date"`
}

// SubscriptionScheduleInvoiceSettings is a structure representing the settings applied to invoices
// associated with a subscription schedule.
type SubscriptionScheduleInvoiceSettings struct {
	DaysUntilDue int64 `json:"days_until_due"`
}

// SubscriptionSchedulePhaseItem represents plan details for a given phase
type SubscriptionSchedulePhaseItem struct {
	BillingThresholds *SubscriptionItemBillingThresholds `json:"billing_thresholds"`
	Plan              *Plan                              `json:"plan"`
	Quantity          int64                              `json:"quantity"`
	TaxRates          []*TaxRate                         `json:"tax_rates"`
}

// SubscriptionSchedulePhase is a structure a phase of a subscription schedule.
type SubscriptionSchedulePhase struct {
	ApplicationFeePercent float64                              `json:"application_fee_percent"`
	BillingThresholds     *SubscriptionBillingThresholds       `json:"billing_thresholds"`
	CollectionMethod      SubscriptionCollectionMethod         `json:"collection_method"`
	Coupon                *Coupon                              `json:"coupon"`
	DefaultPaymentMethod  *PaymentMethod                       `json:"default_payment_method"`
	DefaultTaxRates       []*TaxRate                           `json:"default_tax_rates"`
	EndDate               int64                                `json:"end_date"`
	InvoiceSettings       *SubscriptionScheduleInvoiceSettings `json:"invoice_settings"`
	Plans                 []*SubscriptionSchedulePhaseItem     `json:"plans"`
	StartDate             int64                                `json:"start_date"`
	TrialEnd              int64                                `json:"trial_end"`

	// This field is deprecated and we recommend that you use TaxRates instead.
	TaxPercent float64 `json:"tax_percent"`
}

// SubscriptionScheduleRenewalInterval represents the interval and duration of a schedule.
type SubscriptionScheduleRenewalInterval struct {
	Interval PlanInterval `form:"interval"`
	Length   int64        `form:"length"`
}

// SubscriptionSchedule is the resource representing a Stripe subscription schedule.
type SubscriptionSchedule struct {
	BillingThresholds    *SubscriptionBillingThresholds       `json:"billing_thresholds"`
	CanceledAt           int64                                `json:"canceled_at"`
	CollectionMethod     SubscriptionCollectionMethod         `json:"collection_method"`
	CompletedAt          int64                                `json:"completed_at"`
	Created              int64                                `json:"created"`
	CurrentPhase         *SubscriptionScheduleCurrentPhase    `json:"current_phase"`
	Customer             *Customer                            `json:"customer"`
	DefaultPaymentMethod *PaymentMethod                       `json:"default_payment_method"`
	DefaultSource        *PaymentSource                       `json:"default_source"`
	EndBehavior          SubscriptionScheduleEndBehavior      `json:"end_behavior"`
	ID                   string                               `json:"id"`
	InvoiceSettings      *SubscriptionScheduleInvoiceSettings `json:"invoice_settings"`
	Livemode             bool                                 `json:"livemode"`
	Metadata             map[string]string                    `json:"metadata"`
	Object               string                               `json:"object"`
	Phases               []*SubscriptionSchedulePhase         `json:"phases"`
	ReleasedSubscription *Subscription                        `json:"released_subscription"`
	RenewalBehavior      SubscriptionScheduleRenewalBehavior  `json:"renewal_behavior"`
	RenewalInterval      *SubscriptionScheduleRenewalInterval `json:"renewal_interval"`
	Status               SubscriptionScheduleStatus           `json:"status"`
	Subscription         *Subscription                        `json:"subscription"`

	// This field is deprecated and we recommend that you use CollectionMethod instead.
	Billing SubscriptionBilling `json:"billing"`
}

// SubscriptionScheduleList is a list object for subscription schedules.
type SubscriptionScheduleList struct {
	ListMeta
	Data []*SubscriptionSchedule `json:"data"`
}

// UnmarshalJSON handles deserialization of a SubscriptionSchedule.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (s *SubscriptionSchedule) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		s.ID = id
		return nil
	}

	type schedule SubscriptionSchedule
	var v schedule
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*s = SubscriptionSchedule(v)
	return nil
}
<|endoftext|>


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

import (
	"errors"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestBusTypes(t *testing.T) {
	require.NotPanics(t, func() { Session() }, "session bus")
	require.NotPanics(t, func() { System() }, "system bus")

	require.Panics(t, func() { Test() }, "test bus before setup")
	SetupTestBus()
	require.NotPanics(t, func() { Test() }, "test bus after setup")

	require.Panics(t, func() { connect(nil, errors.New("something")) })
}

func TestExpandAndShorten(t *testing.T) {
	require := require.New(t)

	require.Equal("com.example.service.Method",
		expand("com.example.service", "Method"))
	require.Equal("com.example.service.Method.SubMethod",
		expand("com.example.service", ".Method.SubMethod"))
	require.Equal("net.example.service.Method",
		expand("com.example.service", "net.example.service.Method"))

	require.Equal("Method",
		shorten("com.example.service", "com.example.service.Method"))
	require.Equal(".Method.SubMethod",
		shorten("com.example.service", "com.example.service.Method.SubMethod"))
	require.Equal("net.example.service.Method",
		shorten("com.example.service", "net.example.service.Method"))
	require.Equal("com.example.service2.Method",
		shorten("com.example.service", "com.example.service2.Method"))
}
<commit_msg>Skip system bus test on CI<commit_after>// Copyright 2018 Google 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 dbus

import (
	"errors"
	"os"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestBusTypes(t *testing.T) {
	require.NotPanics(t, func() { Session() }, "session bus")
	if os.Getenv("CI") != "true" {
		require.NotPanics(t, func() { System() }, "system bus")
	}

	require.Panics(t, func() { Test() }, "test bus before setup")
	SetupTestBus()
	require.NotPanics(t, func() { Test() }, "test bus after setup")

	require.Panics(t, func() { connect(nil, errors.New("something")) })
}

func TestExpandAndShorten(t *testing.T) {
	require := require.New(t)

	require.Equal("com.example.service.Method",
		expand("com.example.service", "Method"))
	require.Equal("com.example.service.Method.SubMethod",
		expand("com.example.service", ".Method.SubMethod"))
	require.Equal("net.example.service.Method",
		expand("com.example.service", "net.example.service.Method"))

	require.Equal("Method",
		shorten("com.example.service", "com.example.service.Method"))
	require.Equal(".Method.SubMethod",
		shorten("com.example.service", "com.example.service.Method.SubMethod"))
	require.Equal("net.example.service.Method",
		shorten("com.example.service", "net.example.service.Method"))
	require.Equal("com.example.service2.Method",
		shorten("com.example.service", "com.example.service2.Method"))
}
<|endoftext|>


<commit_before>package pointer

import (
	"github.com/github/git-media/gitmedia"
	"github.com/github/git-media/gitmediaclient"
	"io"
	"os"
)

func Smudge(writer io.Writer, oid string) error {
	mediafile, err := gitmedia.LocalMediaPath(oid)
	if err != nil {
		return err
	}

	if stat, err := os.Stat(mediafile); err != nil || stat == nil {
		err = downloadFile(writer, oid, mediafile)
	} else {
		err = readLocalFile(writer, mediafile)
	}

	if err != nil {
		return &SmudgeError{oid, mediafile, err.Error()}
	} else {
		return nil
	}
}

func downloadFile(writer io.Writer, oid, mediafile string) error {
	reader, err := gitmediaclient.Get(mediafile)
	if err != nil {
		return err
	}
	defer reader.Close()

	mediaWriter, err := newFile(mediafile, oid)
	if err != nil {
		return err
	}

	copyErr := copyFile(reader, writer, mediaWriter)
	closeErr := mediaWriter.Close()

	if copyErr != nil {
		return copyErr
	}

	if closeErr != nil {
		return closeErr
	}

	return nil
}

func readLocalFile(writer io.Writer, mediafile string) error {
	reader, err := os.Open(mediafile)
	if err != nil {
		return err
	}
	defer reader.Close()

	return copyFile(reader, writer)
}

func copyFile(reader io.ReadCloser, writers ...io.Writer) error {
	multiWriter := io.MultiWriter(writers...)

	_, err := io.Copy(multiWriter, reader)
	return err
}

type SmudgeError struct {
	Oid          string
	Filename     string
	ErrorMessage string
}

func (e *SmudgeError) Error() string {
	return e.ErrorMessage
}
<commit_msg>ラララララ ラー ウウウ フフフ<commit_after>package pointer

import (
	"github.com/github/git-media/gitmedia"
	"github.com/github/git-media/gitmediaclient"
	"io"
	"os"
)

func Smudge(writer io.Writer, oid string) error {
	mediafile, err := gitmedia.LocalMediaPath(oid)
	if err != nil {
		return err
	}

	if stat, statErr := os.Stat(mediafile); statErr != nil || stat == nil {
		err = downloadFile(writer, oid, mediafile)
	} else {
		err = readLocalFile(writer, mediafile)
	}

	if err != nil {
		return &SmudgeError{oid, mediafile, err.Error()}
	} else {
		return nil
	}
}

func downloadFile(writer io.Writer, oid, mediafile string) error {
	reader, err := gitmediaclient.Get(mediafile)
	if err != nil {
		return err
	}
	defer reader.Close()

	mediaWriter, err := newFile(mediafile, oid)
	if err != nil {
		return err
	}

	copyErr := copyFile(reader, writer, mediaWriter)
	closeErr := mediaWriter.Close()

	if copyErr != nil {
		return copyErr
	}

	if closeErr != nil {
		return closeErr
	}

	return nil
}

func readLocalFile(writer io.Writer, mediafile string) error {
	reader, err := os.Open(mediafile)
	if err != nil {
		return err
	}
	defer reader.Close()

	return copyFile(reader, writer)
}

func copyFile(reader io.ReadCloser, writers ...io.Writer) error {
	multiWriter := io.MultiWriter(writers...)

	_, err := io.Copy(multiWriter, reader)
	return err
}

type SmudgeError struct {
	Oid          string
	Filename     string
	ErrorMessage string
}

func (e *SmudgeError) Error() string {
	return e.ErrorMessage
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Fabrício Godoy
 *
 * 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.
 */

//go:generate ffjson $GOFILE

package jwt

import (
	"encoding/base64"
	"io"
	"time"

	"github.com/pquerna/ffjson/ffjson"
)

// A GoogleClaims represents a JSON object from Google ID Tokens.
type GoogleClaims struct {
	Issuer          string   `json:"iss"`
	Subject         string   `json:"sub"`
	AuthorizedParty string   `json:"azp"`
	Audience        string   `json:"aud"`
	IssuedAt        UnixTime `json:"iat"`
	ExpireAt        UnixTime `json:"exp"`

	Email         string `json:"email,omitempty"`
	EmailVerified bool   `json:"email_verified,omitempty"`
	Name          string `json:"name,omitempty"`
	Picture       string `json:"picture,omitempty"`
	GivenName     string `json:"given_name,omitempty"`
	FamilyName    string `json:"family_name,omitempty"`
	Locale        string `json:"locale,omitempty"`
}

// GetAudience returns the recipients that the JWT is intended for.
func (gc *GoogleClaims) GetAudience() string {
	return gc.Audience
}

// GetExpireAt returns the token expiration date.
func (gc *GoogleClaims) GetExpireAt() time.Time {
	return gc.ExpireAt.ToTime()
}

// GetIssuedAt returns the token issue date.
func (gc *GoogleClaims) GetIssuedAt() time.Time {
	return gc.IssuedAt.ToTime()
}

// GetIssuer returns the token issuer.
func (gc *GoogleClaims) GetIssuer() string {
	return gc.Issuer
}

// GetNotBefore returns zero.
func (*GoogleClaims) GetNotBefore() time.Time {
	return time.Unix(0, 0)
}

// GetSubject returns the principal that is the subject of the JWT.
func (gc *GoogleClaims) GetSubject() string {
	return gc.Subject
}

// SetExpireAt defines the token expiration date.
func (gc *GoogleClaims) SetExpireAt(dt time.Time) {
	gc.ExpireAt = NewUnixTime(dt)
}

// SetIssuedAt defines the token issue date.
func (gc *GoogleClaims) SetIssuedAt(dt time.Time) {
	gc.IssuedAt = NewUnixTime(dt)
}

// SetIssuer defines the token issuer.
func (gc *GoogleClaims) SetIssuer(issuer string) {
	gc.Issuer = issuer
}

// SetNotBefore does nothing.
func (*GoogleClaims) SetNotBefore(dt time.Time) {}

// Decode specified encoded token to current instance.
func (gc *GoogleClaims) Decode(input string) error {
	b64in, err := base64.RawURLEncoding.DecodeString(input)
	if err != nil {
		return err
	}
	err = ffjson.Unmarshal(b64in, gc)
	if err != nil {
		return err
	}

	return nil
}

// Encode current instance to specified writer.
func (gc *GoogleClaims) Encode(w io.Writer) error {
	b64out := base64.NewEncoder(base64.RawURLEncoding, w)
	jout := ffjson.NewEncoder(b64out)
	if err := jout.Encode(gc); err != nil {
		return err
	}

	b64out.Close()
	return nil
}

// Validate returns whether current claims are valid.
func (gc *GoogleClaims) Validate() bool {
	now := time.Now().Unix()
	exp := gc.ExpireAt.ToInt64()
	iat := gc.IssuedAt.ToInt64()

	// Enforce use of exp and iat claims
	if exp <= 0 || iat <= 0 || now > exp {
		return false
	}

	// Reject invalid values
	if exp < iat {
		return false
	}

	return true
}

var _ Claims = (*GoogleClaims)(nil)
<commit_msg>Added HostedDomain claim to GoogleClaims<commit_after>/*
 * Copyright 2016 Fabrício Godoy
 *
 * 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.
 */

//go:generate ffjson $GOFILE

package jwt

import (
	"encoding/base64"
	"io"
	"time"

	"github.com/pquerna/ffjson/ffjson"
)

// A GoogleClaims represents a JSON object from Google ID Tokens.
type GoogleClaims struct {
	Issuer          string   `json:"iss"`
	Subject         string   `json:"sub"`
	AuthorizedParty string   `json:"azp"`
	Audience        string   `json:"aud"`
	IssuedAt        UnixTime `json:"iat"`
	ExpireAt        UnixTime `json:"exp"`

	Email         string `json:"email,omitempty"`
	EmailVerified bool   `json:"email_verified,omitempty"`
	Name          string `json:"name,omitempty"`
	Picture       string `json:"picture,omitempty"`
	GivenName     string `json:"given_name,omitempty"`
	FamilyName    string `json:"family_name,omitempty"`
	Locale        string `json:"locale,omitempty"`
	HostedDomain  string `json:"hd,omitempty"`
}

// GetAudience returns the recipients that the JWT is intended for.
func (gc *GoogleClaims) GetAudience() string {
	return gc.Audience
}

// GetExpireAt returns the token expiration date.
func (gc *GoogleClaims) GetExpireAt() time.Time {
	return gc.ExpireAt.ToTime()
}

// GetIssuedAt returns the token issue date.
func (gc *GoogleClaims) GetIssuedAt() time.Time {
	return gc.IssuedAt.ToTime()
}

// GetIssuer returns the token issuer.
func (gc *GoogleClaims) GetIssuer() string {
	return gc.Issuer
}

// GetNotBefore returns zero.
func (*GoogleClaims) GetNotBefore() time.Time {
	return time.Unix(0, 0)
}

// GetSubject returns the principal that is the subject of the JWT.
func (gc *GoogleClaims) GetSubject() string {
	return gc.Subject
}

// SetExpireAt defines the token expiration date.
func (gc *GoogleClaims) SetExpireAt(dt time.Time) {
	gc.ExpireAt = NewUnixTime(dt)
}

// SetIssuedAt defines the token issue date.
func (gc *GoogleClaims) SetIssuedAt(dt time.Time) {
	gc.IssuedAt = NewUnixTime(dt)
}

// SetIssuer defines the token issuer.
func (gc *GoogleClaims) SetIssuer(issuer string) {
	gc.Issuer = issuer
}

// SetNotBefore does nothing.
func (*GoogleClaims) SetNotBefore(dt time.Time) {}

// Decode specified encoded token to current instance.
func (gc *GoogleClaims) Decode(input string) error {
	b64in, err := base64.RawURLEncoding.DecodeString(input)
	if err != nil {
		return err
	}
	err = ffjson.Unmarshal(b64in, gc)
	if err != nil {
		return err
	}

	return nil
}

// Encode current instance to specified writer.
func (gc *GoogleClaims) Encode(w io.Writer) error {
	b64out := base64.NewEncoder(base64.RawURLEncoding, w)
	jout := ffjson.NewEncoder(b64out)
	if err := jout.Encode(gc); err != nil {
		return err
	}

	b64out.Close()
	return nil
}

// Validate returns whether current claims are valid.
func (gc *GoogleClaims) Validate() bool {
	now := time.Now().Unix()
	exp := gc.ExpireAt.ToInt64()
	iat := gc.IssuedAt.ToInt64()

	// Enforce use of exp and iat claims
	if exp <= 0 || iat <= 0 || now > exp {
		return false
	}

	// Reject invalid values
	if exp < iat {
		return false
	}

	return true
}

var _ Claims = (*GoogleClaims)(nil)
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"log"
	"strconv"
)

func NewContactList(size int) ContactList {
	return ContactList{i: -1, list: make([]*Contact, 0, size)}
}

type ContactList struct {
	i    int
	list []*Contact
}

func (c *ContactList) Next() bool {
	c.i++

	if len(c.list) < c.i+1 {
		c.i--
		return false
	}

	return true
}

func (c ContactList) Current() *Contact {
	if c.i < 0 {
		return nil
	}

	if len(c.list) < c.i+1 {
		return nil
	}

	return c.list[c.i]
}

func (c *ContactList) Append(contact *Contact) {
	c.list = append(c.list, contact)
}

func (c ContactList) Ids() string {
	ids := bytes.NewBuffer([]byte(`{`))

	strings := make([][]byte, 0)
	for c.Next() {
		if id, err := c.Current().Id.Value(); err == nil {
			strings = append(strings, []byte(strconv.FormatInt(id.(int64), 10)))
		}
	}
	result := bytes.Join(strings, []byte(`,`))

	if _, err := ids.Write(result); err != nil {
		log.Print(err)
	}

	if _, err := ids.Write([]byte(`}`)); err != nil {
		log.Print(err)
		return "{}"
	}

	return ids.String()
}

func (c ContactList) Any() bool {
	return len(c.list) > 0
}

func (c ContactList) Items() []*Contact {
	return c.list
}

func (c *ContactList) First() *Contact {
	c.Next()
	return c.Current()
}
<commit_msg>[kami][ContactList] Refactor<commit_after>package main

import (
	"bytes"
	"log"
	"strconv"
)

func NewContactList(size int) ContactList {
	return ContactList{i: -1, list: make([]*Contact, 0, size)}
}

type ContactList struct {
	i    int
	list []*Contact
}

func (c *ContactList) Next() *Contact {
	c.i++

	if len(c.list) < c.i+1 {
		c.i--
		return nil
	}

	return c.list[c.i]
}

func (c *ContactList) Append(contact *Contact) {
	c.list = append(c.list, contact)
}

func (c ContactList) Ids() []byte {
	ids := bytes.NewBuffer([]byte("{"))

	strings := make([][]byte, 0)
	for _, next := range c.list {
		if id, err := next.Id.Value(); err == nil {
			strings = append(strings, []byte(strconv.FormatInt(id.(int64), 10)))
		}
	}
	result := bytes.Join(strings, []byte(","))

	if _, err := ids.Write(result); err != nil {
		log.Print(err)
	}

	if _, err := ids.Write([]byte("}")); err != nil {
		log.Print(err)
		return []byte("{}")
	}

	return ids.Bytes()
}

func (c ContactList) Any() bool {
	return len(c.list) > 0
}

func (c ContactList) Items() []*Contact {
	return c.list
}
<|endoftext|>


<commit_before>//  Copyright (c) 2013 Couchbase, 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 rest

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync/atomic"
	"testing"

	"sync/atomic"

	"github.com/couchbase/sync_gateway/base"
	goassert "github.com/couchbaselabs/go.assert"
	"github.com/stretchr/testify/assert"
)

// Tests the ConfigServer feature.
func TestConfigServer(t *testing.T) {
	fakeConfigURL := "http://example.com/config"
	mockClient := NewMockClient()
	mockClient.RespondToGET(fakeConfigURL+"/db2", MakeResponse(200, nil,
		`{
			"bucket": "fivez",
			"server": "walrus:/fake"
		}`))

	rt := NewRestTester(t, nil)
	rt.NoFlush = true
	defer rt.Close()

	sc := rt.ServerContext()
	sc.HTTPClient = mockClient.Client
	sc.config.ConfigServer = &fakeConfigURL

	dbc, err := sc.GetDatabase("db")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db")

	dbc, err = sc.GetDatabase("db2")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db2")
	goassert.Equals(t, dbc.Bucket.GetName(), "fivez")

	rt.Bucket() // no-op that just keeps rt from being GC'd/finalized (bug CBL-9)
}

// Tests the ConfigServer feature.
func TestConfigServerWithSyncFunction(t *testing.T) {
	fakeConfigURL := "http://example.com/config"
	fakeConfig := `{
			"bucket": "fivez",
			"server": "walrus:/fake",
			"sync":%s%s%s
		}`

	fakeSyncFunction := `
      function(doc, oldDoc) {
        if (doc.type == "reject_me") {
	      throw({forbidden : "Rejected document"})
        } else if (doc.type == "bar") {
	  // add "bar" docs to the "important" channel
            channel("important");
	} else if (doc.type == "secret") {
          if (!doc.owner) {
            throw({forbidden : "Secret documents must have an owner field"})
          }
	} else {
	    // all other documents just go into all channels listed in the doc["channels"] field
	    channel(doc.channels)
	}
      }
    `
	//Create config with embedded sync function in back quotes
	responseBody := fmt.Sprintf(fakeConfig, "`", fakeSyncFunction, "`")

	mockClient := NewMockClient()
	mockClient.RespondToGET(fakeConfigURL+"/db2", MakeResponse(200, nil, responseBody))

	rt := NewRestTester(t, nil)
	rt.NoFlush = true
	defer rt.Close()

	sc := rt.ServerContext()
	sc.HTTPClient = mockClient.Client
	sc.config.ConfigServer = &fakeConfigURL

	dbc, err := sc.GetDatabase("db")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db")

	dbc, err = sc.GetDatabase("db2")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db2")
	goassert.Equals(t, dbc.Bucket.GetName(), "fivez")

	rt.Bucket() // no-op that just keeps rt from being GC'd/finalized (bug CBL-9)

}

func TestRecordGoroutineHighwaterMark(t *testing.T) {

	// Reset this to 0
	atomic.StoreUint64(&base.MaxGoroutinesSeen, 0)

	assert.Equal(t, uint64(1000), goroutineHighwaterMark(1000))
	assert.Equal(t, uint64(1000), goroutineHighwaterMark(500))
	assert.Equal(t, uint64(1500), goroutineHighwaterMark(1500))

}

//////// MOCK HTTP CLIENT: (TODO: Move this into a separate package)

// Creates a filled-in http.Response from minimal details
func MakeResponse(status int, headers map[string]string, body string) *http.Response {
	return &http.Response{
		StatusCode:    status,
		Status:        fmt.Sprintf("%d", status),
		Body:          ioutil.NopCloser(bytes.NewBufferString(body)),
		ContentLength: int64(len(body)),
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
	}
}

// Implementation of http.RoundTripper that does the actual work
type mockTripper struct {
	getURLs map[string]*http.Response
}

func (m *mockTripper) RoundTrip(rq *http.Request) (*http.Response, error) {
	response := m.getURLs[rq.URL.String()]
	if response == nil {
		response = MakeResponse(http.StatusNotFound, nil, "Not Found")
	}
	return response, nil
}

// Fake http.Client that returns canned responses.
type MockClient struct {
	*http.Client
}

// Creates a new MockClient.
func NewMockClient() *MockClient {
	tripper := mockTripper{
		getURLs: map[string]*http.Response{},
	}
	return &MockClient{
		Client: &http.Client{Transport: &tripper},
	}
}

// Adds a canned response. The Client will respond to a GET of the given URL with the response.
func (client *MockClient) RespondToGET(url string, response *http.Response) {
	tripper := client.Transport.(*mockTripper)
	tripper.getURLs[url] = response
}
<commit_msg>Import fix (#4023)<commit_after>//  Copyright (c) 2013 Couchbase, 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 rest

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync/atomic"
	"testing"

	"github.com/couchbase/sync_gateway/base"
	goassert "github.com/couchbaselabs/go.assert"
	"github.com/stretchr/testify/assert"
)

// Tests the ConfigServer feature.
func TestConfigServer(t *testing.T) {
	fakeConfigURL := "http://example.com/config"
	mockClient := NewMockClient()
	mockClient.RespondToGET(fakeConfigURL+"/db2", MakeResponse(200, nil,
		`{
			"bucket": "fivez",
			"server": "walrus:/fake"
		}`))

	rt := NewRestTester(t, nil)
	rt.NoFlush = true
	defer rt.Close()

	sc := rt.ServerContext()
	sc.HTTPClient = mockClient.Client
	sc.config.ConfigServer = &fakeConfigURL

	dbc, err := sc.GetDatabase("db")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db")

	dbc, err = sc.GetDatabase("db2")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db2")
	goassert.Equals(t, dbc.Bucket.GetName(), "fivez")

	rt.Bucket() // no-op that just keeps rt from being GC'd/finalized (bug CBL-9)
}

// Tests the ConfigServer feature.
func TestConfigServerWithSyncFunction(t *testing.T) {
	fakeConfigURL := "http://example.com/config"
	fakeConfig := `{
			"bucket": "fivez",
			"server": "walrus:/fake",
			"sync":%s%s%s
		}`

	fakeSyncFunction := `
      function(doc, oldDoc) {
        if (doc.type == "reject_me") {
	      throw({forbidden : "Rejected document"})
        } else if (doc.type == "bar") {
	  // add "bar" docs to the "important" channel
            channel("important");
	} else if (doc.type == "secret") {
          if (!doc.owner) {
            throw({forbidden : "Secret documents must have an owner field"})
          }
	} else {
	    // all other documents just go into all channels listed in the doc["channels"] field
	    channel(doc.channels)
	}
      }
    `
	//Create config with embedded sync function in back quotes
	responseBody := fmt.Sprintf(fakeConfig, "`", fakeSyncFunction, "`")

	mockClient := NewMockClient()
	mockClient.RespondToGET(fakeConfigURL+"/db2", MakeResponse(200, nil, responseBody))

	rt := NewRestTester(t, nil)
	rt.NoFlush = true
	defer rt.Close()

	sc := rt.ServerContext()
	sc.HTTPClient = mockClient.Client
	sc.config.ConfigServer = &fakeConfigURL

	dbc, err := sc.GetDatabase("db")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db")

	dbc, err = sc.GetDatabase("db2")
	goassert.Equals(t, err, nil)
	goassert.Equals(t, dbc.Name, "db2")
	goassert.Equals(t, dbc.Bucket.GetName(), "fivez")

	rt.Bucket() // no-op that just keeps rt from being GC'd/finalized (bug CBL-9)

}

func TestRecordGoroutineHighwaterMark(t *testing.T) {

	// Reset this to 0
	atomic.StoreUint64(&base.MaxGoroutinesSeen, 0)

	assert.Equal(t, uint64(1000), goroutineHighwaterMark(1000))
	assert.Equal(t, uint64(1000), goroutineHighwaterMark(500))
	assert.Equal(t, uint64(1500), goroutineHighwaterMark(1500))

}

//////// MOCK HTTP CLIENT: (TODO: Move this into a separate package)

// Creates a filled-in http.Response from minimal details
func MakeResponse(status int, headers map[string]string, body string) *http.Response {
	return &http.Response{
		StatusCode:    status,
		Status:        fmt.Sprintf("%d", status),
		Body:          ioutil.NopCloser(bytes.NewBufferString(body)),
		ContentLength: int64(len(body)),
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
	}
}

// Implementation of http.RoundTripper that does the actual work
type mockTripper struct {
	getURLs map[string]*http.Response
}

func (m *mockTripper) RoundTrip(rq *http.Request) (*http.Response, error) {
	response := m.getURLs[rq.URL.String()]
	if response == nil {
		response = MakeResponse(http.StatusNotFound, nil, "Not Found")
	}
	return response, nil
}

// Fake http.Client that returns canned responses.
type MockClient struct {
	*http.Client
}

// Creates a new MockClient.
func NewMockClient() *MockClient {
	tripper := mockTripper{
		getURLs: map[string]*http.Response{},
	}
	return &MockClient{
		Client: &http.Client{Transport: &tripper},
	}
}

// Adds a canned response. The Client will respond to a GET of the given URL with the response.
func (client *MockClient) RespondToGET(url string, response *http.Response) {
	tripper := client.Transport.(*mockTripper)
	tripper.getURLs[url] = response
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"

	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
	awscommon "github.com/mitchellh/packer/builder/amazon/common"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
)

type Config struct {
	Bucket       string `mapstructure:"bucket"`
	ManifestPath string `mapstructure:"manifest"`
	BoxName      string `mapstructure:"box_name"`
	BoxDir       string `mapstructure:"box_dir"`
	Version      string `mapstructure:"version"`

	common.PackerConfig    `mapstructure:",squash"`
	awscommon.AccessConfig `mapstructure:",squash"`
	tpl                    *packer.ConfigTemplate
}

type PostProcessor struct {
	config Config
	s3     *s3.Bucket
}

func (p *PostProcessor) Configure(raws ...interface{}) error {
	_, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	errs := &packer.MultiError{}

	errs = packer.MultiErrorAppend(errs, p.config.AccessConfig.Prepare(p.config.tpl)...)

	// required configuration
	templates := map[string]*string{
		"bucket":   &p.config.Bucket,
		"manifest": &p.config.ManifestPath,
		"box_name": &p.config.BoxName,
		"box_dir":  &p.config.BoxDir,
		"version":  &p.config.Version,
	}

	for key, ptr := range templates {
		if *ptr == "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("vagrant-s3 %s must be set", key))
		}
	}

	// Template process
	for key, ptr := range templates {
		*ptr, err = p.config.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing %s: %s", key, err))
		}
	}

	// setup the s3 bucket
	auth, err := p.config.AccessConfig.Auth()
	if err != nil {
		errs = packer.MultiErrorAppend(errs, err)
	}
	p.s3 = s3.New(auth, aws.USEast).Bucket(p.config.Bucket)

	if len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	// Only accept input from the vagrant post-processor
	if artifact.BuilderId() != "mitchellh.post-processor.vagrant" {
		return nil, false, fmt.Errorf("Unknown artifact type, requires box from vagrant post-processor: %s", artifact.BuilderId())
	}

	// Assume there is only one .box file to upload
	box := artifact.Files()[0]
	if !strings.HasSuffix(box, ".box") {
		return nil, false, fmt.Errorf("Unknown files in artifact from vagrant post-processor: %s", artifact.Files())
	}

	provider := providerFromBuilderName(artifact.Id())
	ui.Say(fmt.Sprintf("Preparing to upload box for '%s' provider to S3 bucket '%s'", provider, p.config.Bucket))

	// open the box so we can upload to S3 and calculate checksum for the manifest
	file, err := os.Open(box)
	if err != nil {
		return nil, false, err
	}
	defer file.Close()

	// get the file's size
	info, err := file.Stat()
	if err != nil {
		return nil, false, err
	}
	size := info.Size()
	ui.Message(fmt.Sprintf("Box to upload: %s (%d bytes)", box, size))

	// get the latest manifest so we can add to it
	ui.Message("Fetching latest manifest")
	manifest, err := p.getManifest()
	if err != nil {
		return nil, false, err
	}

	// generate the path to store the box in S3
	boxPath := fmt.Sprintf("%s/%s/%s", p.config.BoxDir, p.config.Version, path.Base(box))

	ui.Message("Generating checksum")
	checksum, err := sum256(file)
	if err != nil {
		return nil, false, err
	}
	ui.Message(fmt.Sprintf("Checksum is %s", checksum))

	ui.Message(fmt.Sprintf("Adding %s %s box to manifest", provider, p.config.Version))
	if err := manifest.add(p.config.Version, &Provider{
		Name:         provider,
		Url:          p.s3.URL(boxPath),
		ChecksumType: "sha256",
		Checksum:     checksum,
	}); err != nil {
		return nil, false, err
	}

	// upload the box to S3 (rewinding as we already read the file to generate the checksum)
	ui.Message(fmt.Sprintf("Uploading box to S3: %s", boxPath))
	if _, err := file.Seek(0, 0); err != nil {
		return nil, false, err
	}
	if size > 100*1024*1024 {
		multi, err := p.s3.Multi(boxPath, "application/octet-stream", "public-read")
		if err != nil {
			return nil, false, err
		}
		if _, err := multi.PutAll(file, 5*1024*1024); err != nil {
			return nil, false, err
		}
	} else {
		if err := p.s3.PutReader(boxPath, file, size, "application/octet-stream", "public-read"); err != nil {
			return nil, false, err
		}
	}

	ui.Message(fmt.Sprintf("Uploading the manifest: %s", p.config.ManifestPath))
	if err := p.putManifest(manifest); err != nil {
		return nil, false, err
	}

	return &Artifact{p.s3.URL(p.config.ManifestPath)}, true, nil
}

func (p *PostProcessor) getManifest() (*Manifest, error) {
	body, err := p.s3.GetReader(p.config.ManifestPath)
	if err != nil {
		if err.(*s3.Error).Code == "NoSuchKey" {
			return &Manifest{Name: p.config.BoxName}, nil
		}
		return nil, err
	}
	defer body.Close()

	manifest := &Manifest{}
	if err := json.NewDecoder(body).Decode(manifest); err != nil {
		return nil, err
	}
	return manifest, nil
}

func (p *PostProcessor) putManifest(manifest *Manifest) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(manifest); err != nil {
		return err
	}
	if err := p.s3.Put(p.config.ManifestPath, buf.Bytes(), "application/json", "public-read"); err != nil {
		return err
	}
	return nil
}

// calculates a sha256 checksum of the file
func sum256(file *os.File) (string, error) {
	h := sha256.New()
	if _, err := io.Copy(h, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(h.Sum(nil)), nil
}

// converts a packer builder name to the corresponding vagrant provider
func providerFromBuilderName(name string) string {
	switch name {
	case "aws":
		return "aws"
	case "digitalocean":
		return "digitalocean"
	case "virtualbox":
		return "virtualbox"
	case "vmware":
		return "vmware_desktop"
	case "parallels":
		return "parallels"
	default:
		return name
	}
}
<commit_msg>Fix s3.Error type assertion<commit_after>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"

	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
	awscommon "github.com/mitchellh/packer/builder/amazon/common"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
)

type Config struct {
	Bucket       string `mapstructure:"bucket"`
	ManifestPath string `mapstructure:"manifest"`
	BoxName      string `mapstructure:"box_name"`
	BoxDir       string `mapstructure:"box_dir"`
	Version      string `mapstructure:"version"`

	common.PackerConfig    `mapstructure:",squash"`
	awscommon.AccessConfig `mapstructure:",squash"`
	tpl                    *packer.ConfigTemplate
}

type PostProcessor struct {
	config Config
	s3     *s3.Bucket
}

func (p *PostProcessor) Configure(raws ...interface{}) error {
	_, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	errs := &packer.MultiError{}

	errs = packer.MultiErrorAppend(errs, p.config.AccessConfig.Prepare(p.config.tpl)...)

	// required configuration
	templates := map[string]*string{
		"bucket":   &p.config.Bucket,
		"manifest": &p.config.ManifestPath,
		"box_name": &p.config.BoxName,
		"box_dir":  &p.config.BoxDir,
		"version":  &p.config.Version,
	}

	for key, ptr := range templates {
		if *ptr == "" {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("vagrant-s3 %s must be set", key))
		}
	}

	// Template process
	for key, ptr := range templates {
		*ptr, err = p.config.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing %s: %s", key, err))
		}
	}

	// setup the s3 bucket
	auth, err := p.config.AccessConfig.Auth()
	if err != nil {
		errs = packer.MultiErrorAppend(errs, err)
	}
	p.s3 = s3.New(auth, aws.USEast).Bucket(p.config.Bucket)

	if len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	// Only accept input from the vagrant post-processor
	if artifact.BuilderId() != "mitchellh.post-processor.vagrant" {
		return nil, false, fmt.Errorf("Unknown artifact type, requires box from vagrant post-processor: %s", artifact.BuilderId())
	}

	// Assume there is only one .box file to upload
	box := artifact.Files()[0]
	if !strings.HasSuffix(box, ".box") {
		return nil, false, fmt.Errorf("Unknown files in artifact from vagrant post-processor: %s", artifact.Files())
	}

	provider := providerFromBuilderName(artifact.Id())
	ui.Say(fmt.Sprintf("Preparing to upload box for '%s' provider to S3 bucket '%s'", provider, p.config.Bucket))

	// open the box so we can upload to S3 and calculate checksum for the manifest
	file, err := os.Open(box)
	if err != nil {
		return nil, false, err
	}
	defer file.Close()

	// get the file's size
	info, err := file.Stat()
	if err != nil {
		return nil, false, err
	}
	size := info.Size()
	ui.Message(fmt.Sprintf("Box to upload: %s (%d bytes)", box, size))

	// get the latest manifest so we can add to it
	ui.Message("Fetching latest manifest")
	manifest, err := p.getManifest()
	if err != nil {
		return nil, false, err
	}

	// generate the path to store the box in S3
	boxPath := fmt.Sprintf("%s/%s/%s", p.config.BoxDir, p.config.Version, path.Base(box))

	ui.Message("Generating checksum")
	checksum, err := sum256(file)
	if err != nil {
		return nil, false, err
	}
	ui.Message(fmt.Sprintf("Checksum is %s", checksum))

	ui.Message(fmt.Sprintf("Adding %s %s box to manifest", provider, p.config.Version))
	if err := manifest.add(p.config.Version, &Provider{
		Name:         provider,
		Url:          p.s3.URL(boxPath),
		ChecksumType: "sha256",
		Checksum:     checksum,
	}); err != nil {
		return nil, false, err
	}

	// upload the box to S3 (rewinding as we already read the file to generate the checksum)
	ui.Message(fmt.Sprintf("Uploading box to S3: %s", boxPath))
	if _, err := file.Seek(0, 0); err != nil {
		return nil, false, err
	}
	if size > 100*1024*1024 {
		multi, err := p.s3.Multi(boxPath, "application/octet-stream", "public-read")
		if err != nil {
			return nil, false, err
		}
		if _, err := multi.PutAll(file, 5*1024*1024); err != nil {
			return nil, false, err
		}
	} else {
		if err := p.s3.PutReader(boxPath, file, size, "application/octet-stream", "public-read"); err != nil {
			return nil, false, err
		}
	}

	ui.Message(fmt.Sprintf("Uploading the manifest: %s", p.config.ManifestPath))
	if err := p.putManifest(manifest); err != nil {
		return nil, false, err
	}

	return &Artifact{p.s3.URL(p.config.ManifestPath)}, true, nil
}

func (p *PostProcessor) getManifest() (*Manifest, error) {
	body, err := p.s3.GetReader(p.config.ManifestPath)
	if err != nil {
		if s3Err, ok := err.(*s3.Error); ok && s3Err.Code == "NoSuchKey" {
			return &Manifest{Name: p.config.BoxName}, nil
		}
		return nil, err
	}
	defer body.Close()

	manifest := &Manifest{}
	if err := json.NewDecoder(body).Decode(manifest); err != nil {
		return nil, err
	}
	return manifest, nil
}

func (p *PostProcessor) putManifest(manifest *Manifest) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(manifest); err != nil {
		return err
	}
	if err := p.s3.Put(p.config.ManifestPath, buf.Bytes(), "application/json", "public-read"); err != nil {
		return err
	}
	return nil
}

// calculates a sha256 checksum of the file
func sum256(file *os.File) (string, error) {
	h := sha256.New()
	if _, err := io.Copy(h, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(h.Sum(nil)), nil
}

// converts a packer builder name to the corresponding vagrant provider
func providerFromBuilderName(name string) string {
	switch name {
	case "aws":
		return "aws"
	case "digitalocean":
		return "digitalocean"
	case "virtualbox":
		return "virtualbox"
	case "vmware":
		return "vmware_desktop"
	case "parallels":
		return "parallels"
	default:
		return name
	}
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"context"

	"github.com/pkg/errors"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/watch"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

// Client represents the wrapper of Kubernetes API client
type Client struct {
	clientConfig clientcmd.ClientConfig
	clientset    *kubernetes.Clientset
}

// NewClient creates Client object using local kubecfg
func NewClient(kubeconfig, context string) (*Client, error) {
	clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig},
		&clientcmd.ConfigOverrides{CurrentContext: context})

	config, err := clientConfig.ClientConfig()
	if err != nil {
		return nil, errors.Wrap(err, "falied to load local kubeconfig")
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, errors.Wrap(err, "failed to load clientset")
	}

	return &Client{
		clientConfig: clientConfig,
		clientset:    clientset,
	}, nil
}

// NewClientInCluster creates Client object in Kubernetes cluster
func NewClientInCluster() (*Client, error) {
	config, err := rest.InClusterConfig()
	if err != nil {
		return nil, errors.Wrap(err, "failed to load kubeconfig in cluster")
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, errors.Wrap(err, "falied to load clientset")
	}

	return &Client{
		clientset: clientset,
	}, nil
}

// NamespaceInConfig returns namespace set in kubeconfig
func (c *Client) NamespaceInConfig() (string, error) {
	if c.clientConfig == nil {
		return "", errors.New("clientConfig is not set")
	}

	rawConfig, err := c.clientConfig.RawConfig()
	if err != nil {
		return "", errors.Wrap(err, "failed to load rawConfig")
	}

	return rawConfig.Contexts[rawConfig.CurrentContext].Namespace, nil
}

// WatchPodEvents watches Pod events
func (c *Client) WatchPodEvents(ctx context.Context, namespace, labels string, notifySuccess, notifyFail bool, succeededFunc, failedFunc NotifyFunc) error {
	watcher, err := c.clientset.Core().Pods(namespace).Watch(v1.ListOptions{
		LabelSelector: labels,
	})
	if err != nil {
		return errors.Wrap(err, "cannot create Pod event watcher")
	}

	go func() {
		for {
			select {
			case e := <-watcher.ResultChan():
				if e.Object == nil {
					return
				}

				pod, ok := e.Object.(*v1.Pod)
				if !ok {
					continue
				}

				switch e.Type {
				case watch.Modified:
					if pod.DeletionTimestamp != nil {
						continue
					}

					startedAt := pod.CreationTimestamp.Time

					switch pod.Status.Phase {
					case v1.PodSucceeded:
						for _, cst := range pod.Status.ContainerStatuses {
							if cst.State.Terminated == nil {
								continue
							}

							finishedAt := cst.State.Terminated.FinishedAt.Time

							if cst.State.Terminated.Reason == "Completed" {
								if notifySuccess {
									succeededFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   0,
										Reason:     "",
										Message:    "",
									})
								}
							} else {
								if notifyFail {
									failedFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   int(cst.State.Terminated.ExitCode),
										Reason:     cst.State.Terminated.Reason,
										Message:    "",
									})
								}
							}

							break
						}
					case v1.PodFailed:
						if len(pod.Status.ContainerStatuses) == 0 { // e.g. Pod was evicted
							if notifyFail {
								failedFunc(&PodEvent{
									Namespace:  pod.Namespace,
									PodName:    pod.Name,
									StartedAt:  startedAt,
									FinishedAt: startedAt,
									ExitCode:   -1,
									Reason:     pod.Status.Reason,
									Message:    pod.Status.Message,
								})
							}
						} else {
							for _, cst := range pod.Status.ContainerStatuses {
								if cst.State.Terminated == nil {
									continue
								}

								if notifyFail {
									finishedAt := cst.State.Terminated.FinishedAt.Time

									failedFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   int(cst.State.Terminated.ExitCode),
										Reason:     cst.State.Terminated.Reason,
										Message:    pod.Status.Message,
									})
								}

								break
							}
						}
					default:
						for _, cst := range pod.Status.ContainerStatuses {
							if cst.State.Terminated == nil {
								continue
							}

							if notifyFail {
								finishedAt := cst.State.Terminated.FinishedAt.Time

								failedFunc(&PodEvent{
									Namespace:  pod.Namespace,
									PodName:    pod.Name,
									StartedAt:  startedAt,
									FinishedAt: finishedAt,
									ExitCode:   int(cst.State.Terminated.ExitCode),
									Reason:     cst.State.Terminated.Reason,
									Message:    pod.Status.Message,
								})
							}

							break
						}
					}
				}
			case <-ctx.Done():
				watcher.Stop()
				return
			}
		}
	}()

	return nil
}
<commit_msg>Notify no container even unless Pod failed<commit_after>package kubernetes

import (
	"context"

	"github.com/pkg/errors"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/watch"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

// Client represents the wrapper of Kubernetes API client
type Client struct {
	clientConfig clientcmd.ClientConfig
	clientset    *kubernetes.Clientset
}

// NewClient creates Client object using local kubecfg
func NewClient(kubeconfig, context string) (*Client, error) {
	clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig},
		&clientcmd.ConfigOverrides{CurrentContext: context})

	config, err := clientConfig.ClientConfig()
	if err != nil {
		return nil, errors.Wrap(err, "falied to load local kubeconfig")
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, errors.Wrap(err, "failed to load clientset")
	}

	return &Client{
		clientConfig: clientConfig,
		clientset:    clientset,
	}, nil
}

// NewClientInCluster creates Client object in Kubernetes cluster
func NewClientInCluster() (*Client, error) {
	config, err := rest.InClusterConfig()
	if err != nil {
		return nil, errors.Wrap(err, "failed to load kubeconfig in cluster")
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, errors.Wrap(err, "falied to load clientset")
	}

	return &Client{
		clientset: clientset,
	}, nil
}

// NamespaceInConfig returns namespace set in kubeconfig
func (c *Client) NamespaceInConfig() (string, error) {
	if c.clientConfig == nil {
		return "", errors.New("clientConfig is not set")
	}

	rawConfig, err := c.clientConfig.RawConfig()
	if err != nil {
		return "", errors.Wrap(err, "failed to load rawConfig")
	}

	return rawConfig.Contexts[rawConfig.CurrentContext].Namespace, nil
}

// WatchPodEvents watches Pod events
func (c *Client) WatchPodEvents(ctx context.Context, namespace, labels string, notifySuccess, notifyFail bool, succeededFunc, failedFunc NotifyFunc) error {
	watcher, err := c.clientset.Core().Pods(namespace).Watch(v1.ListOptions{
		LabelSelector: labels,
	})
	if err != nil {
		return errors.Wrap(err, "cannot create Pod event watcher")
	}

	go func() {
		for {
			select {
			case e := <-watcher.ResultChan():
				if e.Object == nil {
					return
				}

				pod, ok := e.Object.(*v1.Pod)
				if !ok {
					continue
				}

				switch e.Type {
				case watch.Modified:
					if pod.DeletionTimestamp != nil {
						continue
					}

					startedAt := pod.CreationTimestamp.Time

					switch pod.Status.Phase {
					case v1.PodSucceeded:
						for _, cst := range pod.Status.ContainerStatuses {
							if cst.State.Terminated == nil {
								continue
							}

							finishedAt := cst.State.Terminated.FinishedAt.Time

							if cst.State.Terminated.Reason == "Completed" {
								if notifySuccess {
									succeededFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   0,
										Reason:     "",
										Message:    "",
									})
								}
							} else {
								if notifyFail {
									failedFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   int(cst.State.Terminated.ExitCode),
										Reason:     cst.State.Terminated.Reason,
										Message:    "",
									})
								}
							}

							break
						}
					case v1.PodFailed:
						if len(pod.Status.ContainerStatuses) == 0 { // e.g. Pod was evicted
							if notifyFail {
								failedFunc(&PodEvent{
									Namespace:  pod.Namespace,
									PodName:    pod.Name,
									StartedAt:  startedAt,
									FinishedAt: startedAt,
									ExitCode:   -1,
									Reason:     pod.Status.Reason,
									Message:    pod.Status.Message,
								})
							}
						} else {
							for _, cst := range pod.Status.ContainerStatuses {
								if cst.State.Terminated == nil {
									continue
								}

								if notifyFail {
									finishedAt := cst.State.Terminated.FinishedAt.Time

									failedFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   int(cst.State.Terminated.ExitCode),
										Reason:     cst.State.Terminated.Reason,
										Message:    pod.Status.Message,
									})
								}

								break
							}
						}
					default:
						if len(pod.Status.ContainerStatuses) == 0 { // e.g. Pod was evicted
							if notifyFail {
								failedFunc(&PodEvent{
									Namespace:  pod.Namespace,
									PodName:    pod.Name,
									StartedAt:  startedAt,
									FinishedAt: startedAt,
									ExitCode:   -1,
									Reason:     pod.Status.Reason,
									Message:    pod.Status.Message,
								})
							}
						} else {
							for _, cst := range pod.Status.ContainerStatuses {
								if cst.State.Terminated == nil {
									continue
								}

								if notifyFail {
									finishedAt := cst.State.Terminated.FinishedAt.Time

									failedFunc(&PodEvent{
										Namespace:  pod.Namespace,
										PodName:    pod.Name,
										StartedAt:  startedAt,
										FinishedAt: finishedAt,
										ExitCode:   int(cst.State.Terminated.ExitCode),
										Reason:     cst.State.Terminated.Reason,
										Message:    pod.Status.Message,
									})
								}

								break
							}
						}
					}
				}
			case <-ctx.Done():
				watcher.Stop()
				return
			}
		}
	}()

	return nil
}
<|endoftext|>


<commit_before>package ccd

import (
	"time"

	"github.com/jteeuwen/go-pkg-xmlx"
)

var (
	VitalSignsTid = []string{"2.16.840.1.113883.10.20.1.16", "2.16.840.1.113883.10.20.22.2.4.1"}

	VitalSignsParser = Parser{
		Type:     PARSE_SECTION,
		Values:   VitalSignsTid,
		Priority: 0,
		Func:     parseVitalSigns,
	}
)

type VitalSignResult struct {
	Type  string
	Value string
	Unit  string
}

type VitalSignObservation struct {
	Name   string
	Date   time.Time
	Code   Code
	Result VitalSignResult
}

type VitalSign struct {
	Date         time.Time
	Observations []VitalSignObservation
}

func parseVitalSigns(node *xmlx.Node, ccd *CCD) []error {
	entryNodes := node.SelectNodes("*", "entry")
	for _, entryNode := range entryNodes {
		organizerNode := Nget(entryNode, "organizer")
		if organizerNode == nil {
			continue
		}

		vitalSign := VitalSign{}

		effectiveTimeNode := Nget(organizerNode, "effectiveTime")
		t := decodeTime(effectiveTimeNode)
		vitalSign.Date = t.Value

		componentNodes := organizerNode.SelectNodes("*", "component")
		for _, componentNode := range componentNodes {
			observation := VitalSignObservation{}

			codeNode := Nget(componentNode, "code")
			if codeNode == nil {
				continue
			}
			observation.Code.decode(codeNode)

			effectiveTimeNode := Nget(componentNode, "effectiveTime")
			t := decodeTime(effectiveTimeNode)
			observation.Date = t.Value

			valueNode := Nget(componentNode, "value")
			// fmt.Println(valueNode)

			observation.Result = VitalSignResult{
				Type:  valueNode.As("*", "type"),
				Value: valueNode.As("*", "value"),
				Unit:  valueNode.As("*", "unit"),
			}

			vitalSign.Observations = append(vitalSign.Observations, observation)
		}

		ccd.VitalSigns = append(ccd.VitalSigns, vitalSign)
	}

	return nil
}
<commit_msg>removed VitalSignObservation.Name.<commit_after>package ccd

import (
	"time"

	"github.com/jteeuwen/go-pkg-xmlx"
)

var (
	VitalSignsTid = []string{"2.16.840.1.113883.10.20.1.16", "2.16.840.1.113883.10.20.22.2.4.1"}

	VitalSignsParser = Parser{
		Type:     PARSE_SECTION,
		Values:   VitalSignsTid,
		Priority: 0,
		Func:     parseVitalSigns,
	}
)

type VitalSignResult struct {
	Type  string
	Value string
	Unit  string
}

type VitalSignObservation struct {
	Date   time.Time
	Code   Code
	Result VitalSignResult
}

type VitalSign struct {
	Date         time.Time
	Observations []VitalSignObservation
}

func parseVitalSigns(node *xmlx.Node, ccd *CCD) []error {
	entryNodes := node.SelectNodes("*", "entry")
	for _, entryNode := range entryNodes {
		organizerNode := Nget(entryNode, "organizer")
		if organizerNode == nil {
			continue
		}

		vitalSign := VitalSign{}

		effectiveTimeNode := Nget(organizerNode, "effectiveTime")
		t := decodeTime(effectiveTimeNode)
		vitalSign.Date = t.Value

		componentNodes := organizerNode.SelectNodes("*", "component")
		for _, componentNode := range componentNodes {
			observation := VitalSignObservation{}

			codeNode := Nget(componentNode, "code")
			if codeNode == nil {
				continue
			}
			observation.Code.decode(codeNode)

			effectiveTimeNode := Nget(componentNode, "effectiveTime")
			t := decodeTime(effectiveTimeNode)
			observation.Date = t.Value

			valueNode := Nget(componentNode, "value")
			// fmt.Println(valueNode)

			observation.Result = VitalSignResult{
				Type:  valueNode.As("*", "type"),
				Value: valueNode.As("*", "value"),
				Unit:  valueNode.As("*", "unit"),
			}

			vitalSign.Observations = append(vitalSign.Observations, observation)
		}

		ccd.VitalSigns = append(ccd.VitalSigns, vitalSign)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"runtime"

	"github.com/AdRoll/goamz/aws"
	"github.com/AdRoll/goamz/sns"
	"github.com/AdRoll/goamz/sqs"
	_ "github.com/lib/pq"
)

var SQS *sqs.SQS
var bufferCount = 2000
var sem = make(chan bool, bufferCount)

func main() {
	n := runtime.NumCPU()
	log.Println("Num CPUS:", n)
	runtime.GOMAXPROCS(n)
	for k, v := range os.Args {
		log.Println(k, v)
	}
	log.Println("-----")
	if len(os.Args) > 1 {
		rawData := os.Args[1]

		var kpayload KinesisPayload
		err := json.Unmarshal([]byte(rawData), &kpayload)
		if err != nil {
			log.Println("Error Kinesisis Payload:", err)
		}
		recrun := false
		lastrun := false
		lastpage := 0
		for _, v := range kpayload.Records {
			log.Println("Record:", v)
			var tpm topicPageMessage
			sDec, errDec := base64.StdEncoding.DecodeString(v.Kinesis.Data)
			if errDec != nil {
				log.Println("Error:", errDec)
			} else {
				log.Println(string(sDec))
				errJSON := json.Unmarshal(sDec, &tpm)
				if errJSON != nil {
					log.Println("Error:", errJSON)
					return
				}
				arns := getDevicesArnsByTopicIDPage(tpm.TopicID, tpm.PageNum, 10000)
				//This should return the arn & the lang for the user
				//we'd then pull the correct iten out of the message map
				msgSlice := make([]sqs.Message, 0, 10)
				msgAll := [][]sqs.Message{}
				log.Printf("Started page %v\n", tpm.PageNum)
				for _, v := range arns {
					tempData := fmt.Sprintf("arn:%v|%v", v, tpm.Message)
					msg := sqs.Message{Body: base64.StdEncoding.EncodeToString([]byte(tempData))}
					msgSlice = append(msgSlice, msg)
					if len(msgSlice) == 10 {
						msgAll = append(msgAll, msgSlice)
						msgSlice = []sqs.Message{}
					}
				}
				for _, s := range msgAll {
					s := s //It's idomatic go I swear! http://golang.org/doc/effective_go.html#channels

					//Using the Semaphore
					sem <- true
					go func(sl10 []sqs.Message) {
						proxySNS(sl10)
						defer func() { <-sem }()
					}(s)

				}
				for i := 0; i < cap(sem); i++ {
					sem <- true
				}
				log.Println("All done!")
			}
			if tpm.PageNum == 1 && !recrun {
				publishPageComplete(1)
			}
			recrun = true
			if tpm.LastPage {
				lastrun = true
				lastpage = tpm.PageNum
				publishPageComplete(tpm.PageNum)
			}
			log.Printf("Completed page %v\n", tpm.PageNum)

		}
		if lastrun {
			publishPageComplete(lastpage)
		}
		return

	}
	log.Println("Error: os.Args was 1 length.")
}
func publishPageComplete(pagenum int) error {
	topicarn, topicErr := getTopicArn()
	if topicErr != nil {
		log.Println(topicErr)
		return topicErr
	}
	p, s, _ := getSettings()
	auth := aws.Auth{AccessKey: p, SecretKey: s}
	region := aws.Region{}
	region.Name = "us-east-1"
	region.SNSEndpoint = "http://sns.us-east-1.amazonaws.com"
	awssns, _ := sns.New(auth, region)
	if awssns == nil {
		return fmt.Errorf("Can't get sns reference for %v %v", auth, region)
	}
	msg := fmt.Sprintf("Page %v complete.", pagenum)
	opt := sns.PublishOptions{}
	opt.TopicArn = topicarn
	opt.Message = msg
	opt.Subject = msg
	_, pubErr := awssns.Publish(&opt)
	if pubErr != nil {
		return pubErr
	}
	return nil
}

func getDevicesArnsByTopicIDPage(topicID, pagenum, pagesize int) []string {
	var arns []string
	info := getDBSettings()
	db, errCon := sql.Open("postgres", fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=require", info.Host, info.Username, info.Password, info.Database))
	defer db.Close()
	if errCon != nil {
		log.Fatal(errCon)
	}
	rows, err := db.Query(`
		select
			u.endpointarn
		from
			subscription s ,userdevices u
		where
			s.topicid= $1 and
			s.userID=u.userid
			order by u.userid
			limit $2 offset $3
;`, topicID, pagesize, (pagenum-1)*pagesize)
	if err != nil {
		panic(err)
	}
	for rows.Next() {
		var arn string
		errScan := rows.Scan(&arn)
		if errScan != nil {
			panic(errScan)
		}
		arns = append(arns, arn)
	}
	return arns
}

type topicPageMessage struct {
	TopicID  int    `json:"topic_id"`
	Message  string `json:"message"`
	PageNum  int    `json:"page_num"`
	LastPage bool   `json:"last_page"`
}

type KinesisPayload struct {
	Records []struct {
		AwsRegion         string `json:"awsRegion"`
		EventID           string `json:"eventID"`
		EventName         string `json:"eventName"`
		EventSource       string `json:"eventSource"`
		EventSourceARN    string `json:"eventSourceARN"`
		EventVersion      string `json:"eventVersion"`
		InvokeIdentityArn string `json:"invokeIdentityArn"`
		Kinesis           struct {
			Data                 string `json:"data"`
			KinesisSchemaVersion string `json:"kinesisSchemaVersion"`
			PartitionKey         string `json:"partitionKey"`
			SequenceNumber       string `json:"sequenceNumber"`
		} `json:"kinesis"`
	} `json:"Records"`
}

func getTopicArn() (string, error) {
	file, err := ioutil.ReadFile("./settings.json")
	if err != nil {
		return "", err
	}
	settingsMap := make(map[string]string)
	json.Unmarshal(file, &settingsMap)
	return settingsMap["Topicarn"], nil
}

func getSettings() (string, string, error) {
	file, err := ioutil.ReadFile("./settings.json")
	if err != nil {
		return "", "", nil
	}
	settingsMap := make(map[string]string)
	json.Unmarshal(file, &settingsMap)
	return settingsMap["Access"], settingsMap["Secret"], nil
}

func getDBSettings() *dbInfo {
	file, err := ioutil.ReadFile("./settings.json")
	if err != nil {
		log.Println("Error:", err)
		return nil
	}
	db := dbInfo{}
	err2 := json.Unmarshal(file, &db)
	if err2 != nil {
		log.Println("Error:", err2)
		return nil
	}
	return &db
}

type dbInfo struct {
	Host     string
	Database string
	Username string
	Password string
}

func proxySNS(msgs []sqs.Message) {
	pub, sec, _ := getSettings()
	sqs, err := getQueue("sns-prox", pub, sec)
	if err != nil {
		panic(err)
	}
	_, respErr := sqs.SendMessageBatch(msgs)
	if respErr != nil {
		log.Println("ERROR:", respErr)
	}
}

func getQueue(name, public, secret string) (*sqs.Queue, error) {
	auth := aws.Auth{AccessKey: public, SecretKey: secret}
	region := aws.Region{}
	region.Name = "us-east-1"
	region.SQSEndpoint = "http://sqs.us-east-1.amazonaws.com"
	awssqs := sqs.New(auth, region)
	if awssqs == nil {
		return nil, fmt.Errorf("Can't get sqs reference for %v %v", auth, region)
	}
	return awssqs.GetQueue(name)
}
<commit_msg>get rid of the batch stuff, just one at a time<commit_after>package main

import (
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"runtime"

	"github.com/AdRoll/goamz/aws"
	"github.com/AdRoll/goamz/sns"
	"github.com/AdRoll/goamz/sqs"
	_ "github.com/lib/pq"
)

var SQS *sqs.SQS
var bufferCount = 2000
var sem = make(chan bool, bufferCount)

func main() {
	n := runtime.NumCPU()
	log.Println("Num CPUS:", n)
	runtime.GOMAXPROCS(n)
	for k, v := range os.Args {
		log.Println(k, v)
	}
	log.Println("-----")
	if len(os.Args) > 1 {
		rawData := os.Args[1]

		var kpayload KinesisPayload
		err := json.Unmarshal([]byte(rawData), &kpayload)
		if err != nil {
			log.Println("Error Kinesisis Payload:", err)
		}
		for _, v := range kpayload.Records {
			log.Println("Record:", v)
			var tpm topicPageMessage
			sDec, errDec := base64.StdEncoding.DecodeString(v.Kinesis.Data)
			if errDec != nil {
				log.Println("Error:", errDec)
			} else {
				log.Println(string(sDec))
				errJSON := json.Unmarshal(sDec, &tpm)
				if errJSON != nil {
					log.Println("Error:", errJSON)
					return
				}
				arns := getDevicesArnsByTopicIDPage(tpm.TopicID, tpm.PageNum, 10000)
				//This should return the arn & the lang for the user
				//we'd then pull the correct iten out of the message map
				msgSlice := make([]sqs.Message, 0, 10)
				msgAll := [][]sqs.Message{}
				log.Printf("Started page %v\n", tpm.PageNum)
				for _, v := range arns {
					tempData := fmt.Sprintf("arn:%v|%v", v, tpm.Message)
					msg := sqs.Message{Body: base64.StdEncoding.EncodeToString([]byte(tempData))}
					msgSlice = append(msgSlice, msg)
					if len(msgSlice) == 10 {
						msgAll = append(msgAll, msgSlice)
						msgSlice = []sqs.Message{}
					}
				}
				for _, s := range msgAll {
					s := s //It's idomatic go I swear! http://golang.org/doc/effective_go.html#channels

					//Using the Semaphore
					sem <- true
					go func(sl10 []sqs.Message) {
						proxySNS(sl10)
						defer func() { <-sem }()
					}(s)

				}
				for i := 0; i < cap(sem); i++ {
					sem <- true
				}
				log.Println("All done!")
			}
			if tpm.PageNum == 1 {
				publishPageComplete(1)
			}
			if tpm.LastPage {
				publishPageComplete(tpm.PageNum)
			}
			log.Printf("Completed page %v\n", tpm.PageNum)

		}
		return

	}
	log.Println("Error: os.Args was 1 length.")
}
func publishPageComplete(pagenum int) error {
	topicarn, topicErr := getTopicArn()
	if topicErr != nil {
		log.Println(topicErr)
		return topicErr
	}
	p, s, _ := getSettings()
	auth := aws.Auth{AccessKey: p, SecretKey: s}
	region := aws.Region{}
	region.Name = "us-east-1"
	region.SNSEndpoint = "http://sns.us-east-1.amazonaws.com"
	awssns, _ := sns.New(auth, region)
	if awssns == nil {
		return fmt.Errorf("Can't get sns reference for %v %v", auth, region)
	}
	msg := fmt.Sprintf("Page %v complete.", pagenum)
	opt := sns.PublishOptions{}
	opt.TopicArn = topicarn
	opt.Message = msg
	opt.Subject = msg
	_, pubErr := awssns.Publish(&opt)
	if pubErr != nil {
		return pubErr
	}
	return nil
}

func getDevicesArnsByTopicIDPage(topicID, pagenum, pagesize int) []string {
	var arns []string
	info := getDBSettings()
	db, errCon := sql.Open("postgres", fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=require", info.Host, info.Username, info.Password, info.Database))
	defer db.Close()
	if errCon != nil {
		log.Fatal(errCon)
	}
	rows, err := db.Query(`
		select
			u.endpointarn
		from
			subscription s ,userdevices u
		where
			s.topicid= $1 and
			s.userID=u.userid
			order by u.userid
			limit $2 offset $3
;`, topicID, pagesize, (pagenum-1)*pagesize)
	if err != nil {
		panic(err)
	}
	for rows.Next() {
		var arn string
		errScan := rows.Scan(&arn)
		if errScan != nil {
			panic(errScan)
		}
		arns = append(arns, arn)
	}
	return arns
}

type topicPageMessage struct {
	TopicID  int    `json:"topic_id"`
	Message  string `json:"message"`
	PageNum  int    `json:"page_num"`
	LastPage bool   `json:"last_page"`
}

type KinesisPayload struct {
	Records []struct {
		AwsRegion         string `json:"awsRegion"`
		EventID           string `json:"eventID"`
		EventName         string `json:"eventName"`
		EventSource       string `json:"eventSource"`
		EventSourceARN    string `json:"eventSourceARN"`
		EventVersion      string `json:"eventVersion"`
		InvokeIdentityArn string `json:"invokeIdentityArn"`
		Kinesis           struct {
			Data                 string `json:"data"`
			KinesisSchemaVersion string `json:"kinesisSchemaVersion"`
			PartitionKey         string `json:"partitionKey"`
			SequenceNumber       string `json:"sequenceNumber"`
		} `json:"kinesis"`
	} `json:"Records"`
}

func getTopicArn() (string, error) {
	file, err := ioutil.ReadFile("./settings.json")
	if err != nil {
		return "", err
	}
	settingsMap := make(map[string]string)
	json.Unmarshal(file, &settingsMap)
	return settingsMap["Topicarn"], nil
}

func getSettings() (string, string, error) {
	file, err := ioutil.ReadFile("./settings.json")
	if err != nil {
		return "", "", nil
	}
	settingsMap := make(map[string]string)
	json.Unmarshal(file, &settingsMap)
	return settingsMap["Access"], settingsMap["Secret"], nil
}

func getDBSettings() *dbInfo {
	file, err := ioutil.ReadFile("./settings.json")
	if err != nil {
		log.Println("Error:", err)
		return nil
	}
	db := dbInfo{}
	err2 := json.Unmarshal(file, &db)
	if err2 != nil {
		log.Println("Error:", err2)
		return nil
	}
	return &db
}

type dbInfo struct {
	Host     string
	Database string
	Username string
	Password string
}

func proxySNS(msgs []sqs.Message) {
	pub, sec, _ := getSettings()
	sqs, err := getQueue("sns-prox", pub, sec)
	if err != nil {
		panic(err)
	}
	_, respErr := sqs.SendMessageBatch(msgs)
	if respErr != nil {
		log.Println("ERROR:", respErr)
	}
}

func getQueue(name, public, secret string) (*sqs.Queue, error) {
	auth := aws.Auth{AccessKey: public, SecretKey: secret}
	region := aws.Region{}
	region.Name = "us-east-1"
	region.SQSEndpoint = "http://sqs.us-east-1.amazonaws.com"
	awssqs := sqs.New(auth, region)
	if awssqs == nil {
		return nil, fmt.Errorf("Can't get sqs reference for %v %v", auth, region)
	}
	return awssqs.GetQueue(name)
}
<|endoftext|>