<commit_before>package neustar

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/google/go-querystring/query"
)

const (
	// MonitorURI is the endpoint for calls to the monitoring API
	MonitorURI = "monitor/1.0"

	// LocationsURI is the endpoint for locations calls
	LocationsURI = "/locations"

	// SummaryURI is the endpoint for summary calls
	SummaryURI = "/summary"

	// AggregateURI is the endpoint for aggregate calls
	AggregateURI = "/aggregate"
)

// MonitorTypes is a slice of valid monitor types
var MonitorTypes = []string{"RealBrowserUser", "VirtualUser", "dns"}

// BrowserTypes is a slice of valid browser types
var BrowserTypes = []string{"FF", "CHROME", "IE"}

// UpdateIntervals is a slice of valid intervals
var UpdateIntervals = []int{1, 2, 3, 4, 5, 10, 15, 20, 30, 60}

// AggregateSampleDataFrequency is a slice of valid frequencies
var AggregateSampleDataFrequency = []string{"day", "hour"}

// AggregateSampleGroupBy is a slice of valid groupBy parameters
var AggregateSampleGroupBy = []string{"location", "step"}

// Monitoring holds monitoring config
type Monitoring struct {
	neustar *Neustar
}

// NewMonitor creates a new Monitoring object
func NewMonitor(neustar *Neustar) *Monitoring {
	return &Monitoring{
		neustar: neustar,
	}
}

// Create creates a new monitor and returns the monitor id of the newly
// created monitor. Name, interval, testScript and locations are required.
// Use the Get Monitoring Locations api to retrieve a list of monitoring locations.
func (m *Monitoring) Create() {}

// List retrieves a list of all monitors associated with your account,
//along with information about each. The monitor id that is returned
// is used to make other api calls.
func (m *Monitoring) List() ([]Monitor, int, error) {
	var response *http.Response
	var data map[string]map[string][]Monitor
	response, err := http.Get(fmt.Sprintf("%s%s?apikey=%s&sig=%s", BaseURL, MonitorURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Get retrieves information for a specific monitor associated with your
// account. The monitor id that is returned is used to make other api calls.
func (m *Monitoring) Get(id string) ([]Monitor, int, error) {
	var response *http.Response
	var data map[string]map[string][]Monitor
	response, err := http.Get(fmt.Sprintf("%s%s/%s?apikey=%s&sig=%s", BaseURL, MonitorURI, id, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Update changes some or all of the parameters of an existing monitor.
// Requires the monitor ID retrieved from the List Monitors api.
func (m *Monitoring) Update() {}

// Delete deletes the given monitor, stopping it from monitoring and removing
// all its monitoring data.
func (m *Monitoring) Delete(id string) (int, error) {
	var response *http.Response
	response, err := http.Get(fmt.Sprintf("%s%s/%s?apikey=%s&sig=%s", BaseURL, MonitorURI, id, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return response.StatusCode, err
	}
	if response.StatusCode != 200 {
		return response.StatusCode, nil
	}
	return response.StatusCode, nil
}

// Samples returns all samples associated to this monitor for a given time period.
// This data is returned at a high level, which timing for the overall sample. To
// get the details for the specific sample, call the get raw sample data api. At a
// maximum, this api will return 2000 samples. If there are more than 2000 results
// returned, the 'more' field will be set to true and you can make another api call
// specifying an offset which would be equal to the number of results returned in the
// first api call plus the offset of that call.
func (m *Monitoring) Samples() ([]string, int, error) {
	var response *http.Response
	var data map[string]map[string][]string
	response, err := http.Get(fmt.Sprintf("%s%s?apikey=%s&sig=%s", BaseURL, MonitorURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// RawSampleData retrieves the raw, HTTP Archive (HAR) data for a particular sample
func (m *Monitoring) RawSampleData(monitorID, sampleID string) {}

// AggregateSampleData retrieves the aggregated sample information for a given period
// of time. You can choose to aggregate the data for each hour or each day. This is
// more effecient than getting all the individual samples for a period of time and
// performing the aggregation yourself.
func (m *Monitoring) AggregateSampleData(monitorID string, asp *AggregateSampleParameters) ([]AggregateSampleDataResponse, int, error) {
	var response *http.Response
	v, err := query.Values(asp)
	if err != nil {
		return nil, 0, err
	}
	var data map[string]map[string][]AggregateSampleDataResponse
	response, err = http.Get(fmt.Sprintf("%s%s/%s%s?%s&apikey=%s&sig=%s", BaseURL, MonitorURI, monitorID, AggregateURI, v.Encode(), m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Summary provides the monitor summary api returns all of the data that is found when looking at your
// list of monitors in the web portal. This includes things such as the average load
// time, sample count and uptime for the day, week, month or year, the last time an
// error occurred, and the last error message.
func (m *Monitoring) Summary(monitorID string) ([]SummaryDataResponse, int, error) {
	var response *http.Response
	var data map[string]map[string][]SummaryDataResponse
	response, err := http.Get(fmt.Sprintf("%s%s/%s/%s?apikey=%s&sig=%s", BaseURL, MonitorURI, monitorID, SummaryURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Locations gets a list of all monitoring locations available
func (m *Monitoring) Locations() ([]string, int, error) {
	var response *http.Response
	var data map[string]map[string][]string
	response, err := http.Get(fmt.Sprintf("%s%s%s?apikey=%s&sig=%s", BaseURL, MonitorURI, LocationsURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// ValidMonitorType validates the given monitor type is valid
func ValidMonitorType(monitorType string) bool {
	for _, i := range MonitorTypes {
		if i == monitorType {
			return true
		}
	}
	return false
}

// ValidBrowserType validates the given browser type is valid
func ValidBrowserType(browserType string) bool {
	for _, i := range BrowserTypes {
		if i == browserType {
			return true
		}
	}
	return false
}

// ValidUpdateInterval validates the given interval is valid
func ValidUpdateInterval(interval int) bool {
	for _, i := range UpdateIntervals {
		if i == interval {
			return true
		}
	}
	return false
}

// ValidAggregateSampleDataFrequency validates the given frequency is valid
func ValidAggregateSampleDataFrequency(frequency string) bool {
	for _, i := range AggregateSampleDataFrequency {
		if i == frequency {
			return true
		}
	}
	return false
}

// ValidAggregateSampleGroupBy validates the given groupBy is valid
func ValidAggregateSampleGroupBy(groupBy string) bool {
	for _, i := range AggregateSampleGroupBy {
		if i == frequency {
			return true
		}
	}
	return false
}
<commit_msg>small bug fix, reformat<commit_after>package neustar

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/google/go-querystring/query"
)

const (
	// MonitorURI is the endpoint for calls to the monitoring API
	MonitorURI = "monitor/1.0"

	// LocationsURI is the endpoint for locations calls
	LocationsURI = "/locations"

	// SummaryURI is the endpoint for summary calls
	SummaryURI = "/summary"

	// AggregateURI is the endpoint for aggregate calls
	AggregateURI = "/aggregate"
)

// MonitorTypes is a slice of valid monitor types
var MonitorTypes = []string{"RealBrowserUser", "VirtualUser", "dns"}

// BrowserTypes is a slice of valid browser types
var BrowserTypes = []string{"FF", "CHROME", "IE"}

// UpdateIntervals is a slice of valid intervals
var UpdateIntervals = []int{1, 2, 3, 4, 5, 10, 15, 20, 30, 60}

// AggregateSampleDataFrequency is a slice of valid frequencies
var AggregateSampleDataFrequency = []string{"day", "hour"}

// AggregateSampleGroupBy is a slice of valid groupBy parameters
var AggregateSampleGroupBy = []string{"location", "step"}

// Monitoring holds monitoring config
type Monitoring struct {
	neustar *Neustar
}

// NewMonitor creates a new Monitoring object
func NewMonitor(neustar *Neustar) *Monitoring {
	return &Monitoring{
		neustar: neustar,
	}
}

// Create creates a new monitor and returns the monitor id of the newly
// created monitor. Name, interval, testScript and locations are required.
// Use the Get Monitoring Locations api to retrieve a list of monitoring locations.
func (m *Monitoring) Create() {}

// List retrieves a list of all monitors associated with your account,
//along with information about each. The monitor id that is returned
// is used to make other api calls.
func (m *Monitoring) List() ([]Monitor, int, error) {
	var response *http.Response
	var data map[string]map[string][]Monitor
	response, err := http.Get(fmt.Sprintf(
		"%s%s?apikey=%s&sig=%s",
		BaseURL, MonitorURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Get retrieves information for a specific monitor associated with your
// account. The monitor id that is returned is used to make other api calls.
func (m *Monitoring) Get(id string) ([]Monitor, int, error) {
	var response *http.Response
	var data map[string]map[string][]Monitor
	response, err := http.Get(fmt.Sprintf(
		"%s%s/%s?apikey=%s&sig=%s",
		BaseURL, MonitorURI, id, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Update changes some or all of the parameters of an existing monitor.
// Requires the monitor ID retrieved from the List Monitors api.
func (m *Monitoring) Update() {}

// Delete deletes the given monitor, stopping it from monitoring and removing
// all its monitoring data.
func (m *Monitoring) Delete(id string) (int, error) {
	var response *http.Response
	response, err := http.Get(fmt.Sprintf(
		"%s%s/%s?apikey=%s&sig=%s",
		BaseURL, MonitorURI, id, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return response.StatusCode, err
	}
	if response.StatusCode != 200 {
		return response.StatusCode, nil
	}
	return response.StatusCode, nil
}

// Samples returns all samples associated to this monitor for a given time period.
// This data is returned at a high level, which timing for the overall sample. To
// get the details for the specific sample, call the get raw sample data api. At a
// maximum, this api will return 2000 samples. If there are more than 2000 results
// returned, the 'more' field will be set to true and you can make another api call
// specifying an offset which would be equal to the number of results returned in the
// first api call plus the offset of that call.
func (m *Monitoring) Samples() ([]string, int, error) {
	var response *http.Response
	var data map[string]map[string][]string
	response, err := http.Get(fmt.Sprintf(
		"%s%s?apikey=%s&sig=%s",
		BaseURL, MonitorURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// RawSampleData retrieves the raw, HTTP Archive (HAR) data for a particular sample
func (m *Monitoring) RawSampleData(monitorID, sampleID string) {}

// AggregateSampleData retrieves the aggregated sample information for a given period
// of time. You can choose to aggregate the data for each hour or each day. This is
// more effecient than getting all the individual samples for a period of time and
// performing the aggregation yourself.
func (m *Monitoring) AggregateSampleData(monitorID string, asp *AggregateSampleParameters) ([]AggregateSampleDataResponse, int, error) {
	var response *http.Response
	v, err := query.Values(asp)
	if err != nil {
		return nil, 0, err
	}
	var data map[string]map[string][]AggregateSampleDataResponse
	response, err = http.Get(fmt.Sprintf(
		"%s%s/%s%s?%s&apikey=%s&sig=%s",
		BaseURL, MonitorURI, monitorID, AggregateURI, v.Encode(), m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Summary provides the monitor summary api returns all of the data that is found when looking at your
// list of monitors in the web portal. This includes things such as the average load
// time, sample count and uptime for the day, week, month or year, the last time an
// error occurred, and the last error message.
func (m *Monitoring) Summary(monitorID string) ([]SummaryDataResponse, int, error) {
	var response *http.Response
	var data map[string]map[string][]SummaryDataResponse
	response, err := http.Get(fmt.Sprintf(
		"%s%s/%s/%s?apikey=%s&sig=%s",
		BaseURL, MonitorURI, monitorID, SummaryURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// Locations gets a list of all monitoring locations available
func (m *Monitoring) Locations() ([]string, int, error) {
	var response *http.Response
	var data map[string]map[string][]string
	response, err := http.Get(fmt.Sprintf(
		"%s%s%s?apikey=%s&sig=%s",
		BaseURL, MonitorURI, LocationsURI, m.neustar.Key, m.neustar.DigitalSignature()))
	if err != nil {
		return nil, response.StatusCode, err
	}
	defer response.Body.Close()
	if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
		return nil, response.StatusCode, err
	}
	return data["data"]["items"], response.StatusCode, nil
}

// ValidMonitorType validates the given monitor type is valid
func ValidMonitorType(monitorType string) bool {
	for _, i := range MonitorTypes {
		if i == monitorType {
			return true
		}
	}
	return false
}

// ValidBrowserType validates the given browser type is valid
func ValidBrowserType(browserType string) bool {
	for _, i := range BrowserTypes {
		if i == browserType {
			return true
		}
	}
	return false
}

// ValidUpdateInterval validates the given interval is valid
func ValidUpdateInterval(interval int) bool {
	for _, i := range UpdateIntervals {
		if i == interval {
			return true
		}
	}
	return false
}

// ValidAggregateSampleDataFrequency validates the given frequency is valid
func ValidAggregateSampleDataFrequency(frequency string) bool {
	for _, i := range AggregateSampleDataFrequency {
		if i == frequency {
			return true
		}
	}
	return false
}

// ValidAggregateSampleGroupBy validates the given groupBy is valid
func ValidAggregateSampleGroupBy(groupBy string) bool {
	for _, i := range AggregateSampleGroupBy {
		if i == groupBy {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2015 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 forecast

import (
	"fmt"
	"math"
)

// Returns the unique integer r such that x == r (mod m) and 0 <= r < m
func mod(x int, m int) int {
	return ((x % m) + m) % m
}

// LinearRegression estimates ys as (a + b*t) and returns (a, b).
// It performs linear regression using the explicit form for minimization of least-squares error.
// When ys[i] is NaN, it is treated as a missing point. (This makes things only slightly more complicated).
func LinearRegression(ys []float64) (float64, float64) {
	xm := 0.0  // mean of xs[i]
	ym := 0.0  // mean of ys[i]
	xym := 0.0 // mean of xs[i]*ys[i]
	x2m := 0.0 // mean of xs[i]^2
	c := 0     // count
	for i := range ys {
		if math.IsNaN(ys[i]) {
			continue
		}
		c++
		xm += float64(i)
		ym += ys[i]
		xym += float64(i) * ys[i]
		x2m += float64(i) * float64(i)
	}
	xm /= float64(c)
	ym /= float64(c)
	xym /= float64(c)
	x2m /= float64(c)
	// See https://en.wikipedia.org/wiki/Simple_linear_regression#Fitting_the_regression_line for justification.
	beta := (xym - xm*ym) / (x2m - xm*xm)
	alpha := ym - beta*xm
	return alpha, beta
}

func pValueFromNormalDifferences(correct []float64, estimate []float64) ([]float64, error) {
	if len(correct) != len(estimate) {
		return nil, fmt.Errorf("p-value calculation requires two lists of equal size")
	}
	deviations := []float64{}
	for i := range correct {
		if math.IsInf(correct[i], 0) || math.IsNaN(correct[i]) {
			continue
		}
		if math.IsInf(estimate[i], 0) || math.IsNaN(estimate[i]) {
			continue
		}
		deviations = append(deviations, estimate[i]-correct[i])
	}
	meandev := 0.0
	for _, dev := range deviations {
		meandev += dev
	}
	meandev /= float64(len(deviations))
	stddev := 0.0
	for _, dev := range deviations {
		stddev += (meandev - dev) * (meandev - dev)
	}
	stddev /= float64(len(deviations)) - 1
	stddev = math.Sqrt(stddev) // Now we have a good estimate for the population standard deviation.
	pvalues := make([]float64, len(estimate))
	for i := range pvalues {
		if math.IsInf(correct[i], 0) || math.IsNaN(correct[i]) {
			pvalues[i] = math.NaN()
			continue
		}
		if math.IsInf(estimate[i], 0) || math.IsNaN(estimate[i]) {
			pvalues[i] = math.NaN()
			continue
		}
		difference := estimate[i] - correct[i]
		tvalue := (difference - meandev) / stddev
		pvalue := 2 * math.Erf(-math.Abs(tvalue))
		pvalues[i] = pvalue
	}
	return pvalues, nil
}
<commit_msg>fix p-value definition wrt. error function<commit_after>// Copyright 2015 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 forecast

import (
	"fmt"
	"math"
)

// Returns the unique integer r such that x == r (mod m) and 0 <= r < m
func mod(x int, m int) int {
	return ((x % m) + m) % m
}

// LinearRegression estimates ys as (a + b*t) and returns (a, b).
// It performs linear regression using the explicit form for minimization of least-squares error.
// When ys[i] is NaN, it is treated as a missing point. (This makes things only slightly more complicated).
func LinearRegression(ys []float64) (float64, float64) {
	xm := 0.0  // mean of xs[i]
	ym := 0.0  // mean of ys[i]
	xym := 0.0 // mean of xs[i]*ys[i]
	x2m := 0.0 // mean of xs[i]^2
	c := 0     // count
	for i := range ys {
		if math.IsNaN(ys[i]) {
			continue
		}
		c++
		xm += float64(i)
		ym += ys[i]
		xym += float64(i) * ys[i]
		x2m += float64(i) * float64(i)
	}
	xm /= float64(c)
	ym /= float64(c)
	xym /= float64(c)
	x2m /= float64(c)
	// See https://en.wikipedia.org/wiki/Simple_linear_regression#Fitting_the_regression_line for justification.
	beta := (xym - xm*ym) / (x2m - xm*xm)
	alpha := ym - beta*xm
	return alpha, beta
}

func pValueFromNormalDifferences(correct []float64, estimate []float64) ([]float64, error) {
	if len(correct) != len(estimate) {
		return nil, fmt.Errorf("p-value calculation requires two lists of equal size")
	}
	deviations := []float64{}
	for i := range correct {
		if math.IsInf(correct[i], 0) || math.IsNaN(correct[i]) {
			continue
		}
		if math.IsInf(estimate[i], 0) || math.IsNaN(estimate[i]) {
			continue
		}
		deviations = append(deviations, estimate[i]-correct[i])
	}
	meandev := 0.0
	for _, dev := range deviations {
		meandev += dev
	}
	meandev /= float64(len(deviations))
	stddev := 0.0
	for _, dev := range deviations {
		stddev += (meandev - dev) * (meandev - dev)
	}
	stddev /= float64(len(deviations)) - 1
	stddev = math.Sqrt(stddev) // Now we have a good estimate for the population standard deviation.
	pvalues := make([]float64, len(estimate))
	for i := range pvalues {
		if math.IsInf(correct[i], 0) || math.IsNaN(correct[i]) {
			pvalues[i] = math.NaN()
			continue
		}
		if math.IsInf(estimate[i], 0) || math.IsNaN(estimate[i]) {
			pvalues[i] = math.NaN()
			continue
		}
		difference := estimate[i] - correct[i]
		tvalue := (difference - meandev) / stddev
		pvalue := 1 - math.Erf(math.Abs(tvalue)/math.Sqrt2)
		pvalues[i] = pvalue
	}
	return pvalues, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Datacratic. All rights reserved.

package metric

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

// Publisher defines an interface where the summary of metrics can be published.
type Publisher interface {
	Send(s *Summary)
}

// PublisherFunc defines a convenience type to wrap a Publisher function.
type PublisherFunc func(s *Summary)

// Send sends the summary to the publisher functions.
func (fn PublisherFunc) Send(s *Summary) {
	fn(s)
}

// DefaultMetricPublishInterval defines the default frequency used to publish the summary of metrics.
var DefaultMetricPublishInterval = time.Second

// Monitor implements a service where metrics can be posted.
type Monitor struct {
	// Name contains an friendly identifier for this set of metrics.
	Name string
	// Publisher represents the handler that will receives the summary of metrics periodically.
	Publisher Publisher
	// PublishInterval contains the frequency of publication. Will use DefaultMetricPublishInterval if 0.
	PublishInterval time.Duration

	summary *Summary
	records chan metricSet
}

type metricSet struct {
	name string
	data interface{}
}

// Start creates the background service that aggregate metrics and publish them periodically.
func (monitor *Monitor) Start() {
	if monitor.Name == "" {
		panic("Name must be set for monitor")
	}

	if monitor.Publisher == nil {
		monitor.PublishFunc(func(s *Summary) {
			text, err := json.MarshalIndent(s, "", "\t")
			if err != nil {
				log.Panic(err)
			}

			log.Println(string(text))
		})
	}

	monitor.summary = &Summary{
		Name: monitor.Name,
		Data: make(map[string]*Metrics),
	}

	if monitor.PublishInterval == 0 {
		monitor.PublishInterval = DefaultMetricPublishInterval
	}

	monitor.records = make(chan metricSet)

	// start the background service
	go func() {
		t := time.NewTicker(monitor.PublishInterval)
		for {
			select {
			case r := <-monitor.records:
				monitor.summary.Record(r.name, r.data)

			case <-t.C:
				if len(monitor.summary.Data) == 0 {
					break
				}

				s := monitor.summary
				s.Time = time.Now()
				s.Step = monitor.PublishInterval
				s.Send++
				monitor.summary = &Summary{
					Name: s.Name,
					Data: make(map[string]*Metrics),
					Send: s.Send,
				}

				monitor.Publisher.Send(s)
			}
		}
	}()

	return
}

// RecordMetrics posts a set of metrics to the monitor background service.
func (monitor *Monitor) RecordMetrics(name string, data interface{}) {
	monitor.records <- metricSet{
		name: name,
		data: data,
	}
}

// Publish sets the publish handler.
func (monitor *Monitor) Publish(handler Publisher) {
	monitor.Publisher = handler
}

// PublishFunc defines an helper to support the Publisher interface.
type PublishFunc func(*Summary)

// Send invokes the function literal with the summary.
func (f PublishFunc) Send(s *Summary) {
	f(s)
}

// PublishFunc is an helper that sets a function literal as the publish handler.
func (monitor *Monitor) PublishFunc(handler func(*Summary)) {
	monitor.Publish(PublishFunc(handler))
}

// NewJSONMonitor creates and starts a monitor that POST the summary of metrics as a JSON object to the specified URL.
func NewJSONMonitor(name string, url string) (monitor *Monitor) {
	monitor = &Monitor{
		Name: name,
	}

	monitor.PublishFunc(func(s *Summary) {
		text, err := json.Marshal(s)
		if err != nil {
			log.Panic(err)
		}

		r, err := http.Post(url, "application/json", bytes.NewReader(text))
		if err != nil {
			log.Panic(err)
		}

		_, err = ioutil.ReadAll(r.Body)
		if err != nil {
			log.Panic(err)
		}

		r.Body.Close()
	})

	monitor.Start()
	return
}

var nullMonitor *Monitor

// NullMonitor defines a monitor that doesn't publish its results.
func NullMonitor() *Monitor {
	return nullMonitor
}

func init() {
	nullMonitor = &Monitor{
		Name:            "null",
		Publisher:       PublisherFunc(func(s *Summary) {}),
		PublishInterval: time.Second,
	}
	nullMonitor.Start()
}
<commit_msg>converted panic to log.Panic.<commit_after>// Copyright (c) 2014 Datacratic. All rights reserved.

package metric

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

// Publisher defines an interface where the summary of metrics can be published.
type Publisher interface {
	Send(s *Summary)
}

// PublisherFunc defines a convenience type to wrap a Publisher function.
type PublisherFunc func(s *Summary)

// Send sends the summary to the publisher functions.
func (fn PublisherFunc) Send(s *Summary) {
	fn(s)
}

// DefaultMetricPublishInterval defines the default frequency used to publish the summary of metrics.
var DefaultMetricPublishInterval = time.Second

// Monitor implements a service where metrics can be posted.
type Monitor struct {
	// Name contains an friendly identifier for this set of metrics.
	Name string
	// Publisher represents the handler that will receives the summary of metrics periodically.
	Publisher Publisher
	// PublishInterval contains the frequency of publication. Will use DefaultMetricPublishInterval if 0.
	PublishInterval time.Duration

	summary *Summary
	records chan metricSet
}

type metricSet struct {
	name string
	data interface{}
}

// Start creates the background service that aggregate metrics and publish them periodically.
func (monitor *Monitor) Start() {
	if monitor.Name == "" {
		log.Panic("Name must be set for monitor")
	}

	if monitor.Publisher == nil {
		monitor.PublishFunc(func(s *Summary) {
			text, err := json.MarshalIndent(s, "", "\t")
			if err != nil {
				log.Panic(err)
			}

			log.Println(string(text))
		})
	}

	monitor.summary = &Summary{
		Name: monitor.Name,
		Data: make(map[string]*Metrics),
	}

	if monitor.PublishInterval == 0 {
		monitor.PublishInterval = DefaultMetricPublishInterval
	}

	monitor.records = make(chan metricSet)

	// start the background service
	go func() {
		t := time.NewTicker(monitor.PublishInterval)
		for {
			select {
			case r := <-monitor.records:
				monitor.summary.Record(r.name, r.data)

			case <-t.C:
				if len(monitor.summary.Data) == 0 {
					break
				}

				s := monitor.summary
				s.Time = time.Now()
				s.Step = monitor.PublishInterval
				s.Send++
				monitor.summary = &Summary{
					Name: s.Name,
					Data: make(map[string]*Metrics),
					Send: s.Send,
				}

				monitor.Publisher.Send(s)
			}
		}
	}()

	return
}

// RecordMetrics posts a set of metrics to the monitor background service.
func (monitor *Monitor) RecordMetrics(name string, data interface{}) {
	monitor.records <- metricSet{
		name: name,
		data: data,
	}
}

// Publish sets the publish handler.
func (monitor *Monitor) Publish(handler Publisher) {
	monitor.Publisher = handler
}

// PublishFunc defines an helper to support the Publisher interface.
type PublishFunc func(*Summary)

// Send invokes the function literal with the summary.
func (f PublishFunc) Send(s *Summary) {
	f(s)
}

// PublishFunc is an helper that sets a function literal as the publish handler.
func (monitor *Monitor) PublishFunc(handler func(*Summary)) {
	monitor.Publish(PublishFunc(handler))
}

// NewJSONMonitor creates and starts a monitor that POST the summary of metrics as a JSON object to the specified URL.
func NewJSONMonitor(name string, url string) (monitor *Monitor) {
	monitor = &Monitor{
		Name: name,
	}

	monitor.PublishFunc(func(s *Summary) {
		text, err := json.Marshal(s)
		if err != nil {
			log.Panic(err)
		}

		r, err := http.Post(url, "application/json", bytes.NewReader(text))
		if err != nil {
			log.Panic(err)
		}

		_, err = ioutil.ReadAll(r.Body)
		if err != nil {
			log.Panic(err)
		}

		r.Body.Close()
	})

	monitor.Start()
	return
}

var nullMonitor *Monitor

// NullMonitor defines a monitor that doesn't publish its results.
func NullMonitor() *Monitor {
	return nullMonitor
}

func init() {
	nullMonitor = &Monitor{
		Name:            "null",
		Publisher:       PublisherFunc(func(s *Summary) {}),
		PublishInterval: time.Second,
	}
	nullMonitor.Start()
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io"
	"os"
	"time"
)

const (
	usage = "Usage: %v [-B | -KB | -KiB | -MB | -MiB]\n"

	buflen = 1024 * 1024 // 1MB
)

const (
	exit_usage = iota + 1
	exit_io
)

var flags = map[string]int{
	"-B":   1,
	"-KB":  1000,
	"-KiB": 1024,
	"-MB":  1000 * 1000,
	"-MiB": 1024 * 1024,
}

func main() {
	unit, size := "KB", 1000
	if len(os.Args) == 2 {
		var ok bool
		size, ok = flags[os.Args[1]]
		if !ok {
			fmt.Fprintf(os.Stderr, usage, os.Args[0])
			os.Exit(exit_usage)
		}

		// Do this after validating that
		// the string is in the map (and
		// thus at least 1 character long)
		unit = os.Args[1][1:]
	} else if len(os.Args) > 2 {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		os.Exit(exit_usage)
	}

	r := newRateReader(os.Stdin, size, unit)
	_, err := io.Copy(os.Stdout, r)
	if err != nil {
		fmt.Fprintf(os.Stderr, "io error: %v\n", err)
		os.Exit(exit_io)
	}
}

type rateReader struct {
	r  io.Reader
	t0 time.Time
	nn int

	size int
	unit string
}

func (r *rateReader) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	r.nn += n
	t1 := time.Now()
	delta := t1.Sub(r.t0)
	if delta < 500*time.Millisecond {
		return n, err
	}

	r.t0 = t1
	bps := (float64(r.nn)) / delta.Seconds()
	r.nn = 0

	fmt.Fprintf(os.Stderr, "\r%8.4f %s/s", bps/float64(r.size), r.unit)
	return n, err
}

func newRateReader(r io.Reader, size int, unit string) *rateReader {
	return &rateReader{r: r,
		t0:   time.Now(),
		size: size,
		unit: unit,
	}
}
<commit_msg>Fixed bug where long-running Read call would stop rate from updating.<commit_after>// Copyright 2014 The Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io"
	"os"
	"sync/atomic"
	"time"
)

const (
	usage = "Usage: %v [-B | -KB | -KiB | -MB | -MiB] [-s | --silent]\n"

	buflen = 1024 * 1024 // 1MB
)

const (
	exit_usage = iota + 1
	exit_io
)

var flags = map[string]int{
	"-B":   1,
	"-KB":  1000,
	"-KiB": 1024,
	"-MB":  1000 * 1000,
	"-MiB": 1024 * 1024,
}

func main() {
	unit, size := "KB", 1000
	if len(os.Args) == 2 {
		var ok bool
		size, ok = flags[os.Args[1]]
		if !ok {
			fmt.Fprintf(os.Stderr, usage, os.Args[0])
			os.Exit(exit_usage)
		}

		// Do this after validating that
		// the string is in the map (and
		// thus at least 1 character long)
		unit = os.Args[1][1:]
	} else if len(os.Args) > 2 {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		os.Exit(exit_usage)
	}

	r := newRateReader(os.Stdin, size, unit)
	defer r.Close()
	_, err := io.Copy(os.Stdout, r)
	if err != nil {
		fmt.Fprintf(os.Stderr, "io error: %v\n", err)
		os.Exit(exit_io)
	}
}

type rateReader struct {
	r  io.Reader
	t0 time.Time
	nn int64

	size int
	unit string

	err error

	exit chan struct{}
}

func (r *rateReader) Read(p []byte) (int, error) {
	if r.err != nil {
		return 0, r.err
	}
	n, err := r.r.Read(p)
	atomic.AddInt64(&r.nn, int64(n))
	if err != nil {
		r.close()
		r.err = err
	}
	return n, err
}

func (r *rateReader) Close() error {
	r.close()
	return nil
}

func (r *rateReader) close() {
	// Include default case in case r has already
	// been closed (and thus we would have to wait
	// for print() to read from r.exit) or r has
	// already been closed twice (in which case
	// print() has already returned, in which case
	// we would block forever).
	select {
	case r.exit <- struct{}{}:
	default:
	}
}

func (r *rateReader) print() {
	for {
		select {
		case <-r.exit:
			return
		default:
			time.Sleep(500 * time.Millisecond)
			t1 := time.Now()
			nn := atomic.SwapInt64(&r.nn, 0)

			delta := t1.Sub(r.t0)
			r.t0 = t1

			bps := float64(nn) / delta.Seconds()
			fmt.Fprintf(os.Stderr, "\r%8.4f %s/s", bps/float64(r.size), r.unit)
		}
	}
}

func newRateReader(r io.Reader, size int, unit string) *rateReader {
	ret := &rateReader{r: r,
		t0:   time.Now(),
		size: size,
		unit: unit,
		exit: make(chan struct{}, 1), // Buffered so that Close() is non-blocking
	}
	go ret.print()
	return ret
}
<|endoftext|>


<commit_before>// Package monitor allows to print counters information into stdout, printing a
// row each second with the status of all Field objects and a title row each ten
// seconds with titles given to each Field objects.
//
// Fields column order is set by creation order.
//
// Fields can be added in realtime after a Start() signal is given. In this case
// a new row with titles will be printed
//
// Field titles must be longest than longest value that will be displayed as
// titles they are not adapted yet
package monitor

import (
	"fmt"
	"github.com/daviddengcn/go-colortext"
	"strconv"
	"time"
)

// Field struct gives control over information printed for this field on each
// row
type Field struct {
	title   string
	value   int
	values  []int
	accu    int
	average int
	reset   bool
	wait    chan int
}

// Add adds given value to Field value
func (f *Field) Add(number int) {
	f.wait <- 1
	f.value += number
	<-f.wait
}

// Set sets Field value to given number
func (f *Field) Set(number int) {
	f.wait <- 1
	f.value = number
	<-f.wait
}

var fields = []*Field{}
var previousFieldCount int
var stop = make(chan int)

// Start gives the order to start printing information on stdout
func Start() {
	go func() {
		tick := time.NewTicker(time.Second).C
		count := 0
		for {
			select {
			case <-tick:
				if count%10 == 0 || previousFieldCount != len(fields) {
					printTitles()
				}
				previousFieldCount = len(fields)

				printValues()
				count++
				if count%10 == 0 || previousFieldCount != len(fields) {
					printSubtotal()
					printAverage()
					fieldReset()
				}

			case <-stop:
				break
			}
		}
	}()
	go Listen()
}

// Stop gives the order to stop printing information on stdout
func Stop() {
	stop <- 1
}

func printTitles() {
	fmt.Println()
	ct.ChangeColor(ct.Black, false, ct.Cyan, true)
	first := true
	for _, field := range fields {
		if !first {
			fmt.Printf("  ")
		}
		fmt.Printf("%v", field.title)
		first = false
	}
	ct.ResetColor()
	fmt.Println()
}

func printValues() {
	first := true
	for _, field := range fields {
		field.wait <- 1
		field.values = append(field.values, field.value)
		if len(field.values) > 10 {
			field.values = field.values[1:]
		}

		s := strconv.Itoa(field.value)
		if !first {
			fmt.Printf("  ")
		}

		field.accu += field.value

		total := 0
		for _, v := range field.values {
			total += v
		}
		field.average = total / len(field.values)

		if field.average == 0 {
			ct.ChangeColor(ct.Yellow, false, ct.None, false)
		} else {
			if field.value >= field.average {
				ct.ChangeColor(ct.Green, false, ct.None, false)
			} else {
				ct.ChangeColor(ct.Red, false, ct.None, false)
			}
		}

		fmt.Printf("%[2]*[1]v", s, len(field.title))
		ct.ResetColor()
		if field.reset {
			field.value = 0
		}

		first = false
		<-field.wait
	}
	fmt.Println()
}

func printSubtotal() {
	first := true
	ct.ChangeColor(ct.Cyan, false, ct.None, false)
	for _, field := range fields {
		field.wait <- 1
		s := strconv.Itoa(field.accu)
		if !first {
			fmt.Printf(" ")
		}
		fmt.Printf("%[2]*[1]v+", s, len(field.title))
		first = false
		<-field.wait
	}
	ct.ResetColor()
	fmt.Println()
}

func printAverage() {
	first := true
	ct.ChangeColor(ct.Cyan, false, ct.None, false)
	for _, field := range fields {
		field.wait <- 1

		if !first {
			fmt.Printf(" ")
		}
		fmt.Printf("%[2]*[1]v~", field.average, len(field.title))

		first = false
		<-field.wait
	}
	ct.ResetColor()
	fmt.Println()
}

func fieldReset() {
	for _, field := range fields {
		if field.reset {
			field.accu = 0
			field.value = 0
		}
	}
}

// NewField creates a new monitor field that is shown as a column each second
//
// - title is the title printed on titles row each ten seconds
//
// - reset tells to reset field value after each time its printed
func NewField(title string, reset bool) *Field {
	field := new(Field)
	field.title = title
	field.reset = reset
	field.wait = make(chan int, 1)
	field.values = []int{}
	fields = append(fields, field)
	return field
}
<commit_msg>improved subtotals & averages printings<commit_after>// Package monitor allows to print counters information into stdout, printing a
// row each second with the status of all Field objects and a title row each ten
// seconds with titles given to each Field objects.
//
// Fields column order is set by creation order.
//
// Fields can be added in realtime after a Start() signal is given. In this case
// a new row with titles will be printed
//
// Field titles must be longest than longest value that will be displayed as
// titles they are not adapted yet
package monitor

import (
	"fmt"
	"github.com/daviddengcn/go-colortext"
	"strconv"
	"time"
)

// Field struct gives control over information printed for this field on each
// row
type Field struct {
	title   string
	value   int
	values  []int
	accu    int
	average int
	reset   bool
	wait    chan int
}

// Add adds given value to Field value
func (f *Field) Add(number int) {
	f.wait <- 1
	f.value += number
	<-f.wait
}

// Set sets Field value to given number
func (f *Field) Set(number int) {
	f.wait <- 1
	f.value = number
	<-f.wait
}

var fields = []*Field{}
var previousFieldCount int
var stop = make(chan int)

// Start gives the order to start printing information on stdout
func Start() {
	go func() {
		tick := time.NewTicker(time.Second).C
		count := 0
		for {
			select {
			case <-tick:
				if count%10 == 0 || previousFieldCount != len(fields) {
					printTitles()
				}
				previousFieldCount = len(fields)

				printValues()
				count++
				if count%10 == 0 || previousFieldCount != len(fields) {
					printSubtotal()
					printAverage()
					fieldReset()
				}

			case <-stop:
				break
			}
		}
	}()
	go Listen()
}

// Stop gives the order to stop printing information on stdout
func Stop() {
	stop <- 1
}

func printTitles() {
	fmt.Println()
	ct.ChangeColor(ct.Black, false, ct.Cyan, true)
	first := true
	for _, field := range fields {
		if !first {
			fmt.Printf("  ")
		}
		fmt.Printf("%v", field.title)
		first = false
	}
	ct.ResetColor()
	fmt.Println()
}

func printValues() {
	first := true
	for _, field := range fields {
		field.wait <- 1
		field.values = append(field.values, field.value)
		if len(field.values) > 10 {
			field.values = field.values[1:]
		}

		s := strconv.Itoa(field.value)
		if !first {
			fmt.Printf("  ")
		}

		field.accu += field.value

		total := 0
		for _, v := range field.values {
			total += v
		}
		field.average = total / len(field.values)

		if field.average == 0 {
			ct.ChangeColor(ct.Yellow, false, ct.None, false)
		} else {
			if field.value >= field.average {
				ct.ChangeColor(ct.Green, false, ct.None, false)
			} else {
				ct.ChangeColor(ct.Red, false, ct.None, false)
			}
		}

		fmt.Printf("%[2]*[1]v", s, len(field.title))
		ct.ResetColor()
		if field.reset {
			field.value = 0
		}

		first = false
		<-field.wait
	}
	fmt.Println()
}

func printSubtotal() {
	first := true
	ct.ChangeColor(ct.Cyan, false, ct.None, false)
	for _, field := range fields {
		field.wait <- 1
		s := strconv.Itoa(field.accu)
		if !first {
			fmt.Printf(" ")
		}

		if field.reset {
			fmt.Printf("%[2]*[1]v+", field.value, len(field.title))
		} else {
			fmt.Printf("%[2]*[1]v+", s, len(field.title))
		}

		first = false
		<-field.wait
	}
	ct.ResetColor()
	fmt.Println()
}

func printAverage() {
	first := true
	ct.ChangeColor(ct.Cyan, false, ct.None, false)
	for _, field := range fields {
		field.wait <- 1

		if !first {
			fmt.Printf(" ")
		}

		if field.reset {
			fmt.Printf("%[2]*[1]v~", " ", len(field.title))
		} else {
			fmt.Printf("%[2]*[1]v~", field.average, len(field.title))
		}

		first = false
		<-field.wait
	}
	ct.ResetColor()
	fmt.Println()
}

func fieldReset() {
	for _, field := range fields {
		if field.reset {
			field.accu = 0
			field.value = 0
		}
	}
}

// NewField creates a new monitor field that is shown as a column each second
//
// - title is the title printed on titles row each ten seconds
//
// - reset tells to reset field value after each time its printed
func NewField(title string, reset bool) *Field {
	field := new(Field)
	field.title = title
	field.reset = reset
	field.wait = make(chan int, 1)
	field.values = []int{}
	fields = append(fields, field)
	return field
}
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"encoding/json"
	"io"
	"io/ioutil"
	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
	"path/filepath"
	"sync"
	"os"
)

var SECRET_KEY string
var configPath string = filepath.Join(GetCurrentDir(), CONFIG_PATH + "config.json")

func init() {
	c := NewConfig()
	// Let's initialise all our json config stuff
	// For some reasons the file will be written bottom up so we start from the end moving up to the top

	// Connections
	if c.Get("connections.0.type").Interface() == nil {
		c.Get("connections.-1").Set(map[string]interface{}{"type": "webdav", "label": "Webdav"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "ftp", "label": "FTP"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "sftp", "label": "SFTP"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "git", "label": "GIT"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "s3", "label": "S3"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "dropbox", "label": "Dropbox"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "gdrive", "label": "Drive"})
	}

	// OAuth credentials
	c.Get("oauth").Default("")

	// Features
	c.Get("features.share.enable").Default(true)
	c.Get("features.search.enable").Default(true)

	// Log
	c.Get("log.telemetry").Default(true)
	c.Get("log.level").Default("INFO")
	c.Get("log.enable").Default(true)

	// Email
	c.Get("email.from").Default("username@gmail.com")
	c.Get("email.password").Default("password")
	c.Get("email.username").Default("username@gmail.com")
	c.Get("email.port").Default(587)
	c.Get("email.server").Default("smtp.gmail.com")

	// General
	c.Get("general.remember_me").Default(true)
	c.Get("general.auto_connect").Default(false)
	c.Get("general.display_hidden").Default(true)
	c.Get("general.fork_button").Default(true)
	c.Get("general.editor").Default("emacs")
	if c.Get("general.secret_key").String() == "" {
		c.Get("general.secret_key").Default(RandomString(16))
	}
	SECRET_KEY = c.Get("general.secret_key").String()
	if env := os.Getenv("APPLICATION_URL"); env != "" {
		c.Get("general.host").Set(env)
	} else {
		c.Get("general.host").Default("http://127.0.0.1:8334")
	}
	c.Get("general.port").Default(8334)
	c.Get("general.name").Default("Nuage")
}

func NewConfig() *Config {
	a := Config{}
	return a.load()
}
type Config struct {
	mu sync.Mutex
	path *string
	json string
	reader gjson.Result
}

func (this *Config) load() *Config {
	if f, err := os.OpenFile(configPath, os.O_RDONLY, os.ModePerm); err == nil {
		j, _ := ioutil.ReadAll(f)
		this.json = string(j)
		f.Close()
	} else {
		this.json = `{}`
	}
	if gjson.Valid(this.json) == true {
		this.reader = gjson.Parse(this.json)
	}
	return this
}

func (this *Config) Get(path string) *Config {
	this.path = &path
	return this
}

func (this *Config) Default(value interface{}) *Config {
	if this.path == nil {
		return this
	}

	if val := this.reader.Get(*this.path).Value(); val == nil {
		this.mu.Lock()
		this.json, _ = sjson.Set(this.json, *this.path, value)
		this.reader = gjson.Parse(this.json)
		this.save()
		this.mu.Unlock()
	}
	return this
}

func (this *Config) Set(value interface{}) *Config {
	if this.path == nil {
		return this
	}

	this.mu.Lock()
	this.json, _ = sjson.Set(this.json, *this.path, value)
	this.reader = gjson.Parse(this.json)
	this.save()
	this.mu.Unlock()
	return this
}

func (this Config) String() string {
	return this.reader.Get(*this.path).String()
}

func (this Config) Int() int {
	val := this.reader.Get(*this.path).Value()
	switch val.(type) {
	  case float64: return int(val.(float64))
	  case int64: return int(val.(int64))
	  case int: return val.(int)
	}
	return 0
}

func (this Config) Bool() bool {
	val := this.reader.Get(*this.path).Value()
	switch val.(type) {
	  case bool: return val.(bool)
	}
	return false
}

func (this Config) Interface() interface{} {
	return this.reader.Get(*this.path).Value()
}

func (this Config) save() {
	if this.path == nil {
		Log.Error("Config error")
		return
	}
	if gjson.Valid(this.json) == false {
		Log.Error("Config error")
		return
	}
	if f, err := os.OpenFile(configPath, os.O_WRONLY|os.O_CREATE, os.ModePerm); err == nil {
		buf := bytes.NewBuffer(PrettyPrint([]byte(this.json)))
		io.Copy(f, buf)
		f.Close()
	}
}

func (this Config) Scan(p interface{}) error {
	content := this.reader.Get(*this.path).String()

	return json.Unmarshal([]byte(content), &p)
}

func (this Config) Export() (string, error) {
	publicConf := struct {
		Editor        string            `json:"editor"`
		ForkButton    bool              `json:"fork_button"`
		DisplayHidden bool              `json:"display_hidden"`
		AutoConnect   bool              `json:"auto_connect"`
		Name          string            `json:"name"`
		RememberMe    bool              `json:"remember_me"`
		Connections   interface{}       `json:"connections"`
		EnableSearch  bool              `json:"enable_search"`
		EnableShare   bool              `json:"enable_share"`
		MimeTypes     map[string]string `json:"mime"`
	}{
		Editor:        this.Get("general.editor").String(),
		ForkButton:    this.Get("general.fork_button").Bool(),
		DisplayHidden: this.Get("general.display_hidden").Bool(),
		AutoConnect:   this.Get("general.auto_connect").Bool(),
		Name:          this.Get("general.name").String(),
		RememberMe:    this.Get("general.remember_me").Bool(),
		Connections:   this.Get("connections").Interface(),
		EnableSearch:  this.Get("features.search.enable").Bool(),
		EnableShare:   this.Get("features.share.enable").Bool(),
		MimeTypes:     AllMimeTypes(),
	}
	j, err := json.Marshal(publicConf)
	if err != nil {
		return "", err
	}
	return string(j), nil
}
<commit_msg>improvement (config): add debug facilities<commit_after>package common

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"encoding/base32"
	"fmt"
	"io"
	"io/ioutil"
	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
	"path/filepath"
	"sync"
	"os"
)

var SECRET_KEY string
var configPath string = filepath.Join(GetCurrentDir(), CONFIG_PATH + "config.json")

func init() {
	c := NewConfig()
	// Let's initialise all our json config stuff
	// For some reasons the file will be written bottom up so we start from the end moving up to the top

	// Connections
	if c.Get("connections.0.type").Interface() == nil {
		c.Get("connections.-1").Set(map[string]interface{}{"type": "webdav", "label": "Webdav"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "ftp", "label": "FTP"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "sftp", "label": "SFTP"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "git", "label": "GIT"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "s3", "label": "S3"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "dropbox", "label": "Dropbox"})
		c.Get("connections.-1").Set(map[string]interface{}{"type": "gdrive", "label": "Drive"})
	}

	// OAuth credentials
	c.Get("oauth").Default("")

	// Features
	c.Get("features.share.enable").Default(true)
	c.Get("features.search.enable").Default(true)

	// Log
	c.Get("log.telemetry").Default(true)
	c.Get("log.level").Default("INFO")
	c.Get("log.enable").Default(true)

	// Email
	c.Get("email.from").Default("username@gmail.com")
	c.Get("email.password").Default("password")
	c.Get("email.username").Default("username@gmail.com")
	c.Get("email.port").Default(587)
	c.Get("email.server").Default("smtp.gmail.com")

	// General
	c.Get("general.remember_me").Default(true)
	c.Get("general.auto_connect").Default(false)
	c.Get("general.display_hidden").Default(true)
	c.Get("general.fork_button").Default(true)
	c.Get("general.editor").Default("emacs")
	if c.Get("general.secret_key").String() == "" {
		c.Get("general.secret_key").Set(RandomString(16))
	}
	SECRET_KEY = c.Get("general.secret_key").String()
	if env := os.Getenv("APPLICATION_URL"); env != "" {
		c.Get("general.host").Set(env)
	} else {
		c.Get("general.host").Default("http://127.0.0.1:8334")
	}
	c.Get("general.port").Default(8334)
	c.Get("general.name").Default("Nuage")
}

func NewConfig() *Config {
	a := Config{}
	return a.load()
}
type Config struct {
	mu sync.Mutex
	path *string
	json string
	reader gjson.Result
}

func (this *Config) load() *Config {
	if f, err := os.OpenFile(configPath, os.O_RDONLY, os.ModePerm); err == nil {
		j, _ := ioutil.ReadAll(f)
		this.json = string(j)
		f.Close()
	} else {
		this.json = `{}`
	}
	if gjson.Valid(this.json) == true {
		this.reader = gjson.Parse(this.json)
	}
	return this
}

func (this *Config) Get(path string) *Config {
	this.path = &path
	return this
}

func (this *Config) Default(value interface{}) *Config {
	if this.path == nil {
		return this
	}

	if val := this.reader.Get(*this.path).Value(); val == nil {
		this.mu.Lock()
		this.json, _ = sjson.Set(this.json, *this.path, value)
		this.reader = gjson.Parse(this.json)
		this.save()
		this.mu.Unlock()
	}
	return this
}

func (this *Config) Set(value interface{}) *Config {
	if this.path == nil {
		return this
	}

	this.mu.Lock()
	this.json, _ = sjson.Set(this.json, *this.path, value)
	this.reader = gjson.Parse(this.json)
	this.save()
	this.mu.Unlock()
	return this
}

func (this Config) String() string {
	return this.reader.Get(*this.path).String()
}

func (this Config) Int() int {
	val := this.reader.Get(*this.path).Value()
	switch val.(type) {
	  case float64: return int(val.(float64))
	  case int64: return int(val.(int64))
	  case int: return val.(int)
	}
	return 0
}

func (this Config) Bool() bool {
	val := this.reader.Get(*this.path).Value()
	switch val.(type) {
	  case bool: return val.(bool)
	}
	return false
}

func (this Config) Interface() interface{} {
	return this.reader.Get(*this.path).Value()
}

func (this Config) save() {
	if this.path == nil {
		Log.Error("Config error")
		return
	}
	if gjson.Valid(this.json) == false {
		Log.Error("Config error")
		return
	}
	if f, err := os.OpenFile(configPath, os.O_WRONLY|os.O_CREATE, os.ModePerm); err == nil {
		buf := bytes.NewBuffer(PrettyPrint([]byte(this.json)))
		io.Copy(f, buf)
		f.Close()
	}
}

func (this Config) Scan(p interface{}) error {
	content := this.reader.Get(*this.path).String()

	return json.Unmarshal([]byte(content), &p)
}

func (this Config) Export() (string, error) {
	publicConf := struct {
		Editor        string            `json:"editor"`
		ForkButton    bool              `json:"fork_button"`
		DisplayHidden bool              `json:"display_hidden"`
		AutoConnect   bool              `json:"auto_connect"`
		Name          string            `json:"name"`
		RememberMe    bool              `json:"remember_me"`
		Connections   interface{}       `json:"connections"`
		EnableSearch  bool              `json:"enable_search"`
		EnableShare   bool              `json:"enable_share"`
		Version       string            `json:"version"`
		MimeTypes     map[string]string `json:"mime"`
	}{
		Editor:        this.Get("general.editor").String(),
		ForkButton:    this.Get("general.fork_button").Bool(),
		DisplayHidden: this.Get("general.display_hidden").Bool(),
		AutoConnect:   this.Get("general.auto_connect").Bool(),
		Name:          this.Get("general.name").String(),
		RememberMe:    this.Get("general.remember_me").Bool(),
		Connections:   this.Get("connections").Interface(),
		EnableSearch:  this.Get("features.search.enable").Bool(),
		EnableShare:   this.Get("features.share.enable").Bool(),
		Version:       func() string {
			f, err := os.OpenFile(GetCurrentDir() + "/nuage", os.O_RDONLY, os.ModePerm)
			if err != nil {
				return APP_VERSION
			}
			defer f.Close()
			h := md5.New()
			if _, err := io.Copy(h, f); err != nil {
				return APP_VERSION
			}
			return fmt.Sprintf("%s rev:%s", APP_VERSION, base32.HexEncoding.EncodeToString(h.Sum(nil))[:6])
		}(),
		MimeTypes:     AllMimeTypes(),
	}
	j, err := json.Marshal(publicConf)
	if err != nil {
		return "", err
	}
	return string(j), nil
}
<|endoftext|>


<commit_before>// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package core

import (
	"net/http"
	"time"

	"github.com/miniflux/miniflux2/server/template"
)

// Response handles HTTP responses.
type Response struct {
	writer   http.ResponseWriter
	request  *http.Request
	template *template.Engine
}

// SetCookie send a cookie to the client.
func (r *Response) SetCookie(cookie *http.Cookie) {
	http.SetCookie(r.writer, cookie)
}

// JSON returns a JSONResponse.
func (r *Response) JSON() *JSONResponse {
	r.commonHeaders()
	return &JSONResponse{writer: r.writer, request: r.request}
}

// HTML returns a HTMLResponse.
func (r *Response) HTML() *HTMLResponse {
	r.commonHeaders()
	return &HTMLResponse{writer: r.writer, request: r.request, template: r.template}
}

// XML returns a XMLResponse.
func (r *Response) XML() *XMLResponse {
	r.commonHeaders()
	return &XMLResponse{writer: r.writer, request: r.request}
}

// Redirect redirects the user to another location.
func (r *Response) Redirect(path string) {
	http.Redirect(r.writer, r.request, path, http.StatusFound)
}

// NotModified sends a response with a 304 status code.
func (r *Response) NotModified() {
	r.writer.WriteHeader(http.StatusNotModified)
}

// Cache returns a response with caching headers.
func (r *Response) Cache(mimeType, etag string, content []byte, duration time.Duration) {
	r.writer.Header().Set("Content-Type", mimeType)
	r.writer.Header().Set("Etag", etag)
	r.writer.Header().Set("Cache-Control", "public")
	r.writer.Header().Set("Expires", time.Now().Add(duration).Format(time.RFC1123))

	if etag == r.request.Header.Get("If-None-Match") {
		r.writer.WriteHeader(http.StatusNotModified)
	} else {
		r.writer.Write(content)
	}
}

func (r *Response) commonHeaders() {
	r.writer.Header().Set("X-XSS-Protection", "1; mode=block")
	r.writer.Header().Set("X-Content-Type-Options", "nosniff")
	r.writer.Header().Set("X-Frame-Options", "DENY")
}

// NewResponse returns a new Response.
func NewResponse(w http.ResponseWriter, r *http.Request, template *template.Engine) *Response {
	return &Response{writer: w, request: r, template: template}
}
<commit_msg>Add Content-Security-Policy header<commit_after>// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package core

import (
	"net/http"
	"time"

	"github.com/miniflux/miniflux2/server/template"
)

// Response handles HTTP responses.
type Response struct {
	writer   http.ResponseWriter
	request  *http.Request
	template *template.Engine
}

// SetCookie send a cookie to the client.
func (r *Response) SetCookie(cookie *http.Cookie) {
	http.SetCookie(r.writer, cookie)
}

// JSON returns a JSONResponse.
func (r *Response) JSON() *JSONResponse {
	r.commonHeaders()
	return &JSONResponse{writer: r.writer, request: r.request}
}

// HTML returns a HTMLResponse.
func (r *Response) HTML() *HTMLResponse {
	r.commonHeaders()
	return &HTMLResponse{writer: r.writer, request: r.request, template: r.template}
}

// XML returns a XMLResponse.
func (r *Response) XML() *XMLResponse {
	r.commonHeaders()
	return &XMLResponse{writer: r.writer, request: r.request}
}

// Redirect redirects the user to another location.
func (r *Response) Redirect(path string) {
	http.Redirect(r.writer, r.request, path, http.StatusFound)
}

// NotModified sends a response with a 304 status code.
func (r *Response) NotModified() {
	r.writer.WriteHeader(http.StatusNotModified)
}

// Cache returns a response with caching headers.
func (r *Response) Cache(mimeType, etag string, content []byte, duration time.Duration) {
	r.writer.Header().Set("Content-Type", mimeType)
	r.writer.Header().Set("Etag", etag)
	r.writer.Header().Set("Cache-Control", "public")
	r.writer.Header().Set("Expires", time.Now().Add(duration).Format(time.RFC1123))

	if etag == r.request.Header.Get("If-None-Match") {
		r.writer.WriteHeader(http.StatusNotModified)
	} else {
		r.writer.Write(content)
	}
}

func (r *Response) commonHeaders() {
	r.writer.Header().Set("X-XSS-Protection", "1; mode=block")
	r.writer.Header().Set("X-Content-Type-Options", "nosniff")
	r.writer.Header().Set("X-Frame-Options", "DENY")
	r.writer.Header().Set("Content-Security-Policy", "default-src 'self'; img-src *; media-src *; frame-src *")
}

// NewResponse returns a new Response.
func NewResponse(w http.ResponseWriter, r *http.Request, template *template.Engine) *Response {
	return &Response{writer: w, request: r, template: template}
}
<|endoftext|>


<commit_before>package sia

// wallet.go contains things like signatures and scans the blockchain for
// available funds that can be spent.

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"errors"
)

type Wallet struct {
	SecretKey       *ecdsa.PrivateKey
	SpendConditions SpendConditions
	CoinAddress     CoinAddress         // 1 of 1 spend using the secret key, no timelock.
	OwnedOutputs    map[OutputID]Output // All outputs to CoinAddress
}

func CreateWallet() (w *Wallet, err error) {
	w = new(Wallet)

	curve := elliptic.P256()
	w.SecretKey, err = ecdsa.GenerateKey(curve, rand.Reader)

	w.SpendConditions.NumSignatures = 1
	w.SpendConditions.PublicKeys = make([]PublicKey, 1)
	w.SpendConditions.PublicKeys[0] = PublicKey(w.SecretKey.PublicKey)
	// w.CoinAddress = sc.GetAddress()

	return
}

// Scans all unspent transactions and adds the ones that are spendable by this
// wallet.
func (w *Wallet) Scan(state *State) {
	w.OwnedOutputs = make(map[OutputID]Output)
	for id, output := range state.ConsensusState.UnspentOutputs {
		if output.SpendHash == w.CoinAddress {
			w.OwnedOutputs[id] = output
		}
	}
}

// Takes a new address, and an amount to send, and adds outputs until the
// amount is reached. Then sends leftovers back to self.
//
// Should probably call scan before doing this...?
func (w *Wallet) SpendCoins(amount Currency, address CoinAddress, state *State) (t Transaction, err error) {
	if amount == Currency(0) {
		err = errors.New("Cannot send 0 coins")
		return
	}

	// Scan blockchain for outputs.
	w.Scan(state)

	t.Version = 1

	total := Currency(0)
	for id, output := range w.OwnedOutputs {
		if total > amount {
			break
		}

		newInput := Input{
			OutputID:        id,
			SpendConditions: w.SpendConditions,
		}
		t.Inputs = append(t.Inputs, newInput)

		total += output.Value
	}

	if total < amount {
		err = errors.New("insufficient funds")
		return
	}

	t.Outputs = make([]Output, 2)
	t.Outputs[0] = Output{
		Value:     amount,
		SpendHash: address,
	}
	t.Outputs[1] = Output{
		Value:     total - amount,
		SpendHash: w.CoinAddress,
	}

	// Still need to sign the transaction.

	return
}
<commit_msg>more concise output making<commit_after>package sia

// wallet.go contains things like signatures and scans the blockchain for
// available funds that can be spent.

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"errors"
)

type Wallet struct {
	SecretKey       *ecdsa.PrivateKey
	SpendConditions SpendConditions
	CoinAddress     CoinAddress         // 1 of 1 spend using the secret key, no timelock.
	OwnedOutputs    map[OutputID]Output // All outputs to CoinAddress
}

func CreateWallet() (w *Wallet, err error) {
	w = new(Wallet)

	curve := elliptic.P256()
	w.SecretKey, err = ecdsa.GenerateKey(curve, rand.Reader)

	w.SpendConditions.NumSignatures = 1
	w.SpendConditions.PublicKeys = make([]PublicKey, 1)
	w.SpendConditions.PublicKeys[0] = PublicKey(w.SecretKey.PublicKey)
	// w.CoinAddress = sc.GetAddress()

	return
}

// Scans all unspent transactions and adds the ones that are spendable by this
// wallet.
func (w *Wallet) Scan(state *State) {
	w.OwnedOutputs = make(map[OutputID]Output)
	for id, output := range state.ConsensusState.UnspentOutputs {
		if output.SpendHash == w.CoinAddress {
			w.OwnedOutputs[id] = output
		}
	}
}

// Takes a new address, and an amount to send, and adds outputs until the
// amount is reached. Then sends leftovers back to self.
//
// Should probably call scan before doing this...?
func (w *Wallet) SpendCoins(amount Currency, address CoinAddress, state *State) (t Transaction, err error) {
	if amount == Currency(0) {
		err = errors.New("Cannot send 0 coins")
		return
	}

	// Scan blockchain for outputs.
	w.Scan(state)

	t.Version = 1

	total := Currency(0)
	for id, output := range w.OwnedOutputs {
		if total > amount {
			break
		}

		newInput := Input{
			OutputID:        id,
			SpendConditions: w.SpendConditions,
		}
		t.Inputs = append(t.Inputs, newInput)

		total += output.Value
	}

	if total < amount {
		err = errors.New("insufficient funds")
		return
	}

	t.Outputs = []Output{
		{Value: amount, SpendHash: address},
		{Value: total - amount, SpendHash: w.CoinAddress},
	}

	// Still need to sign the transaction.

	return
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package client

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"testing"
	"time"

	. "github.com/containerd/containerd"
	"github.com/containerd/containerd/containers"
	"github.com/containerd/containerd/oci"
	"github.com/containerd/containerd/pkg/testutil"
	srvconfig "github.com/containerd/containerd/services/server/config"
	exec "golang.org/x/sys/execabs"
)

// the following nolint is for shutting up gometalinter on non-linux.
// nolint: unused
func newDaemonWithConfig(t *testing.T, configTOML string) (*Client, *daemon, func()) {
	if testing.Short() {
		t.Skip()
	}
	testutil.RequiresRoot(t)
	var (
		ctrd              = daemon{}
		configTOMLDecoded srvconfig.Config
		buf               = bytes.NewBuffer(nil)
	)

	tempDir, err := os.MkdirTemp("", "containerd-test-new-daemon-with-config")
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		if err != nil {
			os.RemoveAll(tempDir)
		}
	}()

	configTOMLFile := filepath.Join(tempDir, "config.toml")
	if err = os.WriteFile(configTOMLFile, []byte(configTOML), 0600); err != nil {
		t.Fatal(err)
	}

	if err = srvconfig.LoadConfig(configTOMLFile, &configTOMLDecoded); err != nil {
		t.Fatal(err)
	}

	address := configTOMLDecoded.GRPC.Address
	if address == "" {
		if runtime.GOOS == "windows" {
			address = fmt.Sprintf(`\\.\pipe\containerd-containerd-test-%s`, filepath.Base(tempDir))
		} else {
			address = filepath.Join(tempDir, "containerd.sock")
		}
	}
	args := []string{"-c", configTOMLFile}
	if configTOMLDecoded.Root == "" {
		args = append(args, "--root", filepath.Join(tempDir, "root"))
	}
	if configTOMLDecoded.State == "" {
		args = append(args, "--state", filepath.Join(tempDir, "state"))
	}
	if err = ctrd.start("containerd", address, args, buf, buf); err != nil {
		t.Fatalf("%v: %s", err, buf.String())
	}

	waitCtx, waitCancel := context.WithTimeout(context.TODO(), 2*time.Second)
	client, err := ctrd.waitForStart(waitCtx)
	waitCancel()
	if err != nil {
		ctrd.Kill()
		ctrd.Wait()
		t.Fatalf("%v: %s", err, buf.String())
	}

	cleanup := func() {
		if err := client.Close(); err != nil {
			t.Fatalf("failed to close client: %v", err)
		}
		if err := ctrd.Stop(); err != nil {
			if err := ctrd.Kill(); err != nil {
				t.Fatalf("failed to signal containerd: %v", err)
			}
		}
		if err := ctrd.Wait(); err != nil {
			if _, ok := err.(*exec.ExitError); !ok {
				t.Fatalf("failed to wait for: %v", err)
			}
		}
		if err := os.RemoveAll(tempDir); err != nil {
			t.Fatalf("failed to remove %s: %v", tempDir, err)
		}
		// cleaning config-specific resources is up to the caller
	}
	return client, &ctrd, cleanup
}

// TestRestartMonitor tests restarting containers
// with the restart monitor service plugin
func TestRestartMonitor(t *testing.T) {
	const (
		interval = 10 * time.Second
		epsilon  = 1 * time.Second
		count    = 20
	)
	configTOML := fmt.Sprintf(`
version = 2
[plugins]
  [plugins."io.containerd.internal.v1.restart"]
	  interval = "%s"
`, interval.String())
	client, _, cleanup := newDaemonWithConfig(t, configTOML)
	defer cleanup()

	var (
		ctx, cancel = testContext(t)
		id          = t.Name()
	)
	defer cancel()

	image, err := client.Pull(ctx, testImage, WithPullUnpack)
	if err != nil {
		t.Fatal(err)
	}

	container, err := client.NewContainer(ctx, id,
		WithNewSnapshot(id, image),
		WithNewSpec(
			oci.WithImageConfig(image),
			longCommand,
		),
		withRestartStatus(Running),
	)
	if err != nil {
		t.Fatal(err)
	}
	defer container.Delete(ctx, WithSnapshotCleanup)

	task, err := container.NewTask(ctx, empty())
	if err != nil {
		t.Fatal(err)
	}
	defer task.Delete(ctx, WithProcessKill)

	if err := task.Start(ctx); err != nil {
		t.Fatal(err)
	}

	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
		t.Fatal(err)
	}

	begin := time.Now()
	lastCheck := begin

	expected := begin.Add(interval).Add(epsilon)

	// Deadline determines when check for restart should be aborted.
	deadline := begin.Add(interval).Add(epsilon * count)
	for {
		status, err := task.Status(ctx)
		now := time.Now()
		if err != nil {
			// ErrNotFound is expected here, because the restart monitor
			// temporarily removes the task before restarting.
			t.Logf("%v: err=%v", now, err)
		} else {
			t.Logf("%v: status=%q", now, status.Status)

			if status.Status == Running {
				break
			}
		}

		// lastCheck represents the last time the status was seen as not running
		lastCheck = now
		if lastCheck.After(deadline) {
			t.Logf("%v: the task was not restarted", lastCheck)
			return
		}
		time.Sleep(epsilon)
	}

	// Use the last timestamp for when the process was seen as not running for the check
	if lastCheck.After(expected) {
		t.Fatalf("%v: the task was restarted, but it must be before %v", lastCheck, expected)
	}
	t.Logf("%v: the task was restarted since %v", time.Now(), lastCheck)
}

// withRestartStatus is a copy of "github.com/containerd/containerd/runtime/restart".WithStatus.
// This copy is needed because `go test` refuses circular imports.
func withRestartStatus(status ProcessStatus) func(context.Context, *Client, *containers.Container) error {
	return func(_ context.Context, _ *Client, c *containers.Container) error {
		if c.Labels == nil {
			c.Labels = make(map[string]string)
		}
		c.Labels["containerd.io/restart.status"] = string(status)
		return nil
	}
}
<commit_msg>Add error logging on cleanup<commit_after>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package client

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"testing"
	"time"

	. "github.com/containerd/containerd"
	"github.com/containerd/containerd/containers"
	"github.com/containerd/containerd/oci"
	"github.com/containerd/containerd/pkg/testutil"
	srvconfig "github.com/containerd/containerd/services/server/config"
	exec "golang.org/x/sys/execabs"
)

// the following nolint is for shutting up gometalinter on non-linux.
// nolint: unused
func newDaemonWithConfig(t *testing.T, configTOML string) (*Client, *daemon, func()) {
	if testing.Short() {
		t.Skip()
	}
	testutil.RequiresRoot(t)
	var (
		ctrd              = daemon{}
		configTOMLDecoded srvconfig.Config
		buf               = bytes.NewBuffer(nil)
	)

	tempDir, err := os.MkdirTemp("", "containerd-test-new-daemon-with-config")
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		if err != nil {
			os.RemoveAll(tempDir)
		}
	}()

	configTOMLFile := filepath.Join(tempDir, "config.toml")
	if err = os.WriteFile(configTOMLFile, []byte(configTOML), 0600); err != nil {
		t.Fatal(err)
	}

	if err = srvconfig.LoadConfig(configTOMLFile, &configTOMLDecoded); err != nil {
		t.Fatal(err)
	}

	address := configTOMLDecoded.GRPC.Address
	if address == "" {
		if runtime.GOOS == "windows" {
			address = fmt.Sprintf(`\\.\pipe\containerd-containerd-test-%s`, filepath.Base(tempDir))
		} else {
			address = filepath.Join(tempDir, "containerd.sock")
		}
	}
	args := []string{"-c", configTOMLFile}
	if configTOMLDecoded.Root == "" {
		args = append(args, "--root", filepath.Join(tempDir, "root"))
	}
	if configTOMLDecoded.State == "" {
		args = append(args, "--state", filepath.Join(tempDir, "state"))
	}
	if err = ctrd.start("containerd", address, args, buf, buf); err != nil {
		t.Fatalf("%v: %s", err, buf.String())
	}

	waitCtx, waitCancel := context.WithTimeout(context.TODO(), 2*time.Second)
	client, err := ctrd.waitForStart(waitCtx)
	waitCancel()
	if err != nil {
		ctrd.Kill()
		ctrd.Wait()
		t.Fatalf("%v: %s", err, buf.String())
	}

	cleanup := func() {
		if err := client.Close(); err != nil {
			t.Fatalf("failed to close client: %v", err)
		}
		if err := ctrd.Stop(); err != nil {
			if err := ctrd.Kill(); err != nil {
				t.Fatalf("failed to signal containerd: %v", err)
			}
		}
		if err := ctrd.Wait(); err != nil {
			if _, ok := err.(*exec.ExitError); !ok {
				t.Fatalf("failed to wait for: %v", err)
			}
		}
		if err := os.RemoveAll(tempDir); err != nil {
			t.Fatalf("failed to remove %s: %v", tempDir, err)
		}
		// cleaning config-specific resources is up to the caller
	}
	return client, &ctrd, cleanup
}

// TestRestartMonitor tests restarting containers
// with the restart monitor service plugin
func TestRestartMonitor(t *testing.T) {
	const (
		interval = 10 * time.Second
		epsilon  = 1 * time.Second
		count    = 20
	)
	configTOML := fmt.Sprintf(`
version = 2
[plugins]
  [plugins."io.containerd.internal.v1.restart"]
	  interval = "%s"
`, interval.String())
	client, _, cleanup := newDaemonWithConfig(t, configTOML)
	defer cleanup()

	var (
		ctx, cancel = testContext(t)
		id          = t.Name()
	)
	defer cancel()

	image, err := client.Pull(ctx, testImage, WithPullUnpack)
	if err != nil {
		t.Fatal(err)
	}

	container, err := client.NewContainer(ctx, id,
		WithNewSnapshot(id, image),
		WithNewSpec(
			oci.WithImageConfig(image),
			longCommand,
		),
		withRestartStatus(Running),
	)
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		if err := container.Delete(ctx, WithSnapshotCleanup); err != nil {
			t.Logf("failed to delete container: %v", err)
		}
	}()

	task, err := container.NewTask(ctx, empty())
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		if _, err := task.Delete(ctx, WithProcessKill); err != nil {
			t.Logf("failed to delete task: %v", err)
		}
	}()

	if err := task.Start(ctx); err != nil {
		t.Fatal(err)
	}

	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
		t.Fatal(err)
	}

	begin := time.Now()
	lastCheck := begin

	expected := begin.Add(interval).Add(epsilon)

	// Deadline determines when check for restart should be aborted.
	deadline := begin.Add(interval).Add(epsilon * count)
	for {
		status, err := task.Status(ctx)
		now := time.Now()
		if err != nil {
			// ErrNotFound is expected here, because the restart monitor
			// temporarily removes the task before restarting.
			t.Logf("%v: err=%v", now, err)
		} else {
			t.Logf("%v: status=%q", now, status.Status)

			if status.Status == Running {
				break
			}
		}

		// lastCheck represents the last time the status was seen as not running
		lastCheck = now
		if lastCheck.After(deadline) {
			t.Logf("%v: the task was not restarted", lastCheck)
			return
		}
		time.Sleep(epsilon)
	}

	// Use the last timestamp for when the process was seen as not running for the check
	if lastCheck.After(expected) {
		t.Fatalf("%v: the task was restarted, but it must be before %v", lastCheck, expected)
	}
	t.Logf("%v: the task was restarted since %v", time.Now(), lastCheck)
}

// withRestartStatus is a copy of "github.com/containerd/containerd/runtime/restart".WithStatus.
// This copy is needed because `go test` refuses circular imports.
func withRestartStatus(status ProcessStatus) func(context.Context, *Client, *containers.Container) error {
	return func(_ context.Context, _ *Client, c *containers.Container) error {
		if c.Labels == nil {
			c.Labels = make(map[string]string)
		}
		c.Labels["containerd.io/restart.status"] = string(status)
		return nil
	}
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 thrift

type TSerializer struct {
	Transport TTransport
	Protocol  TProtocol
}

type TStruct interface {
	Write(p TProtocol) error
	Read(p TProtocol) error
}

func NewTSerializer() *TSerializer {
	var transport TTransport
	transport = NewTMemoryBufferLen(1024)

	protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport)

	return &TSerializer{
		transport,
		protocol}
}

func (t *TSerializer) WriteString(msg TStruct) (s string, err error) {
	s = ""
	err = nil

	if err = msg.Write(t.Protocol); err != nil {
		return
	}

	if err = t.Protocol.Flush(); err != nil {
		return
	}
	if err = t.Transport.Flush(); err != nil {
		return
	}

	var buf []byte
	var place int
	buf = make([]byte, 1024)
	if place, err = t.Transport.Read(buf); err != nil {
		return
	}

	s = string(buf[:place])
	return
}

func (t *TSerializer) Write(msg TStruct) (b []byte, err error) {
	err = nil

	if err = msg.Write(t.Protocol); err != nil {
		return
	}

	if err = t.Protocol.Flush(); err != nil {
		return
	}

	if err = t.Transport.Flush(); err != nil {
		return
	}

	var buf []byte
	var place int
	buf = make([]byte, 1024)
	if place, err = t.Transport.Read(buf); err != nil {
		return
	}

	b = buf[:place]
	return
}
<commit_msg>THRIFT-2279 TSerializer only returns the first 1024 bytes serialized<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 thrift

type TSerializer struct {
	Transport *TMemoryBuffer
	Protocol  TProtocol
}

type TStruct interface {
	Write(p TProtocol) error
	Read(p TProtocol) error
}

func NewTSerializer() *TSerializer {
	transport := NewTMemoryBufferLen(1024)
	protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport)

	return &TSerializer{
		transport,
		protocol}
}

func (t *TSerializer) WriteString(msg TStruct) (s string, err error) {
	t.Transport.Reset()

	if err = msg.Write(t.Protocol); err != nil {
		return
	}

	if err = t.Protocol.Flush(); err != nil {
		return
	}
	if err = t.Transport.Flush(); err != nil {
		return
	}

	return t.Transport.String(), nil
}

func (t *TSerializer) Write(msg TStruct) (b []byte, err error) {
	t.Transport.Reset()

	if err = msg.Write(t.Protocol); err != nil {
		return
	}

	if err = t.Protocol.Flush(); err != nil {
		return
	}

	if err = t.Transport.Flush(); err != nil {
		return
	}

	b = append(b, t.Transport.Bytes()...)
	return
}
<|endoftext|>


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

package gcp_terraforming

import (
	"context"
	"log"
	"net/http"
	"waze/terraformer/terraform_utils"

	"golang.org/x/oauth2/google"

	"cloud.google.com/go/monitoring/apiv3"
	"google.golang.org/api/iterator"
	"google.golang.org/api/sqladmin/v1beta4"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)

var cloudSQLAllowEmptyValues = []string{}

var cloudSQLAdditionalFields = map[string]string{}

type CloudSQLGenerator struct {
	GCPService
}

func (g *CloudSQLGenerator) loadDBInstances(svc *sqladmin.Service, project string) error {
	dbInstances, err := svc.Instances.List(project).Do()
	if err != nil {
		return err
	}
	for _, dbInstance := range dbInstances.Items {
		g.Resources = append(g.Resources, terraform_utils.NewResource(
			dbInstance.Name,
			dbInstance.Name,
			"google_sql_database_instance",
			"google",
			map[string]string{},
			cloudSQLAllowEmptyValues,
			cloudSQLAdditionalFields,
		))
		err := g.loadDBs(svc, dbInstance.Name, project)
		if err != nil {
			return err
		}
	}

	return nil
}

func (g *CloudSQLGenerator) loadDBs(svc *sqladmin.Service, instanceName, project string) error {
	DBs, err := svc.Databases.List(project, instanceName).Do()
	if err != nil {
		return err
	}
	for _, db := range DBs.Items {
		g.Resources = append(g.Resources, terraform_utils.NewResource(
			instanceName+":"+db.Name,
			instanceName+"-"+db.Name,
			"google_sql_database",
			"google",
			map[string]string{},
			cloudSQLAllowEmptyValues,
			cloudSQLAdditionalFields,
		))
	}
	return nil
}

func (g *CloudSQLGenerator) loadSSLCert(ctx context.Context, project string) error {
	client, err := monitoring.NewNotificationChannelClient(ctx)
	if err != nil {
		return err
	}

	req := &monitoringpb.ListNotificationChannelsRequest{
		Name: "projects/" + project,
	}

	notificationChannelIterator := client.ListNotificationChannels(ctx, req)
	for {
		notificationChannel, err := notificationChannelIterator.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Println("error with notification Channel:", err)
			continue
		}
		g.Resources = append(g.Resources, terraform_utils.NewResource(
			notificationChannel.Name,
			notificationChannel.Name,
			"google_monitoring_notification_channel",
			"google",
			map[string]string{
				"name": notificationChannel.Name,
			},
			monitoringAllowEmptyValues,
			monitoringAdditionalFields,
		))
	}
	return nil
}

func (g *CloudSQLGenerator) loadSQLUser(ctx context.Context, project string) error {
	client, err := monitoring.NewUptimeCheckClient(ctx)
	if err != nil {
		return err
	}

	req := &monitoringpb.ListUptimeCheckConfigsRequest{
		Parent: "projects/" + project,
	}

	uptimeCheckConfigsIterator := client.ListUptimeCheckConfigs(ctx, req)
	for {
		uptimeCheckConfigs, err := uptimeCheckConfigsIterator.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Println("error with uptimeCheckConfigs:", err)
			continue
		}
		g.Resources = append(g.Resources, terraform_utils.NewResource(
			uptimeCheckConfigs.Name,
			uptimeCheckConfigs.Name,
			"google_monitoring_uptime_check_config",
			"google",
			map[string]string{
				"name": uptimeCheckConfigs.Name,
			},
			monitoringAllowEmptyValues,
			monitoringAdditionalFields,
		))
	}
	return nil
}

// Generate TerraformResources from GCP API,
// from each alert  create 1 TerraformResource
// Need alert name as ID for terraform resource
func (g *CloudSQLGenerator) InitResources() error {
	project := g.GetArgs()["project"]
	ctx := context.Background()
	var client *http.Client
	var err error
	client, err = google.DefaultClient(ctx, sqladmin.SqlserviceAdminScope)
	svc, err := sqladmin.New(client)
	if err != nil {
		return err
	}
	if err := g.loadDBInstances(svc, project); err != nil {
		return err
	}

	g.PopulateIgnoreKeys()
	return nil
}
<commit_msg>gcp: cloudsql remove unused code<commit_after>// Copyright 2018 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gcp_terraforming

import (
	"context"
	"net/http"
	"waze/terraformer/terraform_utils"

	"golang.org/x/oauth2/google"

	"google.golang.org/api/sqladmin/v1beta4"
)

var cloudSQLAllowEmptyValues = []string{}

var cloudSQLAdditionalFields = map[string]string{}

type CloudSQLGenerator struct {
	GCPService
}

func (g *CloudSQLGenerator) loadDBInstances(svc *sqladmin.Service, project string) error {
	dbInstances, err := svc.Instances.List(project).Do()
	if err != nil {
		return err
	}
	for _, dbInstance := range dbInstances.Items {
		g.Resources = append(g.Resources, terraform_utils.NewResource(
			dbInstance.Name,
			dbInstance.Name,
			"google_sql_database_instance",
			"google",
			map[string]string{},
			cloudSQLAllowEmptyValues,
			cloudSQLAdditionalFields,
		))
		err := g.loadDBs(svc, dbInstance.Name, project)
		if err != nil {
			return err
		}
	}

	return nil
}

func (g *CloudSQLGenerator) loadDBs(svc *sqladmin.Service, instanceName, project string) error {
	DBs, err := svc.Databases.List(project, instanceName).Do()
	if err != nil {
		return err
	}
	for _, db := range DBs.Items {
		g.Resources = append(g.Resources, terraform_utils.NewResource(
			instanceName+":"+db.Name,
			instanceName+"-"+db.Name,
			"google_sql_database",
			"google",
			map[string]string{},
			cloudSQLAllowEmptyValues,
			cloudSQLAdditionalFields,
		))
	}
	return nil
}

// Generate TerraformResources from GCP API,
// from each databases create many TerraformResource(dbinstance + databases)
// Need dbinstance name as ID for terraform resource
func (g *CloudSQLGenerator) InitResources() error {
	project := g.GetArgs()["project"]
	ctx := context.Background()
	var client *http.Client
	var err error
	client, err = google.DefaultClient(ctx, sqladmin.SqlserviceAdminScope)
	svc, err := sqladmin.New(client)
	if err != nil {
		return err
	}
	if err := g.loadDBInstances(svc, project); err != nil {
		return err
	}

	g.PopulateIgnoreKeys()
	return nil
}
<|endoftext|>


<commit_before>package service_test

import (
	"context"
	"os"
	"testing"

	qt "github.com/frankban/quicktest"

	"github.com/gilcrest/go-api-basic/datastore/datastoretest"
	"github.com/gilcrest/go-api-basic/domain/secure"
	"github.com/gilcrest/go-api-basic/domain/secure/random"
	"github.com/gilcrest/go-api-basic/service"
)

func TestGenesisService_Seed(t *testing.T) {
	t.Skip()
	t.Run("standard", func(t *testing.T) {
		c := qt.New(t)

		ds, cleanup := datastoretest.NewDatastore(t)
		c.Cleanup(cleanup)

		const keyEnv string = "ENCRYPT_KEY"
		ekey, ok := os.LookupEnv(keyEnv)
		if !ok {
			c.Fatalf("%s not set\n", keyEnv)
		}
		ek, err := secure.ParseEncryptionKey(ekey)
		if err != nil {
			c.Fatal(err)
		}

		sr := service.GenesisService{
			Datastorer:            ds,
			RandomStringGenerator: random.CryptoGenerator{},
			EncryptionKey:         ek,
		}

		_, err = sr.Seed(context.Background())
		c.Assert(err, qt.IsNil)
	})
}
<commit_msg>test was not helpful<commit_after><|endoftext|>


<commit_before><commit_msg>Add peer start dial seeds function<commit_after><|endoftext|>


<commit_before>/**
 * Copyright 2016 IBM Corp.
 *
 * 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 sl

import (
	"reflect"
	"strings"
	"time"

	"github.com/softlayer/softlayer-go/datatypes"
)

// Convenience functions for returning pointers to values

// Int returns a pointer to the int value provided
func Int(v int) *int {
	return &v
}

// Uint returns a pointer to the uint value provided
func Uint(v uint) *uint {
	return &v
}

// String returns a pointer to the string value provided
func String(v string) *string {
	return &v
}

// Bool returns a pointer to the bool value provided
func Bool(v bool) *bool {
	return &v
}

// Time converts the time.Time value provided to a datatypes.Time value,
// and returns a pointer to it
func Time(v time.Time) *datatypes.Time {
	r := datatypes.Time{Time: v}
	return &r
}

// Float converts the float value provided to a datatypes.Float64 value,
// and returns a pointer to it
func Float(v float64) *datatypes.Float64 {
	r := datatypes.Float64(v)
	return &r
}

// Convenience functions to simplify dereference of datatype properties

// Get returns the value of p, either p itself, or, if p is a pointer, the
// value that p points to. d is an optional default value to be returned
// in the event that p is nil. If d is not specified, and p is nil, a
// type-appropriate zero-value is returned instead.
func Get(p interface{}, d ...interface{}) interface{} {
	var (
		val interface{}
		ok  bool
	)

	if val, ok = GetOk(p); ok {
		return val
	}

	if len(d) > 0 {
		return d[0]
	}

	return val
}

// GetOk returns the value of p, either p itself, or, if p is a pointer, the
// value that p points to. If d is not specified, and p is nil, a type-
// appropriate zero-value is returned instead. If p is a value or non-nil
// pointer, the second return value will be true.  Otherwise, it will be false
func GetOk(p interface{}) (interface{}, bool) {
	t := reflect.TypeOf(p)

	// if p is a non-pointer, just return it
	if t.Kind() != reflect.Ptr {
		return p, true
	}

	// p is a pointer.  If non-nil, return the value pointed to
	v := reflect.Indirect(reflect.ValueOf(p))
	if v.IsValid() {
		return v.Interface(), true
	}

	// p is a nil pointer.  Return the zero value for the pointed-to type
	return reflect.Zero(t.Elem()).Interface(), false
}

// Grab returns the value specified by the path given,
// starting from the struct s.
// If at any point in the path the lookup falls short
// (i.e. a field is not found), or if the last field in the path is nil
// itself, a type-appropriate zero-value is returned.
// This behavior can be overidden by providing a default value.
//
// This is useful for getting values our of deeply nested structures
// Example: val := sl.Grab(virtualGuest, "Datacenter.Name")
func Grab(s interface{}, path string, d ...interface{}) interface{} {
	var (
		val interface{}
		ok  bool
	)

	if val, ok = GrabOk(s, path); ok {
		return val
	}

	if len(d) > 0 {
		return d[0]
	}

	return val
}

// GrabOk returns the value specified by the path given,
// starting from the struct s.
// If at any point in the path the lookup falls short
// (i.e. a field is not found), or if the last field in the path is nil
// itself, a type-appropriate zero-value is returned.
// It returns a second value, a boolean, which will be false if it failed
// to lookup the value, including if the last field in the path was nil.
//
// This is useful for getting values our of deeply nested structures
// Example: val, ok := sl.GrabOk(virtualGuest, "Datacenter.Name")
func GrabOk(s interface{}, path string) (interface{}, bool) {
	t := reflect.TypeOf(s)
	if t.Kind() != reflect.Struct {
		return nil, false
	}

	dotIndex := strings.Index(path, ".")
	if dotIndex == -1 {
		dotIndex = len(path)
	}

	fieldName := path[0:dotIndex]
	val := reflect.ValueOf(s)
	fieldVal := val.FieldByName(fieldName)
	if fieldVal.Kind() == reflect.Ptr {
		if fieldVal.IsNil() {
			return reflect.Zero(fieldVal.Type().Elem()).Interface(), false
		}

		fieldVal = reflect.Indirect(fieldVal)
	}

	result, ok := GetOk(fieldVal.Interface())
	if !ok {
		return result, ok
	}

	if dotIndex == len(path) {
		return result, ok
	}

	return GrabOk(result, path[dotIndex+1:len(path)])
}
<commit_msg>Add proper package comment line to sl package<commit_after>/**
 * Copyright 2016 IBM Corp.
 *
 * 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 sl has convenience functions for returning pointers to values
package sl

import (
	"reflect"
	"strings"
	"time"

	"github.com/softlayer/softlayer-go/datatypes"
)

// Int returns a pointer to the int value provided
func Int(v int) *int {
	return &v
}

// Uint returns a pointer to the uint value provided
func Uint(v uint) *uint {
	return &v
}

// String returns a pointer to the string value provided
func String(v string) *string {
	return &v
}

// Bool returns a pointer to the bool value provided
func Bool(v bool) *bool {
	return &v
}

// Time converts the time.Time value provided to a datatypes.Time value,
// and returns a pointer to it
func Time(v time.Time) *datatypes.Time {
	r := datatypes.Time{Time: v}
	return &r
}

// Float converts the float value provided to a datatypes.Float64 value,
// and returns a pointer to it
func Float(v float64) *datatypes.Float64 {
	r := datatypes.Float64(v)
	return &r
}

// Convenience functions to simplify dereference of datatype properties

// Get returns the value of p, either p itself, or, if p is a pointer, the
// value that p points to. d is an optional default value to be returned
// in the event that p is nil. If d is not specified, and p is nil, a
// type-appropriate zero-value is returned instead.
func Get(p interface{}, d ...interface{}) interface{} {
	var (
		val interface{}
		ok  bool
	)

	if val, ok = GetOk(p); ok {
		return val
	}

	if len(d) > 0 {
		return d[0]
	}

	return val
}

// GetOk returns the value of p, either p itself, or, if p is a pointer, the
// value that p points to. If d is not specified, and p is nil, a type-
// appropriate zero-value is returned instead. If p is a value or non-nil
// pointer, the second return value will be true.  Otherwise, it will be false
func GetOk(p interface{}) (interface{}, bool) {
	t := reflect.TypeOf(p)

	// if p is a non-pointer, just return it
	if t.Kind() != reflect.Ptr {
		return p, true
	}

	// p is a pointer.  If non-nil, return the value pointed to
	v := reflect.Indirect(reflect.ValueOf(p))
	if v.IsValid() {
		return v.Interface(), true
	}

	// p is a nil pointer.  Return the zero value for the pointed-to type
	return reflect.Zero(t.Elem()).Interface(), false
}

// Grab returns the value specified by the path given,
// starting from the struct s.
// If at any point in the path the lookup falls short
// (i.e. a field is not found), or if the last field in the path is nil
// itself, a type-appropriate zero-value is returned.
// This behavior can be overidden by providing a default value.
//
// This is useful for getting values our of deeply nested structures
// Example: val := sl.Grab(virtualGuest, "Datacenter.Name")
func Grab(s interface{}, path string, d ...interface{}) interface{} {
	var (
		val interface{}
		ok  bool
	)

	if val, ok = GrabOk(s, path); ok {
		return val
	}

	if len(d) > 0 {
		return d[0]
	}

	return val
}

// GrabOk returns the value specified by the path given,
// starting from the struct s.
// If at any point in the path the lookup falls short
// (i.e. a field is not found), or if the last field in the path is nil
// itself, a type-appropriate zero-value is returned.
// It returns a second value, a boolean, which will be false if it failed
// to lookup the value, including if the last field in the path was nil.
//
// This is useful for getting values our of deeply nested structures
// Example: val, ok := sl.GrabOk(virtualGuest, "Datacenter.Name")
func GrabOk(s interface{}, path string) (interface{}, bool) {
	t := reflect.TypeOf(s)
	if t.Kind() != reflect.Struct {
		return nil, false
	}

	dotIndex := strings.Index(path, ".")
	if dotIndex == -1 {
		dotIndex = len(path)
	}

	fieldName := path[0:dotIndex]
	val := reflect.ValueOf(s)
	fieldVal := val.FieldByName(fieldName)
	if fieldVal.Kind() == reflect.Ptr {
		if fieldVal.IsNil() {
			return reflect.Zero(fieldVal.Type().Elem()).Interface(), false
		}

		fieldVal = reflect.Indirect(fieldVal)
	}

	result, ok := GetOk(fieldVal.Interface())
	if !ok {
		return result, ok
	}

	if dotIndex == len(path) {
		return result, ok
	}

	return GrabOk(result, path[dotIndex+1:len(path)])
}
<|endoftext|>