<commit_before>package authentication

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

	"github.com/Azure/go-autorest/autorest/azure"
)

var environmentTranslationMap = map[string]azure.Environment{
	"public":       azure.PublicCloud,
	"usgovernment": azure.USGovernmentCloud,
	"german":       azure.GermanCloud,
	"china":        azure.ChinaCloud,
}

type Environment struct {
	Portal                  string         `json:"portal"`
	Authentication          Authentication `json:"authentication"`
	Media                   string         `json:"media"`
	GraphAudience           string         `json:"graphAudience"`
	Graph                   string         `json:"graph"`
	Name                    string         `json:"name"`
	Suffixes                Suffixes       `json:"suffixes"`
	Batch                   string         `json:"batch"`
	ResourceManager         string         `json:"resourceManager"`
	VmImageAliasDoc         string         `json:"vmImageAliasDoc"`
	ActiveDirectoryDataLake string         `json:"activeDirectoryDataLake"`
	SqlManagement           string         `json:"sqlManagement"`
	Gallery                 string         `json:"gallery"`
}

type Authentication struct {
	LoginEndpoint    string   `json:"loginEndpoint"`
	Audiences        []string `json:"audiences"`
	Tenant           string   `json:"tenant"`
	IdentityProvider string   `json:"identityProvider"`
}

type Suffixes struct {
	AzureDataLakeStoreFileSystem        string `json:"azureDataLakeStoreFileSystem"`
	AcrLoginServer                      string `json:"acrLoginServer"`
	SqlServerHostname                   string `json:"sqlServerHostname"`
	AzureDataLakeAnalyticsCatalogAndJob string `json:"azureDataLakeAnalyticsCatalogAndJob"`
	KeyVaultDns                         string `json:"keyVaultDns"`
	Storage                             string `json:"storage"`
	AzureFrontDoorEndpointSuffix        string `json:"azureFrontDoorEndpointSuffix"`
}

// DetermineEnvironment determines what the Environment name is within
// the Azure SDK for Go and then returns the association environment, if it exists.
func DetermineEnvironment(name string) (*azure.Environment, error) {
	// detect cloud from environment
	env, envErr := azure.EnvironmentFromName(name)

	if envErr != nil {
		// try again with wrapped value to support readable values like german instead of AZUREGERMANCLOUD
		wrapped := fmt.Sprintf("AZURE%sCLOUD", name)
		env, envErr = azure.EnvironmentFromName(wrapped)
		if envErr != nil {
			return nil, fmt.Errorf("An Azure Environment with name %q was not found: %+v", name, envErr)
		}
	}

	return &env, nil
}

// LoadEnvironmentFromUrl attempts to load the specified environment from the endpoint.
// if the endpoint is an empty string, or an environment can't be
// found at the endpoint url then an error is returned
func LoadEnvironmentFromUrl(endpoint string) (*azure.Environment, error) {
	if endpoint == "" {
		return nil, fmt.Errorf("Endpoint was not set!")
	}

	env, err := azure.EnvironmentFromURL(endpoint)
	if err != nil {
		return nil, fmt.Errorf("Error retrieving Environment from Endpoint %q: %+v", endpoint, err)
	}

	return &env, nil
}

func normalizeEnvironmentName(input string) string {
	// Environment is stored as `Azure{Environment}Cloud`
	output := strings.ToLower(input)
	output = strings.TrimPrefix(output, "azure")
	output = strings.TrimSuffix(output, "cloud")

	// however Azure Public is `AzureCloud` in the CLI Profile and not `AzurePublicCloud`.
	if output == "" {
		return "public"
	}
	return output
}

// AzureEnvironmentByName returns a specific Azure Environment from the specified endpoint
func AzureEnvironmentByNameFromEndpoint(ctx context.Context, endpoint string, environmentName string) (*azure.Environment, error) {
	if env, ok := environmentTranslationMap[strings.ToLower(environmentName)]; ok {
		return &env, nil
	}

	if endpoint == "" {
		return nil, fmt.Errorf("unable to locate metadata for environment %q from the built in `public`, `usgoverment`, `china` and no custom metadata host has been specified", environmentName)
	}

	environments, err := getSupportedEnvironments(ctx, endpoint)
	if err != nil {
		return nil, err
	}

	// while the array contains values
	for _, env := range environments {
		if strings.EqualFold(env.Name, environmentName) {
			aEnv, err := buildAzureEnvironment(env)
			if err != nil {
				return nil, err
			}
			return aEnv, nil
		}
	}

	return nil, fmt.Errorf("unable to locate metadata for environment %q from custom metadata host %q", environmentName, endpoint)
}

// IsEnvironmentAzureStack returns whether a specific Azure Environment is an Azure Stack environment
func IsEnvironmentAzureStack(ctx context.Context, endpoint string, environmentName string) (bool, error) {
	if _, ok := environmentTranslationMap[strings.ToLower(environmentName)]; ok {
		return false, nil
	}

	environments, err := getSupportedEnvironments(ctx, endpoint)
	if err != nil {
		return false, err
	}

	// while the array contains values
	for _, env := range environments {
		if err != nil {
			return false, fmt.Errorf("unable to decode environment from %q response: %+v", endpoint, err)
		}
		if strings.EqualFold(env.Name, environmentName) {
			if !strings.EqualFold(env.Authentication.IdentityProvider, "AAD") || !strings.EqualFold(env.Authentication.Tenant, "common") {
				return true, nil
			}
			return false, nil
		}
	}

	return false, fmt.Errorf("unable to find environment %q from endpoint %q", environmentName, endpoint)
}

func getSupportedEnvironments(ctx context.Context, endpoint string) ([]Environment, error) {
	uri := fmt.Sprintf("https://%s/metadata/endpoints?api-version=2020-06-01", endpoint)
	client := http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
		},
	}
	req, err := http.NewRequestWithContext(ctx, "GET", uri, nil)
	if err != nil {
		return nil, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("retrieving environments from Azure MetaData service: %+v", err)
	}

	var environments []Environment
	if err := json.NewDecoder(resp.Body).Decode(&environments); err != nil {
		return nil, err
	}

	return environments, nil
}

func buildAzureEnvironment(env Environment) (*azure.Environment, error) {
	aEnv := &azure.Environment{
		Name:                       env.Name,
		ResourceManagerEndpoint:    env.ResourceManager,
		StorageEndpointSuffix:      env.Suffixes.Storage,
		ActiveDirectoryEndpoint:    env.Authentication.LoginEndpoint,
		GraphEndpoint:              env.Graph,
		KeyVaultEndpoint:           fmt.Sprintf("https://%s/", env.Suffixes.KeyVaultDns),
		GalleryEndpoint:            env.Gallery,
		BatchManagementEndpoint:    env.Batch,
		SQLDatabaseDNSSuffix:       env.Suffixes.SqlServerHostname,
		KeyVaultDNSSuffix:          env.Suffixes.KeyVaultDns,
		ContainerRegistryDNSSuffix: env.Suffixes.AcrLoginServer,
		ResourceIdentifiers: azure.ResourceIdentifier{
			// This isn't returned from the metadata url and is universal across all environments
			Storage:  "https://storage.azure.com/",
			Graph:    env.Graph,
			KeyVault: fmt.Sprintf("https://%s/", env.Suffixes.KeyVaultDns),
			Datalake: env.ActiveDirectoryDataLake,
			Batch:    env.Batch,
		},
	}

	if len(env.Authentication.Audiences) > 0 {
		aEnv.TokenAudience = env.Authentication.Audiences[0]
	} else {
		return nil, fmt.Errorf("unable to find token audience for environment %q", env.Name)
	}

	return aEnv, nil
}
<commit_msg>add N/A for values not returned by the metadata endpoint (#72)<commit_after>package authentication

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

	"github.com/Azure/go-autorest/autorest/azure"
)

var sdkEnvironmentLookupMap = map[string]azure.Environment{
	"public":       azure.PublicCloud,
	"usgovernment": azure.USGovernmentCloud,
	"german":       azure.GermanCloud,
	"china":        azure.ChinaCloud,
}

type Environment struct {
	Portal                  string         `json:"portal"`
	Authentication          Authentication `json:"authentication"`
	Media                   string         `json:"media"`
	GraphAudience           string         `json:"graphAudience"`
	Graph                   string         `json:"graph"`
	Name                    string         `json:"name"`
	Suffixes                Suffixes       `json:"suffixes"`
	Batch                   string         `json:"batch"`
	ResourceManager         string         `json:"resourceManager"`
	VmImageAliasDoc         string         `json:"vmImageAliasDoc"`
	ActiveDirectoryDataLake string         `json:"activeDirectoryDataLake"`
	SqlManagement           string         `json:"sqlManagement"`
	Gallery                 string         `json:"gallery"`
}

type Authentication struct {
	LoginEndpoint    string   `json:"loginEndpoint"`
	Audiences        []string `json:"audiences"`
	Tenant           string   `json:"tenant"`
	IdentityProvider string   `json:"identityProvider"`
}

type Suffixes struct {
	AzureDataLakeStoreFileSystem        string `json:"azureDataLakeStoreFileSystem"`
	AcrLoginServer                      string `json:"acrLoginServer"`
	SqlServerHostname                   string `json:"sqlServerHostname"`
	AzureDataLakeAnalyticsCatalogAndJob string `json:"azureDataLakeAnalyticsCatalogAndJob"`
	KeyVaultDns                         string `json:"keyVaultDns"`
	Storage                             string `json:"storage"`
	AzureFrontDoorEndpointSuffix        string `json:"azureFrontDoorEndpointSuffix"`
}

// DetermineEnvironment determines what the Environment name is within
// the Azure SDK for Go and then returns the association environment, if it exists.
func DetermineEnvironment(name string) (*azure.Environment, error) {
	// detect cloud from environment
	env, envErr := azure.EnvironmentFromName(name)

	if envErr != nil {
		// try again with wrapped value to support readable values like german instead of AZUREGERMANCLOUD
		wrapped := fmt.Sprintf("AZURE%sCLOUD", name)
		env, envErr = azure.EnvironmentFromName(wrapped)
		if envErr != nil {
			return nil, fmt.Errorf("An Azure Environment with name %q was not found: %+v", name, envErr)
		}
	}

	return &env, nil
}

// LoadEnvironmentFromUrl attempts to load the specified environment from the endpoint.
// if the endpoint is an empty string, or an environment can't be
// found at the endpoint url then an error is returned
func LoadEnvironmentFromUrl(endpoint string) (*azure.Environment, error) {
	if endpoint == "" {
		return nil, fmt.Errorf("Endpoint was not set!")
	}

	env, err := azure.EnvironmentFromURL(endpoint)
	if err != nil {
		return nil, fmt.Errorf("Error retrieving Environment from Endpoint %q: %+v", endpoint, err)
	}

	return &env, nil
}

func normalizeEnvironmentName(input string) string {
	// Environment is stored as `Azure{Environment}Cloud`
	output := strings.ToLower(input)
	output = strings.TrimPrefix(output, "azure")
	output = strings.TrimSuffix(output, "cloud")

	// however Azure Public is `AzureCloud` in the CLI Profile and not `AzurePublicCloud`.
	if output == "" {
		return "public"
	}
	return output
}

// AzureEnvironmentByName returns a specific Azure Environment from the specified endpoint
func AzureEnvironmentByNameFromEndpoint(ctx context.Context, endpoint string, environmentName string) (*azure.Environment, error) {
	if env, ok := sdkEnvironmentLookupMap[strings.ToLower(environmentName)]; ok {
		return &env, nil
	}

	if endpoint == "" {
		return nil, fmt.Errorf("unable to locate metadata for environment %q from the built in `public`, `usgoverment`, `china` and no custom metadata host has been specified", environmentName)
	}

	environments, err := getSupportedEnvironments(ctx, endpoint)
	if err != nil {
		return nil, err
	}

	// while the array contains values
	for _, env := range environments {
		if strings.EqualFold(env.Name, environmentName) {
			aEnv, err := buildAzureEnvironment(env)
			if err != nil {
				return nil, err
			}
			return aEnv, nil
		}
	}

	return nil, fmt.Errorf("unable to locate metadata for environment %q from custom metadata host %q", environmentName, endpoint)
}

// IsEnvironmentAzureStack returns whether a specific Azure Environment is an Azure Stack environment
func IsEnvironmentAzureStack(ctx context.Context, endpoint string, environmentName string) (bool, error) {
	if _, ok := sdkEnvironmentLookupMap[strings.ToLower(environmentName)]; ok {
		return false, nil
	}

	environments, err := getSupportedEnvironments(ctx, endpoint)
	if err != nil {
		return false, err
	}

	// while the array contains values
	for _, env := range environments {
		if err != nil {
			return false, fmt.Errorf("unable to decode environment from %q response: %+v", endpoint, err)
		}
		if strings.EqualFold(env.Name, environmentName) {
			if !strings.EqualFold(env.Authentication.IdentityProvider, "AAD") || !strings.EqualFold(env.Authentication.Tenant, "common") {
				return true, nil
			}
			return false, nil
		}
	}

	return false, fmt.Errorf("unable to find environment %q from endpoint %q", environmentName, endpoint)
}

func getSupportedEnvironments(ctx context.Context, endpoint string) ([]Environment, error) {
	uri := fmt.Sprintf("https://%s/metadata/endpoints?api-version=2020-06-01", endpoint)
	client := http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
		},
	}
	req, err := http.NewRequestWithContext(ctx, "GET", uri, nil)
	if err != nil {
		return nil, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("retrieving environments from Azure MetaData service: %+v", err)
	}

	var environments []Environment
	if err := json.NewDecoder(resp.Body).Decode(&environments); err != nil {
		return nil, err
	}

	return environments, nil
}

func buildAzureEnvironment(env Environment) (*azure.Environment, error) {
	aEnv := &azure.Environment{
		Name:                       env.Name,
		ResourceManagerEndpoint:    env.ResourceManager,
		StorageEndpointSuffix:      env.Suffixes.Storage,
		ActiveDirectoryEndpoint:    env.Authentication.LoginEndpoint,
		GraphEndpoint:              env.Graph,
		KeyVaultEndpoint:           fmt.Sprintf("https://%s/", env.Suffixes.KeyVaultDns),
		GalleryEndpoint:            env.Gallery,
		BatchManagementEndpoint:    env.Batch,
		SQLDatabaseDNSSuffix:       env.Suffixes.SqlServerHostname,
		KeyVaultDNSSuffix:          env.Suffixes.KeyVaultDns,
		ContainerRegistryDNSSuffix: env.Suffixes.AcrLoginServer,
		ResourceIdentifiers: azure.ResourceIdentifier{
			// This isn't returned from the metadata url and is universal across all environments
			Storage:             "https://storage.azure.com/",
			Graph:               env.Graph,
			KeyVault:            fmt.Sprintf("https://%s/", env.Suffixes.KeyVaultDns),
			Datalake:            env.ActiveDirectoryDataLake,
			Batch:               env.Batch,
			Synapse:             azure.NotAvailable,
			ServiceBus:          azure.NotAvailable,
			OperationalInsights: azure.NotAvailable,
		},
	}

	if len(env.Authentication.Audiences) > 0 {
		aEnv.TokenAudience = env.Authentication.Audiences[0]
	} else {
		return nil, fmt.Errorf("unable to find token audience for environment %q", env.Name)
	}

	return aEnv, nil
}
<|endoftext|>


<commit_before>package trello

import (
	"sort"
	"time"

	"github.com/pkg/errors"
)

type ListDuration struct {
	ListID       string
	ListName     string
	Duration     time.Duration
	FirstEntered time.Time
	TimesInList  int
}

func (l *ListDuration) AddDuration(d time.Duration) {
	l.Duration = l.Duration + d
	l.TimesInList++
}

func (c *Card) GetListDurations() (durations []*ListDuration, err error) {

	// Get all actions which affected the Card's List
	actions, err := c.GetListChangeActions()
	if err != nil {
		err = errors.Wrap(err, "GetListChangeActions() call failed.")
		return
	}
	sort.Sort(ByActionDate(actions))

	var prevTime time.Time
	var prevList *List

	durs := make(map[string]*ListDuration)
	for _, action := range actions {
		if prevList != nil {
			duration := action.Date.Sub(prevTime)
			_, durExists := durs[prevList.ID]
			if !durExists {
				durs[prevList.ID] = &ListDuration{ListID: prevList.ID, ListName: prevList.Name, Duration: duration, TimesInList: 1, FirstEntered: prevTime}
			} else {
				durs[prevList.ID].AddDuration(duration)
			}
		}
		prevList = ListAfterAction(action)
		prevTime = action.Date
	}

	if prevList != nil {
		duration := time.Now().Sub(prevTime)
		_, durExists := durs[prevList.ID]
		if !durExists {
			durs[prevList.ID] = &ListDuration{ListID: prevList.ID, ListName: prevList.Name, Duration: duration, TimesInList: 1, FirstEntered: prevTime}
		} else {
			durs[prevList.ID].AddDuration(duration)
		}
	}

	durations = make([]*ListDuration, 0, len(durs))
	for _, ld := range durs {
		durations = append(durations, ld)
	}
	sort.Sort(ByFirstEntered(durations))

	return durations, nil
}
<commit_msg>Refactor GetListDurations().<commit_after>package trello

import (
	"sort"
	"time"

	"github.com/pkg/errors"
)

type ListDuration struct {
	ListID       string
	ListName     string
	Duration     time.Duration
	FirstEntered time.Time
	TimesInList  int
}

func (l *ListDuration) AddDuration(d time.Duration) {
	l.Duration = l.Duration + d
	l.TimesInList++
}

// Analytzes a Cards actions to figure out how long it was in each List
func (c *Card) GetListDurations() (durations []*ListDuration, err error) {

	var actions ActionCollection
	if len(c.Actions) == 0 {
		// Get all actions which affected the Card's List
		c.client.Logger.Debugf("GetListDurations() called on card '%s' without any Card.Actions. Fetching fresh.", c.ID)
		actions, err = c.GetListChangeActions()
		if err != nil {
			err = errors.Wrap(err, "GetListChangeActions() call failed.")
			return
		}
	} else {
		actions = c.Actions.FilterToListChangeActions()
	}

	return actions.GetListDurations()
}

func (actions ActionCollection) GetListDurations() (durations []*ListDuration, err error) {
	sort.Sort(actions)

	var prevTime time.Time
	var prevList *List

	durs := make(map[string]*ListDuration)
	for _, action := range actions {
		if prevList != nil {
			duration := action.Date.Sub(prevTime)
			_, durExists := durs[prevList.ID]
			if !durExists {
				durs[prevList.ID] = &ListDuration{ListID: prevList.ID, ListName: prevList.Name, Duration: duration, TimesInList: 1, FirstEntered: prevTime}
			} else {
				durs[prevList.ID].AddDuration(duration)
			}
		}
		prevList = ListAfterAction(action)
		prevTime = action.Date
	}

	if prevList != nil {
		duration := time.Now().Sub(prevTime)
		_, durExists := durs[prevList.ID]
		if !durExists {
			durs[prevList.ID] = &ListDuration{ListID: prevList.ID, ListName: prevList.Name, Duration: duration, TimesInList: 1, FirstEntered: prevTime}
		} else {
			durs[prevList.ID].AddDuration(duration)
		}
	}

	durations = make([]*ListDuration, 0, len(durs))
	for _, ld := range durs {
		durations = append(durations, ld)
	}
	sort.Sort(ByFirstEntered(durations))

	return durations, nil
}
<|endoftext|>


<commit_before>/*
 *    Copyright (C) 2014      Daniel 'grindhold' Brendle
 *                  2014-2017 Christian Muehlhaeuser
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Daniel 'grindhold' Brendle <grindhold@skarphed.org>
 *      Christian Muehlhaeuser <muesli@gmail.com>
 */

// Package jenkinsbee is a Bee that can interface with a Jenkins server.
package jenkinsbee

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/muesli/beehive/bees"
)

// JenkinsBee is a Bee that can interface with a Jenkins server.
type JenkinsBee struct {
	bees.Bee

	url      string
	user     string
	password string

	Jobs      map[string]Job `json:"jobs"`
	eventChan chan bees.Event
}

type report struct {
	Jobs []Job `json:"jobs"`
}

// Job represents the JSON API response for a Jenkins job.
type Job struct {
	Name  string `json:"name"`
	URL   string `json:"url"`
	Color string `json:"color"`
}

func (mod *JenkinsBee) announceStatusChange(j Job) {
	event := bees.Event{
		Bee:  mod.Name(),
		Name: "status_change",
		Options: []bees.Placeholder{
			{
				Name:  "name",
				Type:  "string",
				Value: j.Name,
			},
			{
				Name:  "url",
				Type:  "string",
				Value: j.URL,
			},
			{
				Name:  "status",
				Type:  "string",
				Value: j.Color,
			},
		},
	}
	mod.eventChan <- event
}

// Run executes the Bee's event loop.
func (mod *JenkinsBee) Run(cin chan bees.Event) {
	mod.eventChan = cin
	for {
		select {
		case <-mod.SigChan:
			return

		default:
		}
		time.Sleep(10 * time.Second)

		request, err := http.NewRequest("GET", mod.url+"/api/json", nil)
		if err != nil {
			mod.Logln("Could not build request")
			break
		}
		request.SetBasicAuth(mod.user, mod.password)

		client := http.Client{}
		resp, err := client.Do(request)
		if err != nil {
			mod.Logln("Could not call API on "+mod.url+"/api/json", err)
			continue
		}

		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			mod.Logln("Could not read data of API-Call")
			continue
		}
		rep := new(report)
		err = json.Unmarshal(body, &rep)
		if err != nil {
			mod.Logln("Failed to unmarshal JSON")
			continue
		}

		jobmap := make(map[string]Job)
		for job := range rep.Jobs {
			if oldState, ok := mod.Jobs[rep.Jobs[job].Name]; !ok {
				// There is no record of this job
				mod.announceStatusChange(rep.Jobs[job])
			} else {
				// There exists a record of this job
				if oldState.Color != rep.Jobs[job].Color {
					// The status is different from last time
					mod.announceStatusChange(rep.Jobs[job])
				}
			}
			jobmap[rep.Jobs[job].Name] = rep.Jobs[job]
		}
		mod.Jobs = jobmap
	}
}

func (mod *JenkinsBee) triggerBuild(jobname string) {
	client := http.Client{}
	request, err := http.NewRequest("GET", mod.url+"/job/"+jobname+"/build", nil)
	if err != nil {
		mod.Logln("Could not build request")
		return
	}
	request.SetBasicAuth(mod.user, mod.password)
	if _, err := client.Do(request); err != nil {
		mod.Logln("Could not trigger build")
	}
}

// Action triggers the action passed to it.
func (mod *JenkinsBee) Action(action bees.Action) []bees.Placeholder {
	outs := []bees.Placeholder{}
	switch action.Name {
	case "trigger":
		jobname := ""
		action.Options.Bind("job", &jobname)

		mod.triggerBuild(jobname)

	default:
		panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
	}
	return outs
}

// ReloadOptions parses the config options and initializes the Bee.
func (mod *JenkinsBee) ReloadOptions(options bees.BeeOptions) {
	mod.SetOptions(options)

	options.Bind("url", &mod.url)
	options.Bind("user", &mod.user)
	options.Bind("password", &mod.password)
}
<commit_msg>Don't block in JenkinsBee so it can be gracefully stopped<commit_after>/*
 *    Copyright (C) 2014      Daniel 'grindhold' Brendle
 *                  2014-2017 Christian Muehlhaeuser
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Daniel 'grindhold' Brendle <grindhold@skarphed.org>
 *      Christian Muehlhaeuser <muesli@gmail.com>
 */

// Package jenkinsbee is a Bee that can interface with a Jenkins server.
package jenkinsbee

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/muesli/beehive/bees"
)

// JenkinsBee is a Bee that can interface with a Jenkins server.
type JenkinsBee struct {
	bees.Bee

	url      string
	user     string
	password string

	Jobs      map[string]Job `json:"jobs"`
	eventChan chan bees.Event
}

type report struct {
	Jobs []Job `json:"jobs"`
}

// Job represents the JSON API response for a Jenkins job.
type Job struct {
	Name  string `json:"name"`
	URL   string `json:"url"`
	Color string `json:"color"`
}

func (mod *JenkinsBee) announceStatusChange(j Job) {
	event := bees.Event{
		Bee:  mod.Name(),
		Name: "status_change",
		Options: []bees.Placeholder{
			{
				Name:  "name",
				Type:  "string",
				Value: j.Name,
			},
			{
				Name:  "url",
				Type:  "string",
				Value: j.URL,
			},
			{
				Name:  "status",
				Type:  "string",
				Value: j.Color,
			},
		},
	}
	mod.eventChan <- event
}

func (mod *JenkinsBee) poll() {
	request, err := http.NewRequest("GET", mod.url+"/api/json", nil)
	if err != nil {
		mod.LogErrorf("Could not build request: %s\n", err)
		return
	}
	request.SetBasicAuth(mod.user, mod.password)

	client := http.Client{}
	resp, err := client.Do(request)
	if err != nil {
		mod.LogErrorf("Could not call API on %s/api/json: %s\n", mod.url, err)
		return
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		mod.LogErrorf("Could not read data from API: %s\n", err)
		return
	}
	rep := new(report)
	err = json.Unmarshal(body, &rep)
	if err != nil {
		mod.LogErrorf("Failed to unmarshal JSON: %s\n", err)
		return
	}

	jobmap := make(map[string]Job)
	for job := range rep.Jobs {
		if oldState, ok := mod.Jobs[rep.Jobs[job].Name]; !ok {
			// There is no record of this job
			mod.announceStatusChange(rep.Jobs[job])
		} else {
			// There exists a record of this job
			if oldState.Color != rep.Jobs[job].Color {
				// The status is different from last time
				mod.announceStatusChange(rep.Jobs[job])
			}
		}
		jobmap[rep.Jobs[job].Name] = rep.Jobs[job]
	}
	mod.Jobs = jobmap
}

// Run executes the Bee's event loop.
func (mod *JenkinsBee) Run(cin chan bees.Event) {
	mod.eventChan = cin

	for {
		select {
		case <-mod.SigChan:
			return

		case <-time.After(time.Duration(10 * time.Second)):
			mod.poll()
		}
	}
}

func (mod *JenkinsBee) triggerBuild(jobname string) {
	client := http.Client{}
	request, err := http.NewRequest("GET", mod.url+"/job/"+jobname+"/build", nil)
	if err != nil {
		mod.LogErrorf("Could not build request: %s\n", err)
		return
	}
	request.SetBasicAuth(mod.user, mod.password)
	if _, err := client.Do(request); err != nil {
		mod.LogErrorf("Could not trigger build: %s\n", err)
	}
}

// Action triggers the action passed to it.
func (mod *JenkinsBee) Action(action bees.Action) []bees.Placeholder {
	outs := []bees.Placeholder{}
	switch action.Name {
	case "trigger":
		jobname := ""
		action.Options.Bind("job", &jobname)

		mod.triggerBuild(jobname)

	default:
		panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
	}
	return outs
}

// ReloadOptions parses the config options and initializes the Bee.
func (mod *JenkinsBee) ReloadOptions(options bees.BeeOptions) {
	mod.SetOptions(options)

	options.Bind("url", &mod.url)
	options.Bind("user", &mod.user)
	options.Bind("password", &mod.password)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"log/syslog"
	"os"
	"time"

	"github.com/x-cray/marathon-service-registrator/bridge"
	"github.com/x-cray/marathon-service-registrator/types"

	log "github.com/Sirupsen/logrus"
	logrusSyslog "github.com/Sirupsen/logrus/hooks/syslog"
	prefixed "github.com/x-cray/logrus-prefixed-formatter"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	reconnectInterval = 5 * time.Second
)

var (
	version        string
	app            = kingpin.New("registrator", "Automatically registers/deregisters Marathon tasks as services in Consul.")
	consul         = app.Flag("consul", "Address and port of Consul agent").Short('c').Default("http://127.0.0.1:8500").URL()
	marathon       = app.Flag("marathon", "URL of Marathon instance. Multiple inctances may be specified in case of HA setup: http://addr1:8080,addr2:8080,addr3:8080").Short('m').Default("http://127.0.0.1:8080").String()
	resyncInterval = app.Flag("resync-interval", "Time interval to resync Marathon services to determine dangling instances. Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"").Short('i').Default("5m").Duration()
	enableDryRun   = app.Flag("dry-run", "Do not perform actual service registeration/deregistration").Short('d').Bool()
	logLevel       = app.Flag("log-level", "Set the logging level - valid values are \"debug\", \"info\", \"warn\", \"error\", and \"fatal\"").Short('l').Default("info").Enum("debug", "info", "warn", "error", "fatal")
	enableSyslog   = app.Flag("syslog", "Send the log output to syslog").Short('s').Bool()
)

func validateParams(app *kingpin.Application) error {
	if *resyncInterval <= 0 {
		return errors.New("--resync-interval must be greater than 0")
	}
	return nil
}

func printVersion(*kingpin.ParseContext) error {
	fmt.Fprintln(os.Stderr, version)
	os.Exit(0)
	return nil
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func trySync(b *bridge.Bridge) bool {
	if err := b.Sync(); err != nil {
		log.Errorf("Failed to sync services: %v", err)
		return false
	}

	return true
}

func main() {
	config, err := getConfig()
	assert(err)

	log.Infof("Starting Marathon service registrator v%s", version)
	b, err := bridge.New(config)
	assert(err)

	log.Info("Performing initial sync")
	for {
		if trySync(b) {
			break
		}
		log.Infof("Retrying initial sync in %v", reconnectInterval)
		time.Sleep(reconnectInterval)
	}

	quit := make(chan bool)

	// Start the resync timer.
	ticker := time.NewTicker(config.ResyncInterval)
	go func() {
		for {
			select {
			case <-ticker.C:
				trySync(b)
			case <-quit:
				ticker.Stop()
				return
			}
		}
	}()

	for {
		err = b.ProcessSchedulerEvents()
		if err == nil {
			break
		}
		log.Info("Retrying event stream connection in %v", reconnectInterval)
		time.Sleep(reconnectInterval)
	}

	close(quit)
	log.Fatal("Scheduler event loop closed")
}

func getConfig() (*types.Config, error) {
	app.Validate(validateParams)
	kingpin.HelpFlag.Short('h')
	app.Flag("version", "Print application version and exit").PreAction(printVersion).Short('v').Bool()
	kingpin.MustParse(app.Parse(os.Args[1:]))

	c := &types.Config{
		Consul:         *consul,
		Marathon:       *marathon,
		ResyncInterval: *resyncInterval,
		DryRun:         *enableDryRun,
	}

	// Setup the logging.
	level, err := log.ParseLevel(*logLevel)
	if err != nil {
		return nil, err
	}

	log.SetFormatter(new(prefixed.TextFormatter))
	log.SetLevel(level)

	if *enableSyslog {
		hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_DEBUG, app.Name)
		if err != nil {
			return nil, err
		}

		log.AddHook(hook)
	}

	return c, nil
}
<commit_msg>Add --force-colors option<commit_after>package main

import (
	"errors"
	"fmt"
	"log/syslog"
	"os"
	"time"

	"github.com/x-cray/marathon-service-registrator/bridge"
	"github.com/x-cray/marathon-service-registrator/types"

	log "github.com/Sirupsen/logrus"
	logrusSyslog "github.com/Sirupsen/logrus/hooks/syslog"
	prefixed "github.com/x-cray/logrus-prefixed-formatter"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	reconnectInterval = 5 * time.Second
)

var (
	version        string
	app            = kingpin.New("registrator", "Automatically registers/deregisters Marathon tasks as services in Consul.")
	consul         = app.Flag("consul", "Address and port of Consul agent").Short('c').Default("http://127.0.0.1:8500").URL()
	marathon       = app.Flag("marathon", "URL of Marathon instance. Multiple inctances may be specified in case of HA setup: http://addr1:8080,addr2:8080,addr3:8080").Short('m').Default("http://127.0.0.1:8080").String()
	resyncInterval = app.Flag("resync-interval", "Time interval to resync Marathon services to determine dangling instances. Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"").Short('i').Default("5m").Duration()
	enableDryRun   = app.Flag("dry-run", "Do not perform actual service registeration/deregistration. Just log intents").Short('d').Bool()
	logLevel       = app.Flag("log-level", "Set the logging level - valid values are \"debug\", \"info\", \"warn\", \"error\", and \"fatal\"").Short('l').Default("info").Enum("debug", "info", "warn", "error", "fatal")
	enableSyslog   = app.Flag("syslog", "Send the log output to syslog").Short('s').Bool()
	forceColors    = app.Flag("force-colors", "Force colored log output").Short('r').Bool()
)

func validateParams(app *kingpin.Application) error {
	if *resyncInterval <= 0 {
		return errors.New("--resync-interval must be greater than 0")
	}
	return nil
}

func printVersion(*kingpin.ParseContext) error {
	fmt.Fprintln(os.Stderr, version)
	os.Exit(0)
	return nil
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func trySync(b *bridge.Bridge) bool {
	if err := b.Sync(); err != nil {
		log.Errorf("Failed to sync services: %v", err)
		return false
	}

	return true
}

func main() {
	config, err := getConfig()
	assert(err)

	log.Infof("Starting Marathon service registrator v%s", version)
	b, err := bridge.New(config)
	assert(err)

	log.Info("Performing initial sync")
	for {
		if trySync(b) {
			break
		}
		log.Infof("Retrying initial sync in %v", reconnectInterval)
		time.Sleep(reconnectInterval)
	}

	quit := make(chan bool)

	// Start the resync timer.
	ticker := time.NewTicker(config.ResyncInterval)
	go func() {
		for {
			select {
			case <-ticker.C:
				trySync(b)
			case <-quit:
				ticker.Stop()
				return
			}
		}
	}()

	for {
		err = b.ProcessSchedulerEvents()
		if err == nil {
			break
		}
		log.Info("Retrying event stream connection in %v", reconnectInterval)
		time.Sleep(reconnectInterval)
	}

	close(quit)
	log.Fatal("Scheduler event loop closed")
}

func getConfig() (*types.Config, error) {
	app.Validate(validateParams)
	kingpin.HelpFlag.Short('h')
	app.Flag("version", "Print application version and exit").PreAction(printVersion).Short('v').Bool()
	kingpin.MustParse(app.Parse(os.Args[1:]))

	c := &types.Config{
		Consul:         *consul,
		Marathon:       *marathon,
		ResyncInterval: *resyncInterval,
		DryRun:         *enableDryRun,
	}

	// Setup the logging.
	level, err := log.ParseLevel(*logLevel)
	if err != nil {
		return nil, err
	}

	log.SetFormatter(&prefixed.TextFormatter{
		ForceColors: *forceColors,
	})
	log.SetLevel(level)

	if *enableSyslog {
		hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_DEBUG, app.Name)
		if err != nil {
			return nil, err
		}

		log.AddHook(hook)
	}

	return c, nil
}
<|endoftext|>


<commit_before>package render

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/vito/booklit"
)

var initTmpl *template.Template

type WalkContext struct {
	Current *booklit.Section
	Section *booklit.Section
}

func init() {
	initTmpl = template.New("engine").Funcs(template.FuncMap{
		"url": tagURLFunc,

		"stripAux": booklit.StripAux,

		"rawHTML": func(con booklit.Content) template.HTML {
			return template.HTML(con.String())
		},

		"render": func(booklit.Content) (template.HTML, error) {
			return "", errors.New("render stubbed out")
		},

		"walkContext": func(current *booklit.Section, section *booklit.Section) WalkContext {
			return WalkContext{
				Current: current,
				Section: section,
			}
		},

		"headerDepth": func(con *booklit.Section) int {
			depth := con.PageDepth() + 1
			if depth > 6 {
				depth = 6
			}

			return depth
		},
	})

	for _, asset := range AssetNames() {
		info, err := AssetInfo(asset)
		if err != nil {
			panic(err)
		}

		content := strings.TrimRight(string(MustAsset(asset)), "\n")

		_, err = initTmpl.New(filepath.Base(info.Name())).Parse(content)
		if err != nil {
			panic(err)
		}
	}
}

type HTMLRenderingEngine struct {
	tmpl         *template.Template
	tmplModTimes map[string]time.Time

	template *template.Template
	data     interface{}
}

func NewHTMLRenderingEngine() *HTMLRenderingEngine {
	engine := &HTMLRenderingEngine{
		tmplModTimes: map[string]time.Time{},
	}

	engine.resetTmpl()

	return engine
}

func (engine *HTMLRenderingEngine) resetTmpl() {
	engine.tmpl = template.Must(initTmpl.Clone())
	engine.tmpl.Funcs(template.FuncMap{
		"render": engine.subRender,
	})
}

func (engine *HTMLRenderingEngine) LoadTemplates(templatesDir string) error {
	templates, err := filepath.Glob(filepath.Join(templatesDir, "*.tmpl"))
	if err != nil {
		return err
	}

	var shouldReload bool
	for _, path := range templates {
		info, err := os.Stat(path)
		if err != nil {
			return err
		}

		modTime := info.ModTime()

		lastModTime, found := engine.tmplModTimes[path]
		if !found || modTime.After(lastModTime) {
			shouldReload = true
		}

		engine.tmplModTimes[path] = modTime
	}

	if !shouldReload {
		return nil
	}

	engine.resetTmpl()

	for _, path := range templates {
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		trimmed := strings.TrimRight(string(content), "\n")

		_, err = engine.tmpl.New(filepath.Base(path)).Parse(trimmed)
		if err != nil {
			return err
		}
	}

	return nil
}

func (engine *HTMLRenderingEngine) FileExtension() string {
	return "html"
}

func (engine *HTMLRenderingEngine) URL(tag booklit.Tag) string {
	return tagURLFunc(tag)
}

func (engine *HTMLRenderingEngine) RenderSection(out io.Writer, con *booklit.Section) error {
	if con.Style != "" {
		engine.template = engine.tmpl.Lookup(con.Style + "-page.tmpl")
	} else {
		engine.template = engine.tmpl.Lookup("page.tmpl")
	}

	engine.data = con

	return engine.render(out)
}

func (engine *HTMLRenderingEngine) VisitString(con booklit.String) error {
	engine.template = engine.tmpl.Lookup("string.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitReference(con *booklit.Reference) error {
	engine.template = engine.tmpl.Lookup("reference.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitSection(con *booklit.Section) error {
	if con.Style != "" {
		engine.template = engine.tmpl.Lookup(con.Style + ".tmpl")

		if engine.template == nil {
			return fmt.Errorf("no '%s.tmpl' template defined for section: %s", con.Style, con.PrimaryTag.Name)
		}
	} else {
		engine.template = engine.tmpl.Lookup("section.tmpl")
	}

	engine.data = con

	return nil
}

func (engine *HTMLRenderingEngine) VisitSequence(con booklit.Sequence) error {
	engine.template = engine.tmpl.Lookup("sequence.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitParagraph(con booklit.Paragraph) error {
	engine.template = engine.tmpl.Lookup("paragraph.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitPreformatted(con booklit.Preformatted) error {
	engine.template = engine.tmpl.Lookup("preformatted.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitTableOfContents(con booklit.TableOfContents) error {
	engine.template = engine.tmpl.Lookup("toc.tmpl")
	engine.data = con.Section
	return nil
}

func (engine *HTMLRenderingEngine) VisitStyled(con booklit.Styled) error {
	engine.template = engine.tmpl.Lookup(string(con.Style) + ".tmpl")
	if engine.template == nil {
		return fmt.Errorf("no template defined for style: %s", con.Style)
	}

	engine.data = con

	return nil
}

func (engine *HTMLRenderingEngine) VisitTarget(con booklit.Target) error {
	engine.template = engine.tmpl.Lookup("target.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitImage(con booklit.Image) error {
	engine.template = engine.tmpl.Lookup("image.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitList(con booklit.List) error {
	engine.template = engine.tmpl.Lookup("list.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitLink(con booklit.Link) error {
	engine.template = engine.tmpl.Lookup("link.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitTable(con booklit.Table) error {
	engine.template = engine.tmpl.Lookup("table.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) VisitDefinitions(con booklit.Definitions) error {
	engine.template = engine.tmpl.Lookup("definitions.tmpl")
	engine.data = con
	return nil
}

func (engine *HTMLRenderingEngine) render(out io.Writer) error {
	if engine.template == nil {
		return fmt.Errorf("unknown template for '%s' (%T)", engine.data, engine.data)
	}

	return engine.template.Execute(out, engine.data)
}

func (engine *HTMLRenderingEngine) subRender(content booklit.Content) (template.HTML, error) {
	buf := new(bytes.Buffer)

	subEngine := NewHTMLRenderingEngine()
	subEngine.tmpl = engine.tmpl

	err := content.Visit(subEngine)
	if err != nil {
		return "", err
	}

	err = subEngine.render(buf)
	if err != nil {
		return "", err
	}

	return template.HTML(buf.String()), nil
}

func tagURLFunc(tag booklit.Tag) string {
	return sectionURL(tag.Section, tag.Anchor)
}

func sectionURL(section *booklit.Section, anchor string) string {
	owner := sectionPageOwner(section)

	if owner != section {
		if anchor == "" {
			anchor = section.PrimaryTag.Name
		}

		return sectionURL(owner, anchor)
	}

	filename := section.PrimaryTag.Name + ".html"

	if anchor != "" {
		filename += "#" + anchor
	}

	return filename
}

func sectionPageOwner(section *booklit.Section) *booklit.Section {
	if section.Parent == nil {
		return section
	}

	if section.Parent.SplitSections {
		return section
	}

	return sectionPageOwner(section.Parent)
}
<commit_msg>catch *all* missing template errors early<commit_after>package render

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/vito/booklit"
)

var initTmpl *template.Template

type WalkContext struct {
	Current *booklit.Section
	Section *booklit.Section
}

func init() {
	initTmpl = template.New("engine").Funcs(template.FuncMap{
		"url": tagURLFunc,

		"stripAux": booklit.StripAux,

		"rawHTML": func(con booklit.Content) template.HTML {
			return template.HTML(con.String())
		},

		"render": func(booklit.Content) (template.HTML, error) {
			return "", errors.New("render stubbed out")
		},

		"walkContext": func(current *booklit.Section, section *booklit.Section) WalkContext {
			return WalkContext{
				Current: current,
				Section: section,
			}
		},

		"headerDepth": func(con *booklit.Section) int {
			depth := con.PageDepth() + 1
			if depth > 6 {
				depth = 6
			}

			return depth
		},
	})

	for _, asset := range AssetNames() {
		info, err := AssetInfo(asset)
		if err != nil {
			panic(err)
		}

		content := strings.TrimRight(string(MustAsset(asset)), "\n")

		_, err = initTmpl.New(filepath.Base(info.Name())).Parse(content)
		if err != nil {
			panic(err)
		}
	}
}

type HTMLRenderingEngine struct {
	tmpl         *template.Template
	tmplModTimes map[string]time.Time

	template *template.Template
	data     interface{}
}

func NewHTMLRenderingEngine() *HTMLRenderingEngine {
	engine := &HTMLRenderingEngine{
		tmplModTimes: map[string]time.Time{},
	}

	engine.resetTmpl()

	return engine
}

func (engine *HTMLRenderingEngine) resetTmpl() {
	engine.tmpl = template.Must(initTmpl.Clone())
	engine.tmpl.Funcs(template.FuncMap{
		"render": engine.subRender,
	})
}

func (engine *HTMLRenderingEngine) LoadTemplates(templatesDir string) error {
	templates, err := filepath.Glob(filepath.Join(templatesDir, "*.tmpl"))
	if err != nil {
		return err
	}

	var shouldReload bool
	for _, path := range templates {
		info, err := os.Stat(path)
		if err != nil {
			return err
		}

		modTime := info.ModTime()

		lastModTime, found := engine.tmplModTimes[path]
		if !found || modTime.After(lastModTime) {
			shouldReload = true
		}

		engine.tmplModTimes[path] = modTime
	}

	if !shouldReload {
		return nil
	}

	engine.resetTmpl()

	for _, path := range templates {
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		trimmed := strings.TrimRight(string(content), "\n")

		_, err = engine.tmpl.New(filepath.Base(path)).Parse(trimmed)
		if err != nil {
			return err
		}
	}

	return nil
}

func (engine *HTMLRenderingEngine) FileExtension() string {
	return "html"
}

func (engine *HTMLRenderingEngine) URL(tag booklit.Tag) string {
	return tagURLFunc(tag)
}

func (engine *HTMLRenderingEngine) RenderSection(out io.Writer, con *booklit.Section) error {
	tmpl := "page"
	if con.Style != "" {
		tmpl = con.Style + "-page"
	}

	engine.data = con

	err := engine.setTmpl(tmpl)
	if err != nil {
		return err
	}

	return engine.render(out)
}

func (engine *HTMLRenderingEngine) VisitString(con booklit.String) error {
	engine.data = con
	return engine.setTmpl("string")
}

func (engine *HTMLRenderingEngine) VisitReference(con *booklit.Reference) error {
	engine.data = con
	return engine.setTmpl("reference")
}

func (engine *HTMLRenderingEngine) VisitSection(con *booklit.Section) error {
	tmpl := "section"
	if con.Style != "" {
		tmpl = con.Style
	}

	engine.data = con
	return engine.setTmpl(tmpl)
}

func (engine *HTMLRenderingEngine) VisitSequence(con booklit.Sequence) error {
	engine.data = con
	return engine.setTmpl("sequence")
}

func (engine *HTMLRenderingEngine) VisitParagraph(con booklit.Paragraph) error {
	engine.data = con
	return engine.setTmpl("paragraph")
}

func (engine *HTMLRenderingEngine) VisitPreformatted(con booklit.Preformatted) error {
	engine.data = con
	return engine.setTmpl("preformatted")
}

func (engine *HTMLRenderingEngine) VisitTableOfContents(con booklit.TableOfContents) error {
	engine.data = con.Section
	return engine.setTmpl("toc")
}

func (engine *HTMLRenderingEngine) VisitStyled(con booklit.Styled) error {
	engine.data = con
	return engine.setTmpl(string(con.Style))
}

func (engine *HTMLRenderingEngine) VisitTarget(con booklit.Target) error {
	engine.data = con
	return engine.setTmpl("target")
}

func (engine *HTMLRenderingEngine) VisitImage(con booklit.Image) error {
	engine.data = con
	return engine.setTmpl("image")
}

func (engine *HTMLRenderingEngine) VisitList(con booklit.List) error {
	engine.data = con
	return engine.setTmpl("list")
}

func (engine *HTMLRenderingEngine) VisitLink(con booklit.Link) error {
	engine.data = con
	return engine.setTmpl("link")
}

func (engine *HTMLRenderingEngine) VisitTable(con booklit.Table) error {
	engine.data = con
	return engine.setTmpl("table")
}

func (engine *HTMLRenderingEngine) VisitDefinitions(con booklit.Definitions) error {
	engine.data = con
	return engine.setTmpl("definitions")
}

func (engine *HTMLRenderingEngine) setTmpl(name string) error {
	tmpl := engine.tmpl.Lookup(name+".tmpl")

	if tmpl == nil {
		return fmt.Errorf("template '%s.tmpl' not found", name)
	}

	engine.template = tmpl

	return nil
}

func (engine *HTMLRenderingEngine) render(out io.Writer) error {
	if engine.template == nil {
		return fmt.Errorf("unknown template for '%s' (%T)", engine.data, engine.data)
	}

	return engine.template.Execute(out, engine.data)
}

func (engine *HTMLRenderingEngine) subRender(content booklit.Content) (template.HTML, error) {
	buf := new(bytes.Buffer)

	subEngine := NewHTMLRenderingEngine()
	subEngine.tmpl = engine.tmpl

	err := content.Visit(subEngine)
	if err != nil {
		return "", err
	}

	err = subEngine.render(buf)
	if err != nil {
		return "", err
	}

	return template.HTML(buf.String()), nil
}

func tagURLFunc(tag booklit.Tag) string {
	return sectionURL(tag.Section, tag.Anchor)
}

func sectionURL(section *booklit.Section, anchor string) string {
	owner := sectionPageOwner(section)

	if owner != section {
		if anchor == "" {
			anchor = section.PrimaryTag.Name
		}

		return sectionURL(owner, anchor)
	}

	filename := section.PrimaryTag.Name + ".html"

	if anchor != "" {
		filename += "#" + anchor
	}

	return filename
}

func sectionPageOwner(section *booklit.Section) *booklit.Section {
	if section.Parent == nil {
		return section
	}

	if section.Parent.SplitSections {
		return section
	}

	return sectionPageOwner(section.Parent)
}
<|endoftext|>


<commit_before>package repl

import "fmt"

// Prompt is the REPL prompt
type Prompt struct {
	URL   string
	Index string
}

// NewPrompt creates a new prompt with the defaults (localhost:9200)
func NewPrompt() *Prompt {
	return &Prompt{}
}

// Prompt displays the prompt
func (prompt *Prompt) Prompt() string {
	return fmt.Sprint(
		prompt.URL,
		" (",
		prompt.Index,
		") > ",
	)
}
<commit_msg>Remove blank fields from prompt<commit_after>package repl

import (
	"bytes"
	"fmt"
)

// Prompt is the REPL prompt
type Prompt struct {
	URL   string
	Index string
}

// NewPrompt creates a new prompt with the defaults (localhost:9200)
func NewPrompt() *Prompt {
	return &Prompt{}
}

// Prompt displays the prompt
func (prompt *Prompt) Prompt() string {
	buf := bytes.NewBufferString("")

	if prompt.URL != "" {
		buf.WriteString(fmt.Sprintf("%s ", prompt.URL))
	}

	if prompt.Index != "" {
		buf.WriteString(fmt.Sprintf("(%s) ", prompt.Index))
	}

	buf.WriteString("> ")
	return buf.String()
}
<|endoftext|>


<commit_before>package couch

import (
	"fmt"
	"net/url"
)

// TODO add: db.RunningReplications() []Replication
// TODO add: repl.Running()

// A replication from a source to a target
type Replication struct {
	source     *Database
	target     *Database
	continuous bool
	sessionID  string
}

// A bidirectional replication
type Sync struct {
	replA2B *Replication
	replB2A *Replication
}

// CouchDB request for replication
type replRequest struct {
	CreateTarget bool   `json:"create_target"`
	Source       string `json:"source"`
	Target       string `json:"target"`
	Continuous   bool   `json:"continuous"`
	Cancel       bool   `json:"cancel,omitempty"`
}

// CouchDB response to replication request
type replResponse struct {
	Ok            bool   `json:"ok"`
	ReplIDVersion int    `json:"replication_id_version"`
	SessionID     string `json:"session_id"`
	SourceLastSeq int    `json:"source_last_seq"`
}

// Replicates given database to a target database. If the target database
// does not exist it will be created. The target database may be on a different host.
func (db *Database) ReplicateTo(target *Database, continuously bool) (*Replication, error) {
	var resp replResponse
	req := replRequest{CreateTarget: true, Source: db.URL(), Target: target.urlWithCredentials(), Continuous: continuously}
	_, err := Do(db.replicationURL(), "POST", db.Cred(), req, &resp)
	if err != nil {
		return nil, err
	}
	repl := &Replication{source: db, target: target, continuous: continuously, sessionID: resp.SessionID}
	return repl, err
}

// Cancel a continuously running replication
func (repl *Replication) Cancel() error {
	req := replRequest{CreateTarget: true, Source: repl.source.URL(), Target: repl.target.URL(), Continuous: repl.continuous, Cancel: true}
	_, err := Do(repl.source.replicationURL(), "POST", repl.source.Cred(), req, nil)
	return err
}

// Returns replication source
func (repl *Replication) Source() *Database {
	return repl.source
}

// Returns replication target
func (repl *Replication) Target() *Database {
	return repl.target
}

// Returns whether replication is running continuously or not
func (repl *Replication) Continuous() bool {
	return repl.continuous
}

func (repl *Replication) SessionID() string {
	return repl.sessionID
}

// Synchronizes two databases by setting up two replications, one from given database
// to target and from target to given database. If the target database does not exist it will be created.
// The target database may be on a different host.
//
// This method may be convenient but note that it is not atomic: Sync means that this method will first
// replicate db to target and then target to db. If the first one fails, both fail. If the first one works but
// the second doesn't, the first one will have executed nonetheless. If the sync has been set up to be continuous,
// the first continuous replication will be cancelled if the second one fails.
func (db *Database) SyncWith(target *Database, continuously bool) (*Sync, error) {
	replA2B, err := db.ReplicateTo(target, continuously)
	if err != nil {
		return nil, err
	}
	replB2A, err := target.ReplicateTo(db, continuously)
	if err != nil {
		replA2B.Cancel()
		return nil, err
	}
	sync := &Sync{replA2B, replB2A}
	return sync, nil
}

// Cancel a continuously running sync
func (sync *Sync) Cancel() error {
	// Call cancel directly on both replications, if replA2B.Cancel() leads to
	// an error we might still be able to cancel replB2A. Errors will be combined later.
	errA2B := sync.replA2B.Cancel()
	errB2A := sync.replB2A.Cancel()
	var err error
	if errA2B != nil || errB2A != nil {
		err = fmt.Errorf("couch: Error cancelling replication, a->b: %v, b->a: %v", errA2B, errB2A)
	}
	return err
}

// Not safe, only used body of replication request
func (db *Database) urlWithCredentials() string {
	result, _ := url.Parse(db.URL())
	result.User = url.UserPassword(db.server.cred.user, db.server.cred.password)
	return result.String()
}

func (db *Database) replicationURL() string {
	return db.server.url + "/_replicate"
}
<commit_msg>Fix bug in case admin party is used<commit_after>package couch

import (
	"fmt"
	"net/url"
)

// TODO add: db.RunningReplications() []Replication
// TODO add: repl.Running()

// A replication from a source to a target
type Replication struct {
	source     *Database
	target     *Database
	continuous bool
	sessionID  string
}

// A bidirectional replication
type Sync struct {
	replA2B *Replication
	replB2A *Replication
}

// CouchDB request for replication
type replRequest struct {
	CreateTarget bool   `json:"create_target"`
	Source       string `json:"source"`
	Target       string `json:"target"`
	Continuous   bool   `json:"continuous"`
	Cancel       bool   `json:"cancel,omitempty"`
}

// CouchDB response to replication request
type replResponse struct {
	Ok            bool   `json:"ok"`
	ReplIDVersion int    `json:"replication_id_version"`
	SessionID     string `json:"session_id"`
	SourceLastSeq int    `json:"source_last_seq"`
}

// Replicates given database to a target database. If the target database
// does not exist it will be created. The target database may be on a different host.
func (db *Database) ReplicateTo(target *Database, continuously bool) (*Replication, error) {
	var resp replResponse
	req := replRequest{CreateTarget: true, Source: db.URL(), Target: target.urlWithCredentials(), Continuous: continuously}
	_, err := Do(db.replicationURL(), "POST", db.Cred(), req, &resp)
	if err != nil {
		return nil, err
	}
	repl := &Replication{source: db, target: target, continuous: continuously, sessionID: resp.SessionID}
	return repl, err
}

// Cancel a continuously running replication
func (repl *Replication) Cancel() error {
	req := replRequest{CreateTarget: true, Source: repl.source.URL(), Target: repl.target.URL(), Continuous: repl.continuous, Cancel: true}
	_, err := Do(repl.source.replicationURL(), "POST", repl.source.Cred(), req, nil)
	return err
}

// Returns replication source
func (repl *Replication) Source() *Database {
	return repl.source
}

// Returns replication target
func (repl *Replication) Target() *Database {
	return repl.target
}

// Returns whether replication is running continuously or not
func (repl *Replication) Continuous() bool {
	return repl.continuous
}

func (repl *Replication) SessionID() string {
	return repl.sessionID
}

// Synchronizes two databases by setting up two replications, one from given database
// to target and from target to given database. If the target database does not exist it will be created.
// The target database may be on a different host.
//
// This method may be convenient but note that it is not atomic: Sync means that this method will first
// replicate db to target and then target to db. If the first one fails, both fail. If the first one works but
// the second doesn't, the first one will have executed nonetheless. If the sync has been set up to be continuous,
// the first continuous replication will be cancelled if the second one fails.
func (db *Database) SyncWith(target *Database, continuously bool) (*Sync, error) {
	replA2B, err := db.ReplicateTo(target, continuously)
	if err != nil {
		return nil, err
	}
	replB2A, err := target.ReplicateTo(db, continuously)
	if err != nil {
		replA2B.Cancel()
		return nil, err
	}
	sync := &Sync{replA2B, replB2A}
	return sync, nil
}

// Cancel a continuously running sync
func (sync *Sync) Cancel() error {
	// Call cancel directly on both replications, if replA2B.Cancel() leads to
	// an error we might still be able to cancel replB2A. Errors will be combined later.
	errA2B := sync.replA2B.Cancel()
	errB2A := sync.replB2A.Cancel()
	var err error
	if errA2B != nil || errB2A != nil {
		err = fmt.Errorf("couch: Error cancelling replication, a->b: %v, b->a: %v", errA2B, errB2A)
	}
	return err
}

// Not safe, only used body of replication request
func (db *Database) urlWithCredentials() string {
	result, _ := url.Parse(db.URL())
	cred := db.Cred()
	if cred != nil {
		result.User = url.UserPassword(db.server.cred.user, db.server.cred.password)
	}
	return result.String()
}

func (db *Database) replicationURL() string {
	return db.server.url + "/_replicate"
}
<|endoftext|>


<commit_before>package ec2

import (
	"fmt"
	"io"
	"launchpad.net/goamz/s3"
	"launchpad.net/juju/go/environs"
	"launchpad.net/juju/go/log"
	"sync"
	"time"
)

// storage implements environs.Storage on
// an ec2.bucket.
type storage struct {
	bucketMutex sync.Mutex
	madeBucket  bool
	bucket      *s3.Bucket
}

// makeBucket makes the environent's control bucket, the
// place where bootstrap information and deployed charms
// are stored. To avoid two round trips on every PUT operation,
// we do this only once for each environ.
func (s *storage) makeBucket() error {
	s.bucketMutex.Lock()
	defer s.bucketMutex.Unlock()
	log.Printf("makeBucket %p, made %v", s, s.madeBucket)
	if s.madeBucket {
		return nil
	}
	// try to make the bucket - PutBucket will succeed if the
	// bucket already exists.
	err := s.bucket.PutBucket(s3.Private)
	if err == nil {
		s.madeBucket = true
	}
	return err
}

func (s *storage) Put(file string, r io.Reader, length int64) error {
	if err := s.makeBucket(); err != nil {
		return fmt.Errorf("cannot make S3 control bucket: %v", err)
	}
	err := s.bucket.PutReader(file, r, length, "binary/octet-stream", s3.Private)
	if err != nil {
		return fmt.Errorf("cannot write file %q to control bucket: %v", file, err)
	}
	return nil
}

func (s *storage) Get(file string) (r io.ReadCloser, err error) {
	for a := shortAttempt.start(); a.next(); {
		r, err = s.bucket.GetReader(file)
		if s3ErrorStatusCode(err) == 404 {
			continue
		}
		return
	}
	return r, maybeNotFound(err)
}

func (s *storage) URL(name string) (string, error) {
	// 10 years should be good enough.
	return s.bucket.SignedURL(name, time.Now().AddDate(1, 0, 0)), nil
}

// s3ErrorStatusCode returns the HTTP status of the S3 request error,
// if it is an error from an S3 operation, or 0 if it was not.
func s3ErrorStatusCode(err error) int {
	if err, _ := err.(*s3.Error); err != nil {
		return err.StatusCode
	}
	return 0
}

func (s *storage) Remove(file string) error {
	err := s.bucket.Del(file)
	// If we can't delete the object because the bucket doesn't
	// exist, then we don't care.
	if s3ErrorStatusCode(err) == 404 {
		return nil
	}
	return err
}

func (s *storage) List(prefix string) ([]string, error) {
	// TODO cope with more than 1000 objects in the bucket.
	resp, err := s.bucket.List(prefix, "", "", 0)
	if err != nil {
		return nil, maybeNotFound(err)
	}
	var names []string
	for _, key := range resp.Contents {
		names = append(names, key.Key)
	}
	return names, nil
}

func (s *storage) deleteAll() error {
	names, err := s.List("")
	if err != nil {
		if _, ok := err.(*environs.NotFoundError); ok {
			return nil
		}
		return err
	}
	// Remove all the objects in parallel so that we incur less round-trips.
	// If we're in danger of having hundreds of objects,
	// we'll want to change this to limit the number
	// of concurrent operations.
	var wg sync.WaitGroup
	wg.Add(len(names))
	errc := make(chan error, len(names))
	for _, name := range names {
		name := name
		go func() {
			if err := s.Remove(name); err != nil {
				errc <- err
			}
			wg.Done()
		}()
	}
	wg.Wait()
	select {
	case err := <-errc:
		return fmt.Errorf("cannot delete all provider state: %v", err)
	default:
	}

	s.bucketMutex.Lock()
	defer s.bucketMutex.Unlock()
	// Even DelBucket fails, it won't harm if we try again - the operation
	// might have succeeded even if we get an error.
	log.Printf("deleteAll %p setting madeBucket to false", s)
	s.madeBucket = false
	return s.bucket.DelBucket()
}

func (e *environ) Storage() environs.Storage {
	return &e.storage
}

func (e *environ) PublicStorage() environs.StorageReader {
	if e.publicStorage == nil {
		return environs.EmptyStorage
	}
	return e.publicStorage
}
<commit_msg>environs/ec2: remove debugging prints<commit_after>package ec2

import (
	"fmt"
	"io"
	"launchpad.net/goamz/s3"
	"launchpad.net/juju/go/environs"
	"launchpad.net/juju/go/log"
	"sync"
	"time"
)

// storage implements environs.Storage on
// an ec2.bucket.
type storage struct {
	bucketMutex sync.Mutex
	madeBucket  bool
	bucket      *s3.Bucket
}

// makeBucket makes the environent's control bucket, the
// place where bootstrap information and deployed charms
// are stored. To avoid two round trips on every PUT operation,
// we do this only once for each environ.
func (s *storage) makeBucket() error {
	s.bucketMutex.Lock()
	defer s.bucketMutex.Unlock()
	if s.madeBucket {
		return nil
	}
	// try to make the bucket - PutBucket will succeed if the
	// bucket already exists.
	err := s.bucket.PutBucket(s3.Private)
	if err == nil {
		s.madeBucket = true
	}
	return err
}

func (s *storage) Put(file string, r io.Reader, length int64) error {
	if err := s.makeBucket(); err != nil {
		return fmt.Errorf("cannot make S3 control bucket: %v", err)
	}
	err := s.bucket.PutReader(file, r, length, "binary/octet-stream", s3.Private)
	if err != nil {
		return fmt.Errorf("cannot write file %q to control bucket: %v", file, err)
	}
	return nil
}

func (s *storage) Get(file string) (r io.ReadCloser, err error) {
	for a := shortAttempt.start(); a.next(); {
		r, err = s.bucket.GetReader(file)
		if s3ErrorStatusCode(err) == 404 {
			continue
		}
		return
	}
	return r, maybeNotFound(err)
}

func (s *storage) URL(name string) (string, error) {
	// 10 years should be good enough.
	return s.bucket.SignedURL(name, time.Now().AddDate(1, 0, 0)), nil
}

// s3ErrorStatusCode returns the HTTP status of the S3 request error,
// if it is an error from an S3 operation, or 0 if it was not.
func s3ErrorStatusCode(err error) int {
	if err, _ := err.(*s3.Error); err != nil {
		return err.StatusCode
	}
	return 0
}

func (s *storage) Remove(file string) error {
	err := s.bucket.Del(file)
	// If we can't delete the object because the bucket doesn't
	// exist, then we don't care.
	if s3ErrorStatusCode(err) == 404 {
		return nil
	}
	return err
}

func (s *storage) List(prefix string) ([]string, error) {
	// TODO cope with more than 1000 objects in the bucket.
	resp, err := s.bucket.List(prefix, "", "", 0)
	if err != nil {
		return nil, maybeNotFound(err)
	}
	var names []string
	for _, key := range resp.Contents {
		names = append(names, key.Key)
	}
	return names, nil
}

func (s *storage) deleteAll() error {
	names, err := s.List("")
	if err != nil {
		if _, ok := err.(*environs.NotFoundError); ok {
			return nil
		}
		return err
	}
	// Remove all the objects in parallel so that we incur less round-trips.
	// If we're in danger of having hundreds of objects,
	// we'll want to change this to limit the number
	// of concurrent operations.
	var wg sync.WaitGroup
	wg.Add(len(names))
	errc := make(chan error, len(names))
	for _, name := range names {
		name := name
		go func() {
			if err := s.Remove(name); err != nil {
				errc <- err
			}
			wg.Done()
		}()
	}
	wg.Wait()
	select {
	case err := <-errc:
		return fmt.Errorf("cannot delete all provider state: %v", err)
	default:
	}

	s.bucketMutex.Lock()
	defer s.bucketMutex.Unlock()
	// Even DelBucket fails, it won't harm if we try again - the operation
	// might have succeeded even if we get an error.
	s.madeBucket = false
	return s.bucket.DelBucket()
}

func (e *environ) Storage() environs.Storage {
	return &e.storage
}

func (e *environ) PublicStorage() environs.StorageReader {
	if e.publicStorage == nil {
		return environs.EmptyStorage
	}
	return e.publicStorage
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package krusty

import (
	"sigs.k8s.io/kustomize/api/konfig"
	"sigs.k8s.io/kustomize/api/types"
)

// Options holds high-level kustomize configuration options,
// e.g. are plugins enabled, should the loader be restricted
// to the kustomization root, etc.
type Options struct {
	// When true, sort the resources before emitting them,
	// per a particular sort order.  When false, don't do the
	// sort, and instead respect the depth-first resource input
	// order as specified by the kustomization file(s).
	DoLegacyResourceSort bool

	// When true, a label
	//     app.kubernetes.io/managed-by: kustomize-<version>
	// is added to all the resources in the build out.
	AddManagedbyLabel bool

	// Restrictions on what can be loaded from the file system.
	// See type definition.
	LoadRestrictions types.LoadRestrictions

	// Create an inventory object for pruning.
	DoPrune bool

	// Options related to kustomize plugins.
	PluginConfig *types.PluginConfig

	// When true, use kyaml/ packages to manipulate KRM yaml.
	// When false, use k8sdeps/ instead (uses k8s.io/api* packages).
	UseKyaml bool

	// When true, allow name and kind changing via a patch
	// When false, patch name/kind don't overwrite target name/kind
	AllowResourceIdChanges bool
}

// MakeDefaultOptions returns a default instance of Options.
// TODO(#3343): UseKyaml: konfig.FlagEnableKyamlDefaultValue
func MakeDefaultOptions() *Options {
	return &Options{
		DoLegacyResourceSort:   false,
		AddManagedbyLabel:      false,
		LoadRestrictions:       types.LoadRestrictionsRootOnly,
		DoPrune:                false,
		PluginConfig:           konfig.DisabledPluginConfig(),
		UseKyaml:               false,
		AllowResourceIdChanges: false,
	}
}

func (o Options) IfApiMachineryElseKyaml(s1, s2 string) string {
	if !o.UseKyaml {
		return s1
	}
	return s2
}
<commit_msg>Close 3343<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package krusty

import (
	"sigs.k8s.io/kustomize/api/konfig"
	"sigs.k8s.io/kustomize/api/types"
)

// Options holds high-level kustomize configuration options,
// e.g. are plugins enabled, should the loader be restricted
// to the kustomization root, etc.
type Options struct {
	// When true, sort the resources before emitting them,
	// per a particular sort order.  When false, don't do the
	// sort, and instead respect the depth-first resource input
	// order as specified by the kustomization file(s).
	DoLegacyResourceSort bool

	// When true, a label
	//     app.kubernetes.io/managed-by: kustomize-<version>
	// is added to all the resources in the build out.
	AddManagedbyLabel bool

	// Restrictions on what can be loaded from the file system.
	// See type definition.
	LoadRestrictions types.LoadRestrictions

	// Create an inventory object for pruning.
	DoPrune bool

	// Options related to kustomize plugins.
	PluginConfig *types.PluginConfig

	// When true, use kyaml/ packages to manipulate KRM yaml.
	// When false, use k8sdeps/ instead (uses k8s.io/api* packages).
	UseKyaml bool

	// When true, allow name and kind changing via a patch
	// When false, patch name/kind don't overwrite target name/kind
	AllowResourceIdChanges bool
}

// MakeDefaultOptions returns a default instance of Options.
func MakeDefaultOptions() *Options {
	return &Options{
		DoLegacyResourceSort:   false,
		AddManagedbyLabel:      false,
		LoadRestrictions:       types.LoadRestrictionsRootOnly,
		DoPrune:                false,
		PluginConfig:           konfig.DisabledPluginConfig(),
		UseKyaml:               konfig.FlagEnableKyamlDefaultValue,
		AllowResourceIdChanges: false,
	}
}

func (o Options) IfApiMachineryElseKyaml(s1, s2 string) string {
	if !o.UseKyaml {
		return s1
	}
	return s2
}
<|endoftext|>


<commit_before>// Copyright 2013 Ivan Danyliuk
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package xml

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gorilla/rpc"
)

// ----------------------------------------------------------------------------
// Codec
// ----------------------------------------------------------------------------

// NewCodec returns a new XML-RPC Codec.
func NewCodec() *Codec {
	return &Codec{}
}

// Codec creates a CodecRequest to process each request.
type Codec struct {
}

// NewRequest returns a CodecRequest.
func (c *Codec) NewRequest(r *http.Request) rpc.CodecRequest {
	return newCodecRequest(r)
}

// ----------------------------------------------------------------------------
// CodecRequest
// ----------------------------------------------------------------------------

type ServerRequest struct {
	Name   xml.Name `xml:"methodCall"`
	Method string   `xml:"methodName"`
	rawxml string
}

// CodecRequest decodes and encodes a single request.
type CodecRequest struct {
	request *ServerRequest
	err     error
}

func newCodecRequest(r *http.Request) rpc.CodecRequest {
	rawxml, err := ioutil.ReadAll(r.Body)
	var request ServerRequest
	err = xml.Unmarshal(rawxml, &request)
	request.rawxml = string(rawxml)

	r.Body.Close()
	return &CodecRequest{request: &request, err: err}
}

// Method returns the RPC method for the current request.
//
// The method uses a dotted notation as in "Service.Method".
func (c *CodecRequest) Method() (string, error) {
	if c.err == nil {
		return c.request.Method, nil
	}
	return "", c.err
}

// ReadRequest fills the request object for the RPC method.
//
// args is the pointer to the Service.Args structure
// it gets populated from temporary XML structure
func (c *CodecRequest) ReadRequest(args interface{}) error {
	c.err = xml2RPC(c.request.rawxml, args)
	return nil
}

// WriteResponse encodes the response and writes it to the ResponseWriter.
//
// response is the pointer to the Service.Response structure
// it gets encoded into the XML-RPC xml string
func (c *CodecRequest) WriteResponse(w http.ResponseWriter, response interface{}, methodErr error) error {
	var xmlstr string
	if c.err != nil {
		var fault Fault
		switch c.err.(type) {
		case Fault:
			fault = c.err.(Fault)
		default:
			fault = FaultApplicationError
			fault.String += fmt.Sprintf(": %v", c.err)
		}
		xmlstr = fault2XML(fault)
	} else {
		xmlstr, _ = rpcResponse2XML(response)
	}

	w.Header().Set("Content-Type", "text/xml; charset=utf-8")
	w.Write([]byte(xmlstr))
	return nil
}
<commit_msg>Allow registering method aliases<commit_after>// Copyright 2013 Ivan Danyliuk
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package xml

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gorilla/rpc"
)

// ----------------------------------------------------------------------------
// Codec
// ----------------------------------------------------------------------------

// NewCodec returns a new XML-RPC Codec.
func NewCodec() *Codec {
	return &Codec{
		aliases: make(map[string]string),
	}
}

// Codec creates a CodecRequest to process each request.
type Codec struct {
	aliases map[string]string
}

// RegisterAlias creates a method alias
func (c *Codec) RegisterAlias(alias, method string) {
	c.aliases[alias] = method
}

// NewRequest returns a CodecRequest.
func (c *Codec) NewRequest(r *http.Request) rpc.CodecRequest {
	return c.newCodecRequest(r)
}

// ----------------------------------------------------------------------------
// CodecRequest
// ----------------------------------------------------------------------------

type ServerRequest struct {
	Name   xml.Name `xml:"methodCall"`
	Method string   `xml:"methodName"`
	rawxml string
}

// CodecRequest decodes and encodes a single request.
type CodecRequest struct {
	request *ServerRequest
	err     error
}

func (c *Codec) newCodecRequest(r *http.Request) rpc.CodecRequest {
	rawxml, err := ioutil.ReadAll(r.Body)
	var request ServerRequest
	err = xml.Unmarshal(rawxml, &request)
	request.rawxml = string(rawxml)

	if method, ok := c.aliases[request.Method]; ok {
		request.Method = method
	}

	r.Body.Close()
	return &CodecRequest{request: &request, err: err}
}

// Method returns the RPC method for the current request.
//
// The method uses a dotted notation as in "Service.Method".
func (c *CodecRequest) Method() (string, error) {
	if c.err == nil {
		return c.request.Method, nil
	}
	return "", c.err
}

// ReadRequest fills the request object for the RPC method.
//
// args is the pointer to the Service.Args structure
// it gets populated from temporary XML structure
func (c *CodecRequest) ReadRequest(args interface{}) error {
	c.err = xml2RPC(c.request.rawxml, args)
	return nil
}

// WriteResponse encodes the response and writes it to the ResponseWriter.
//
// response is the pointer to the Service.Response structure
// it gets encoded into the XML-RPC xml string
func (c *CodecRequest) WriteResponse(w http.ResponseWriter, response interface{}, methodErr error) error {
	var xmlstr string
	if c.err != nil {
		var fault Fault
		switch c.err.(type) {
		case Fault:
			fault = c.err.(Fault)
		default:
			fault = FaultApplicationError
			fault.String += fmt.Sprintf(": %v", c.err)
		}
		xmlstr = fault2XML(fault)
	} else {
		xmlstr, _ = rpcResponse2XML(response)
	}

	w.Header().Set("Content-Type", "text/xml; charset=utf-8")
	w.Write([]byte(xmlstr))
	return nil
}
<|endoftext|>


<commit_before>package node_types_examples
import (
	"testing"
	//"strconv"
	//"reflect"
	"fmt"
//	"encoding/json"
	"github.com/h4ck3rm1k3/gogccintro/tree"
	"github.com/h4ck3rm1k3/gogccintro/models"
	//"io/ioutil"
	//"os"
)

func CamelCase(s string) string {
	var r []byte
	var i = 1

	// first letterx
	c2 := s[0]
	c2 ^= ' ' // Make it a capital letter.
	r = append(r, c2)

	for ; i < len(s); i++ {
		c := s[i]
		if c == '_' {
			c2 := s[i+1]
			c2 ^= ' ' // Make it a capital letter.
			i = i +1
			r = append(r, c2)
		} else {
			r = append(r, c)
		}
	}
	return string(r[:])
}

type Stats struct {

}

// generic instance of a type
type NodeFieldInstance interface {
}

type NodeFieldInstanceString struct {
}

type NodeFieldInstanceRef struct {
}

type FieldTypeGeneric interface {
}

type FieldType struct {
	// sample values
	// used by type
	// generic field vs field in type
	// domain of field (cardinality)
	// range of field (cardinality)
	// domain to range (cardinality matrix!)
}

type NodeTypeInstance struct {
	fields_outgoing map[string] NodeFieldInstance // outgoing fields
	fields_incoming [] NodeFieldInstance // array of incoming objects
}

type NodeType struct {
	fields_outgoing map[string] *FieldTypeGeneric // outgoing fields
	fields_incoming map[string] *FieldTypeGeneric // incoming fields
	instances map[int] *NodeTypeInstance
	// cardinality of this node type
	// referenced by other nodes, contained by one?
	// references other nodes
}

type NodeInstanceGeneric interface {

}

type NodeTypeGeneric interface {
	StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric);
}

type TReceiver struct {
	node_types map[string] NodeTypeGeneric
	node_types_generic map[string] NodeTypeGeneric
	ids   map[int] NodeInstanceGeneric// instances
}

func (r* TReceiver) StartGraph(){
	r.node_types_generic = make(map[string] NodeTypeGeneric)
	r.ids = make(map[int] NodeInstanceGeneric)

	r.node_types =
		map[string] NodeTypeGeneric {
		"integer_type":&NodeTypeIntegerType{},
		"type_decl":&NodeTypeTypeDecl{},
		"array_type":&NodeTypeArrayType{},
		"identifier_node":&NodeTypeIdentifierNode{
			names: make(map[string] *NodeInstanceIdentifierNode),// instances
		},
		"pointer_type":&NodeTypePointerType{},
		"integer_cst":&NodeTypeIntegerCst{},
		"union_type":&NodeTypeUnionType{},
		"record_type":&NodeTypeRecordType{},
		"field_decl":&NodeTypeFieldDecl{},
		"tree_list":&NodeTypeTreeList{},
		"function_decl":&NodeTypeFunctionDecl{},
		"void_type":&NodeTypeVoidType{},
		"function_type":&NodeTypeFunctionType{},
	}
}

type NodeTypeArrayType struct {}
type NodeTypeFieldDecl struct {}
type NodeTypeFunctionDecl struct {}
type NodeTypeFunctionType struct {}

type NodeTypeIdentifierNode struct {
	//String string
	names map[string] *NodeInstanceIdentifierNode// instances

}

type NodeInstanceIdentifierNode struct {
	String string
	NodeID int
}

type NodeTypeIntegerCst struct {}
type NodeTypeIntegerType struct {}
type NodeTypePointerType struct {}
type NodeTypeRecordType struct {}
type NodeTypeTreeList struct {}
type NodeTypeTypeDecl struct {}
type NodeTypeUnionType struct {}
type NodeTypeVoidType struct {}

func (t* NodeTypeArrayType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeFieldDecl) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeFunctionDecl) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeFunctionType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}

func (t* NodeTypeIdentifierNode) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	o:=NodeInstanceIdentifierNode{
		String :v.AttrsString,
		NodeID: v.NodeID,
	}
	t.names[v.AttrsString]=&o
	return &o
}

func (t* NodeTypeIntegerCst) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeIntegerType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypePointerType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeRecordType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeTreeList) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeTypeDecl) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeUnionType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeVoidType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}

func (r* TReceiver) StartNode(v * models.GccTuParserNode){
	//fmt.Printf("node id %d %s\n", v.NodeID,v.NodeType)

	o := r.node_types[v.NodeType].StartNode(v)

	r.ids[v.NodeID]=o

	if _, ok := r.node_types_generic[v.NodeType]; ok {
		//fmt.Printf("node type %s %s\n",v.NodeType, val)

	}else {
		c := fmt.Sprintf("NodeType%s",CamelCase(v.NodeType))
		//fmt.Printf("node type not %s %s -> %s\n",v.NodeType, val, c)
		//fmt.Printf("type %s struct {}\n",c)
		fmt.Printf("\"%s\":%s,\n",v.NodeType,c)
		//r.node_types[v.NodeType]=NodeType{}
	}

}

func (r *TReceiver)	ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){
	fmt.Printf("\tField %d/%s -> %s -> %d/%s\n", n.NodeID, n.NodeType, name, o.NodeID, o.NodeType)
}

func (r *TReceiver)	ReferenceAttribute(n * models.GccTuParserNode, name string, value string){
	fmt.Printf("\tField %d %s -> %s : %v\n", n.NodeID, n.NodeType,name,value)
}

func (r *TReceiver)	EndNode(n * models.GccTuParserNode){}
func (r* TReceiver)	EndGraph(){

	fmt.Printf("End%v\n", r )
}

func TestLoadType(*testing.T){
	//fmt.Printf("test load")
	const filename = "funct_decl_key_get_conv_rpc_auth.json"
	treemap := tree.NewTreeMapFromFile(filename)
	r := &TReceiver{}
	treemap.ResolveReferences(r)

}
<commit_msg>adding ref<commit_after>package node_types_examples
import (
	"testing"
	//"strconv"
	//"reflect"
	"fmt"
//	"encoding/json"
	"github.com/h4ck3rm1k3/gogccintro/tree"
	"github.com/h4ck3rm1k3/gogccintro/models"
	//"io/ioutil"
	//"os"
)

func CamelCase(s string) string {
	var r []byte
	var i = 1

	// first letterx
	c2 := s[0]
	c2 ^= ' ' // Make it a capital letter.
	r = append(r, c2)

	for ; i < len(s); i++ {
		c := s[i]
		if c == '_' {
			c2 := s[i+1]
			c2 ^= ' ' // Make it a capital letter.
			i = i +1
			r = append(r, c2)
		} else {
			r = append(r, c)
		}
	}
	return string(r[:])
}

type Stats struct {

}

// generic instance of a type
type NodeFieldInstance interface {
}

type NodeFieldInstanceString struct {
}

type NodeFieldInstanceRef struct {
}

type FieldTypeGeneric interface {
}

type FieldType struct {
	// sample values
	// used by type
	// generic field vs field in type
	// domain of field (cardinality)
	// range of field (cardinality)
	// domain to range (cardinality matrix!)
}

type NodeTypeInstance struct {
	fields_outgoing map[string] NodeFieldInstance // outgoing fields
	fields_incoming [] NodeFieldInstance // array of incoming objects
}

type NodeType struct {
	fields_outgoing map[string] *FieldTypeGeneric // outgoing fields
	fields_incoming map[string] *FieldTypeGeneric // incoming fields
	instances map[int] *NodeTypeInstance
	// cardinality of this node type
	// referenced by other nodes, contained by one?
	// references other nodes
}

type NodeInstanceGeneric interface {

}

type NodeTypeGeneric interface {
	StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric)

	// incoming
	ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode)

	// outgoing
	ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode)

}

type TReceiver struct {
	node_types map[string] NodeTypeGeneric
	node_types_generic map[string] NodeTypeGeneric
	ids   map[int] NodeInstanceGeneric// instances
}

func (r* TReceiver) StartGraph(){
	r.node_types_generic = make(map[string] NodeTypeGeneric)
	r.ids = make(map[int] NodeInstanceGeneric)

	r.node_types =
		map[string] NodeTypeGeneric {
		"integer_type":&NodeTypeIntegerType{},
		"type_decl":&NodeTypeTypeDecl{},
		"array_type":&NodeTypeArrayType{},
		"identifier_node":&NodeTypeIdentifierNode{
			names: make(map[string] *NodeInstanceIdentifierNode),// instances
		},
		"pointer_type":&NodeTypePointerType{},
		"integer_cst":&NodeTypeIntegerCst{},
		"union_type":&NodeTypeUnionType{},
		"record_type":&NodeTypeRecordType{},
		"field_decl":&NodeTypeFieldDecl{},
		"tree_list":&NodeTypeTreeList{},
		"function_decl":&NodeTypeFunctionDecl{},
		"void_type":&NodeTypeVoidType{},
		"function_type":&NodeTypeFunctionType{},
	}
}

type NamedObjectInterface interface {}
type NodeInstanceIdentifierNode struct {
	String string
	NodeID int
	Named  NamedObjectInterface // what object is named?
}

///////////////////////////////

type NodeTypeArrayType struct {}
type NodeTypeFieldDecl struct {}
type NodeTypeFunctionDecl struct {}
type NodeTypeFunctionType struct {}
type NodeTypeIdentifierNode struct {
	names map[string] *NodeInstanceIdentifierNode// instances
}
type NodeTypeIntegerCst struct {}
type NodeTypeIntegerType struct {}
type NodeTypePointerType struct {}
type NodeTypeRecordType struct {}
type NodeTypeTreeList struct {}
type NodeTypeTypeDecl struct {}
type NodeTypeUnionType struct {}
type NodeTypeVoidType struct {}

///////////////////////////////////

func (t* NodeTypeArrayType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeFieldDecl) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeFunctionDecl) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeFunctionType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeIdentifierNode) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeIntegerCst) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeIntegerType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypePointerType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeRecordType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeTreeList) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeTypeDecl) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeUnionType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeVoidType) ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}

func (t* NodeTypeArrayType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeFieldDecl) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeFunctionDecl) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeFunctionType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeIdentifierNode) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeIntegerCst) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeIntegerType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypePointerType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeRecordType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeTreeList) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeTypeDecl) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeUnionType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}
func (t* NodeTypeVoidType) ReferencedNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){}

func (t* NodeTypeArrayType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeFieldDecl) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeFunctionDecl) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeFunctionType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}

func (t* NodeTypeIdentifierNode) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	o:=NodeInstanceIdentifierNode{
		String :v.AttrsString,
		NodeID: v.NodeID,
	}
	t.names[v.AttrsString]=&o
	return &o
}

func (t* NodeTypeIntegerCst) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeIntegerType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypePointerType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeRecordType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeTreeList) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeTypeDecl) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeUnionType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}
func (t* NodeTypeVoidType) StartNode(v * models.GccTuParserNode)(NodeInstanceGeneric){
	return nil
}

func (r* TReceiver) StartNode(v * models.GccTuParserNode){
	//fmt.Printf("node id %d %s\n", v.NodeID,v.NodeType)

	o := r.node_types[v.NodeType].StartNode(v)

	r.ids[v.NodeID]=o

	if _, ok := r.node_types_generic[v.NodeType]; ok {
		//fmt.Printf("node type %s %s\n",v.NodeType, val)

	}else {
		c := fmt.Sprintf("NodeType%s",CamelCase(v.NodeType))
		//fmt.Printf("node type not %s %s -> %s\n",v.NodeType, val, c)
		//fmt.Printf("type %s struct {}\n",c)
		fmt.Printf("\"%s\":%s,\n",v.NodeType,c)
		//r.node_types[v.NodeType]=NodeType{}
	}

}

func (r *TReceiver)	ReferenceNode(n * models.GccTuParserNode, name string, o * models.GccTuParserNode){
	fmt.Printf("\tField %d/%s -> %s -> %d/%s\n", n.NodeID, n.NodeType, name, o.NodeID, o.NodeType)

	// look up the o.NodeType and
	r.node_types[n.NodeType].ReferenceNode(n,name,o)
	r.node_types[o.NodeType].ReferencedNode(n,name,o)
}

func (r *TReceiver)	ReferenceAttribute(n * models.GccTuParserNode, name string, value string){
	fmt.Printf("\tField %d %s -> %s : %v\n", n.NodeID, n.NodeType,name,value)
}

func (r *TReceiver)	EndNode(n * models.GccTuParserNode){}
func (r* TReceiver)	EndGraph(){

	fmt.Printf("End%v\n", r )
	fmt.Printf("End%v\n", r.node_types )
	for i,x := range r.node_types {
		fmt.Printf("End: %v -> %v\n", i, x )
	}

}

func TestLoadType(*testing.T){
	//fmt.Printf("test load")
	const filename = "funct_decl_key_get_conv_rpc_auth.json"
	treemap := tree.NewTreeMapFromFile(filename)
	r := &TReceiver{}
	treemap.ResolveReferences(r)

}
<|endoftext|>


<commit_before>package response

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

	log "github.com/sirupsen/logrus"
)

type Error interface {
	//This could have just been `Code`, but that would make it accidentally share an interface with gocql and lead to nonsense HTTP codes
	//See https://github.com/grafana/metrictank/issues/1678
	HTTPStatusCode() int
	Error() string
}

type ErrorResp struct {
	code int
	err  string
}

func WrapError(e error) *ErrorResp {
	if err, ok := e.(*ErrorResp); ok {
		err.ValidateAndFixCode()
		return err
	}
	resp := &ErrorResp{
		err:  e.Error(),
		code: http.StatusInternalServerError,
	}
	if _, ok := e.(Error); ok {
		resp.code = e.(Error).HTTPStatusCode()
	}

	resp.ValidateAndFixCode()
	return resp
}

type TagDBError struct {
	Error string `json:"error"`
}

// graphite's http tagdb client requires a specific error format
func WrapErrorForTagDB(e error) *ErrorResp {
	b, err := json.Marshal(TagDBError{Error: e.Error()})
	if err != nil {
		return &ErrorResp{
			err:  "{\"error\": \"failed to encode error message\"}",
			code: http.StatusInternalServerError,
		}
	}

	resp := &ErrorResp{
		err:  string(b),
		code: http.StatusInternalServerError,
	}

	if _, ok := e.(Error); ok {
		resp.code = e.(Error).HTTPStatusCode()
	}

	resp.ValidateAndFixCode()
	return resp
}

func NewError(code int, err string) *ErrorResp {
	return &ErrorResp{
		code: code,
		err:  err,
	}
}

func Errorf(code int, format string, a ...interface{}) *ErrorResp {
	return &ErrorResp{
		code: code,
		err:  fmt.Sprintf(format, a...),
	}
}

func (r *ErrorResp) Error() string {
	return r.err
}

func (r *ErrorResp) HTTPStatusCode() int {
	return r.code
}

func (r *ErrorResp) Code() int {
	return r.code
}

func (r *ErrorResp) Close() {
	return
}

func (r *ErrorResp) Body() ([]byte, error) {
	return []byte(r.err), nil
}

func (r *ErrorResp) Headers() (headers map[string]string) {
	headers = map[string]string{"content-type": "text/plain"}
	return headers
}

func (r *ErrorResp) ValidateAndFixCode() {
	// 599 is max HTTP status code
	if r.code > 599 {
		log.Warnf("Encountered invalid HTTP status code %d, printing stack", r.code)
		debug.PrintStack()
		r.code = http.StatusInternalServerError
	}
}

var RequestCanceledErr = NewError(499, "request canceled")
<commit_msg>Remove ErrorResp.ValidateAndFixCode now that it is no longer necessary.<commit_after>package response

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

type Error interface {
	//This could have just been `Code`, but that would make it accidentally share an interface with gocql and lead to nonsense HTTP codes
	//See https://github.com/grafana/metrictank/issues/1678
	HTTPStatusCode() int
	Error() string
}

type ErrorResp struct {
	code int
	err  string
}

func WrapError(e error) *ErrorResp {
	if err, ok := e.(*ErrorResp); ok {
		return err
	}
	resp := &ErrorResp{
		err:  e.Error(),
		code: http.StatusInternalServerError,
	}
	if _, ok := e.(Error); ok {
		resp.code = e.(Error).HTTPStatusCode()
	}
	return resp
}

type TagDBError struct {
	Error string `json:"error"`
}

// graphite's http tagdb client requires a specific error format
func WrapErrorForTagDB(e error) *ErrorResp {
	b, err := json.Marshal(TagDBError{Error: e.Error()})
	if err != nil {
		return &ErrorResp{
			err:  "{\"error\": \"failed to encode error message\"}",
			code: http.StatusInternalServerError,
		}
	}

	resp := &ErrorResp{
		err:  string(b),
		code: http.StatusInternalServerError,
	}

	if _, ok := e.(Error); ok {
		resp.code = e.(Error).HTTPStatusCode()
	}
	return resp
}

func NewError(code int, err string) *ErrorResp {
	return &ErrorResp{
		code: code,
		err:  err,
	}
}

func Errorf(code int, format string, a ...interface{}) *ErrorResp {
	return &ErrorResp{
		code: code,
		err:  fmt.Sprintf(format, a...),
	}
}

func (r *ErrorResp) Error() string {
	return r.err
}

func (r *ErrorResp) HTTPStatusCode() int {
	return r.code
}

func (r *ErrorResp) Code() int {
	return r.code
}

func (r *ErrorResp) Close() {
	return
}

func (r *ErrorResp) Body() ([]byte, error) {
	return []byte(r.err), nil
}

func (r *ErrorResp) Headers() (headers map[string]string) {
	headers = map[string]string{"content-type": "text/plain"}
	return headers
}

var RequestCanceledErr = NewError(499, "request canceled")
<|endoftext|>


<commit_before>package harvey

import (
	"crypto/sha1"

	"io"

	"bldy.build/build"
)

type Move struct {
	Name         string            `move:"name"`
	Dependencies []string          `move:"deps"`
	Exports      map[string]string `move:"installs"`
}

func (m *Move) Hash() []byte {

	h := sha1.New()

	io.WriteString(h, m.Name)
	return h.Sum(nil)
}

func (m *Move) Build(c *build.Context) error {

	return nil
}

func (m *Move) Installs() map[string]string {
	return m.Exports
}

func (m *Move) GetName() string {
	return m.Name
}
func (m *Move) GetDependencies() []string {
	return m.Dependencies
}
<commit_msg>harvey/targets: use expand for exports in move<commit_after>package harvey

import (
	"crypto/sha1"

	"io"

	"bldy.build/build"
)

type Move struct {
	Name         string            `move:"name"`
	Dependencies []string          `move:"deps"`
	Exports      map[string]string `move:"installs" build:"expand"`
}

func (m *Move) Hash() []byte {
	h := sha1.New()
	io.WriteString(h, m.Name)
	return h.Sum(nil)
}

func (m *Move) Build(c *build.Context) error {
	return nil
}

func (m *Move) Installs() map[string]string {
	return m.Exports
}

func (m *Move) GetName() string {
	return m.Name
}
func (m *Move) GetDependencies() []string {
	return m.Dependencies
}
<|endoftext|>


<commit_before>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.1.24"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<commit_msg>functions: 0.1.25 release [skip ci]<commit_after>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.1.25"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<|endoftext|>