<commit_before>/*
Copyright 2019 The Vitess Authors.

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

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

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

package sqlparser

import (
	querypb "vitess.io/vitess/go/vt/proto/query"
	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"
)

// PrepareAST will normalize the query
func PrepareAST(in Statement, bindVars map[string]*querypb.BindVariable, prefix string) (*RewriteASTResult, error) {
	Normalize(in, bindVars, prefix)
	return RewriteAST(in)
}

// RewriteAST rewrites the whole AST, replacing function calls and adding column aliases to queries
func RewriteAST(in Statement) (*RewriteASTResult, error) {
	er := new(expressionRewriter)
	Rewrite(in, er.goingDown, er.comingUp)

	return &RewriteASTResult{
		AST:              in,
		NeedLastInsertID: er.lastInsertID,
		NeedDatabase:     er.database,
	}, nil
}

// RewriteASTResult contains the rewritten ast and meta information about it
type RewriteASTResult struct {
	AST              Statement
	NeedLastInsertID bool
	NeedDatabase     bool
}

type expressionRewriter struct {
	lastInsertID, database bool
	err                    error
	aliases                []*AliasedExpr
}

func (er *expressionRewriter) comingUp(cursor *Cursor) bool {
	if er.err != nil {
		return false
	}

	n := len(er.aliases) - 1
	if n >= 0 {
		// if we encounter the last alias when coming up, we'll pop it from the stack
		topOfStack := er.aliases[n]
		if cursor.Node() == topOfStack {
			er.aliases = er.aliases[:n]
		}
	}

	return true
}

// walks the stack of seen AliasedExpr and adds column aliases where there isn't any already
func (er *expressionRewriter) addAliasIfNeeded() {
	idents := make([]ColIdent, len(er.aliases))
	for i, node := range er.aliases {
		if node.As.IsEmpty() {
			buf := NewTrackedBuffer(nil)
			node.Expr.Format(buf)
			idents[i] = NewColIdent(buf.String())
		} else {
			idents[i] = node.As
		}
	}
	for i, node := range er.aliases {
		node.As = idents[i]
	}
}

const (
	//LastInsertIDName is a reserved bind var name for last_insert_id()
	LastInsertIDName = "__lastInsertId"
	//DBVarName is a reserved bind var name for database()
	DBVarName = "__vtdbname"
)

func (er *expressionRewriter) goingDown(cursor *Cursor) bool {
	switch node := cursor.Node().(type) {
	case *AliasedExpr:
		er.aliases = append(er.aliases, node)

	case *FuncExpr:
		switch {
		case node.Name.EqualString("last_insert_id"):
			if len(node.Exprs) > 0 {
				er.err = vterrors.New(vtrpc.Code_UNIMPLEMENTED, "Argument to LAST_INSERT_ID() not supported")
			} else {
				er.addAliasIfNeeded()
				cursor.Replace(bindVarExpression(LastInsertIDName))
				er.lastInsertID = true
			}
		case node.Name.EqualString("database"):
			if len(node.Exprs) > 0 {
				er.err = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "Syntax error. DATABASE() takes no arguments")
			} else {
				er.addAliasIfNeeded()
				cursor.Replace(bindVarExpression(DBVarName))
				er.database = true
			}
		}
	}
	return true
}

func (er *expressionRewriter) didAnythingChange() bool {
	return er.database || er.lastInsertID
}

func bindVarExpression(name string) *SQLVal {
	return NewValArg([]byte(":" + name))
}
<commit_msg>Simplified expression rewriting<commit_after>/*
Copyright 2019 The Vitess Authors.

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

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

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

package sqlparser

import (
	"vitess.io/vitess/go/vt/log"
	querypb "vitess.io/vitess/go/vt/proto/query"
	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"
)

// PrepareAST will normalize the query
func PrepareAST(in Statement, bindVars map[string]*querypb.BindVariable, prefix string) (*RewriteASTResult, error) {
	Normalize(in, bindVars, prefix)
	return RewriteAST(in)
}

// RewriteAST rewrites the whole AST, replacing function calls and adding column aliases to queries
func RewriteAST(in Statement) (*RewriteASTResult, error) {
	er := new(expressionRewriter)
	Rewrite(in, er.goingDown, nil)

	return &RewriteASTResult{
		AST:              in,
		NeedLastInsertID: er.lastInsertID,
		NeedDatabase:     er.database,
	}, nil
}

// RewriteASTResult contains the rewritten ast and meta information about it
type RewriteASTResult struct {
	AST              Statement
	NeedLastInsertID bool
	NeedDatabase     bool
}

type expressionRewriter struct {
	lastInsertID, database bool
	err                    error
}

const (
	//LastInsertIDName is a reserved bind var name for last_insert_id()
	LastInsertIDName = "__lastInsertId"
	//DBVarName is a reserved bind var name for database()
	DBVarName = "__vtdbname"
)

func (er *expressionRewriter) goingDown(cursor *Cursor) bool {
	switch node := cursor.Node().(type) {
	case *AliasedExpr:
		if node.As.IsEmpty() {
			buf := NewTrackedBuffer(nil)
			node.Expr.Format(buf)
			inner := new(expressionRewriter)
			tmp := Rewrite(node.Expr, inner.goingDown, nil)
			newExpr, ok := tmp.(Expr)
			if !ok {
				log.Errorf("failed to rewrite AST. function expected to return Expr returned a %s", String(tmp))
				return false
			}
			node.Expr = newExpr
			er.database = er.database || inner.database
			er.lastInsertID = er.lastInsertID || inner.lastInsertID
			if inner.didAnythingChange() {
				node.As = NewColIdent(buf.String())
			}
			return false
		}

	case *FuncExpr:
		switch {
		case node.Name.EqualString("last_insert_id"):
			if len(node.Exprs) > 0 {
				er.err = vterrors.New(vtrpc.Code_UNIMPLEMENTED, "Argument to LAST_INSERT_ID() not supported")
			} else {
				cursor.Replace(bindVarExpression(LastInsertIDName))
				er.lastInsertID = true
			}
		case node.Name.EqualString("database"):
			if len(node.Exprs) > 0 {
				er.err = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "Syntax error. DATABASE() takes no arguments")
			} else {
				cursor.Replace(bindVarExpression(DBVarName))
				er.database = true
			}
		}
	}
	return true
}

func (er *expressionRewriter) didAnythingChange() bool {
	return er.database || er.lastInsertID
}

func bindVarExpression(name string) *SQLVal {
	return NewValArg([]byte(":" + name))
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.121"
<commit_msg>functions: 0.3.122 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.122"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.551"
<commit_msg>fnserver: 0.3.552 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.552"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.441"
<commit_msg>fnserver: 0.3.442 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.442"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.386"
<commit_msg>fnserver: 0.3.387 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.387"
<|endoftext|>


<commit_before>package main

import "testing"

type Case struct {
	m   [][]int
	sum int
}

func TestCheckSum(t *testing.T) {
	cases := []Case{
		Case{
			[][]int{
				{5, 1, 9, 5},
				{7, 5, 3},
				{2, 4, 6, 8},
			},
			18,
		},
		Case{
			[][]int{
				{},
				{7, 5, 3},
				{2, 4, 6, 8},
			},
			10,
		}}

	for k, c := range cases {
		if CheckSum(c.m) != c.sum {
			t.Error("No match on case:", k)
		}
	}
}

func TestParsing(arr string) [][]int {

}
<commit_msg>remove unused<commit_after>package main

import "testing"

type Case struct {
	m   [][]int
	sum int
}

func TestCheckSum(t *testing.T) {
	cases := []Case{
		Case{
			[][]int{
				{5, 1, 9, 5},
				{7, 5, 3},
				{2, 4, 6, 8},
			},
			18,
		},
		Case{
			[][]int{
				{},
				{7, 5, 3},
				{2, 4, 6, 8},
			},
			10,
		}}

	for k, c := range cases {
		if CheckSum(c.m) != c.sum {
			t.Error("No match on case:", k)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestDockerRestartStoppedContainer(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "foobar")
	out, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	deleteAllContainers()

	logDone("restart - echo foobar for stopped container")
}

func TestDockerRestartRunningContainer(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
	out, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	cleanedContainerID := stripTrailingCharacters(out)

	time.Sleep(1 * time.Second)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", "-t", "1", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	time.Sleep(1 * time.Second)

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	deleteAllContainers()

	logDone("restart - echo foobar for running container")
}

// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func TestDockerRestartWithVolumes(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/test", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumes, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, volumes)

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume after restart received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, volumesAfterRestart)

	if volumes != volumesAfterRestart {
		volumes = strings.Trim(volumes, " \n\r")
		volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
		t.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
	}

	deleteAllContainers()

	logDone("restart - does not create a new volume on restart")
}
<commit_msg>Use prefix naming for restart tests<commit_after>package main

import (
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestRestartStoppedContainer(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "foobar")
	out, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	deleteAllContainers()

	logDone("restart - echo foobar for stopped container")
}

func TestRestartRunningContainer(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
	out, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	cleanedContainerID := stripTrailingCharacters(out)

	time.Sleep(1 * time.Second)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", "-t", "1", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	time.Sleep(1 * time.Second)

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	deleteAllContainers()

	logDone("restart - echo foobar for running container")
}

// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func TestRestartWithVolumes(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/test", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumes, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, volumes)

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	errorOut(err, t, out)

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume after restart received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
	errorOut(err, t, volumesAfterRestart)

	if volumes != volumesAfterRestart {
		volumes = strings.Trim(volumes, " \n\r")
		volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
		t.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
	}

	deleteAllContainers()

	logDone("restart - does not create a new volume on restart")
}
<|endoftext|>


<commit_before>package capabilities

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

	"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2017-09-30/containerservice"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/adal"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/mcuadros/go-version"
)

func NewAKSVersionsHandler() *AKSVersionHandler {
	return &AKSVersionHandler{}
}

type AKSVersionHandler struct {
}

type regionCapabilitiesRequestBody struct {
	// BaseURL specifies the Azure Resource management endpoint, it defaults "https://management.azure.com/".
	BaseURL string `json:"baseUrl"`
	// AuthBaseURL specifies the Azure OAuth 2.0 authentication endpoint, it defaults "https://login.microsoftonline.com/".
	AuthBaseURL string `json:"authBaseUrl"`
	// credentials
	ClientID       string `json:"clientId"`
	ClientSecret   string `json:"clientSecret"`
	SubscriptionID string `json:"subscriptionId"`
	TenantID       string `json:"tenantId"`

	Region string `json:"region"`
}

func (g *AKSVersionHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		writer.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	writer.Header().Set("Content-Type", "application/json")

	var body regionCapabilitiesRequestBody
	if err := extractRequestBody(writer, req, &body); err != nil {
		handleErr(writer, err)
		return
	}

	if err := validateRegionRequestBody(writer, &body); err != nil {
		handleErr(writer, err)
		return
	}

	region := body.Region

	clientID := body.ClientID
	clientSecret := body.ClientSecret
	subscriptionID := body.SubscriptionID
	tenantID := body.TenantID

	baseURL := body.BaseURL
	authBaseURL := body.AuthBaseURL
	if baseURL == "" {
		baseURL = azure.PublicCloud.ResourceManagerEndpoint
	}
	if authBaseURL == "" {
		authBaseURL = azure.PublicCloud.ActiveDirectoryEndpoint
	}

	oAuthConfig, err := adal.NewOAuthConfig(authBaseURL, tenantID)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to configure azure oaith: %v", err))
		return
	}

	spToken, err := adal.NewServicePrincipalToken(*oAuthConfig, clientID, clientSecret, baseURL)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to create token: %v", err))
		return
	}

	authorizer := autorest.NewBearerAuthorizer(spToken)

	client := containerservice.NewContainerServicesClientWithBaseURI(baseURL, subscriptionID)
	client.Authorizer = authorizer

	orchestrators, err := client.ListOrchestrators(context.Background(), region, "managedClusters")
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to get orchestrators: %v", err))
		return
	}

	if orchestrators.Orchestrators == nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("no version profiles returned: %v", err))
		return
	}

	var kubernetesVersions []string

	for _, profile := range *orchestrators.Orchestrators {
		if profile.OrchestratorType == nil || profile.OrchestratorVersion == nil {
			writer.WriteHeader(http.StatusInternalServerError)
			handleErr(writer, fmt.Errorf("unexpected nil orchestrator type or version"))
			return
		}

		if *profile.OrchestratorType == "Kubernetes" {
			kubernetesVersions = append(kubernetesVersions, *profile.OrchestratorVersion)
		}
	}

	sort.Sort(sortableVersion(kubernetesVersions))

	serialized, err := json.Marshal(kubernetesVersions)
	if err != nil {
		writer.WriteHeader(http.StatusInternalServerError)
		handleErr(writer, err)
		return
	}

	writer.Write(serialized)
}

type sortableVersion []string

func (s sortableVersion) Len() int {
	return len(s)
}

func (s sortableVersion) Swap(a, b int) {
	s[a], s[b] = s[b], s[a]
}

func (s sortableVersion) Less(a, b int) bool {
	return version.Compare(s[a], s[b], "<")
}

func validateRegionRequestBody(writer http.ResponseWriter, body *regionCapabilitiesRequestBody) error {
	toCheck := map[string]string{
		"region":         body.Region,
		"clientID":       body.ClientID,
		"clientSecret":   body.ClientSecret,
		"subscriptionID": body.SubscriptionID,
		"tenantID":       body.TenantID,
	}
	for k, v := range toCheck {
		if v == "" {
			writer.WriteHeader(http.StatusBadRequest)
			return fmt.Errorf("invalid %s", k)
		}
	}

	return nil
}
<commit_msg>Changed map -> [][]string to keep BC order<commit_after>package capabilities

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

	"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2017-09-30/containerservice"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/adal"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/mcuadros/go-version"
)

func NewAKSVersionsHandler() *AKSVersionHandler {
	return &AKSVersionHandler{}
}

type AKSVersionHandler struct {
}

type regionCapabilitiesRequestBody struct {
	// BaseURL specifies the Azure Resource management endpoint, it defaults "https://management.azure.com/".
	BaseURL string `json:"baseUrl"`
	// AuthBaseURL specifies the Azure OAuth 2.0 authentication endpoint, it defaults "https://login.microsoftonline.com/".
	AuthBaseURL string `json:"authBaseUrl"`
	// credentials
	ClientID       string `json:"clientId"`
	ClientSecret   string `json:"clientSecret"`
	SubscriptionID string `json:"subscriptionId"`
	TenantID       string `json:"tenantId"`

	Region string `json:"region"`
}

func (g *AKSVersionHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		writer.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	writer.Header().Set("Content-Type", "application/json")

	var body regionCapabilitiesRequestBody
	if err := extractRequestBody(writer, req, &body); err != nil {
		handleErr(writer, err)
		return
	}

	if err := validateRegionRequestBody(writer, &body); err != nil {
		handleErr(writer, err)
		return
	}

	region := body.Region

	clientID := body.ClientID
	clientSecret := body.ClientSecret
	subscriptionID := body.SubscriptionID
	tenantID := body.TenantID

	baseURL := body.BaseURL
	authBaseURL := body.AuthBaseURL
	if baseURL == "" {
		baseURL = azure.PublicCloud.ResourceManagerEndpoint
	}
	if authBaseURL == "" {
		authBaseURL = azure.PublicCloud.ActiveDirectoryEndpoint
	}

	oAuthConfig, err := adal.NewOAuthConfig(authBaseURL, tenantID)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to configure azure oaith: %v", err))
		return
	}

	spToken, err := adal.NewServicePrincipalToken(*oAuthConfig, clientID, clientSecret, baseURL)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to create token: %v", err))
		return
	}

	authorizer := autorest.NewBearerAuthorizer(spToken)

	client := containerservice.NewContainerServicesClientWithBaseURI(baseURL, subscriptionID)
	client.Authorizer = authorizer

	orchestrators, err := client.ListOrchestrators(context.Background(), region, "managedClusters")
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to get orchestrators: %v", err))
		return
	}

	if orchestrators.Orchestrators == nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("no version profiles returned: %v", err))
		return
	}

	var kubernetesVersions []string

	for _, profile := range *orchestrators.Orchestrators {
		if profile.OrchestratorType == nil || profile.OrchestratorVersion == nil {
			writer.WriteHeader(http.StatusInternalServerError)
			handleErr(writer, fmt.Errorf("unexpected nil orchestrator type or version"))
			return
		}

		if *profile.OrchestratorType == "Kubernetes" {
			kubernetesVersions = append(kubernetesVersions, *profile.OrchestratorVersion)
		}
	}

	sort.Sort(sortableVersion(kubernetesVersions))

	serialized, err := json.Marshal(kubernetesVersions)
	if err != nil {
		writer.WriteHeader(http.StatusInternalServerError)
		handleErr(writer, err)
		return
	}

	writer.Write(serialized)
}

type sortableVersion []string

func (s sortableVersion) Len() int {
	return len(s)
}

func (s sortableVersion) Swap(a, b int) {
	s[a], s[b] = s[b], s[a]
}

func (s sortableVersion) Less(a, b int) bool {
	return version.Compare(s[a], s[b], "<")
}

func validateRegionRequestBody(writer http.ResponseWriter, body *regionCapabilitiesRequestBody) error {
	toCheck := [][]string{
		{"region", body.Region},
		{"clientID", body.ClientID},
		{"clientSecret", body.ClientSecret},
		{"subscriptionID", body.SubscriptionID},
		{"tenantID", body.TenantID},
	}
	for _, v := range toCheck {
		if v[1] == "" {
			writer.WriteHeader(http.StatusBadRequest)
			return fmt.Errorf("invalid %s", v[0])
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/google/syzkaller/pkg/compiler"
)

type freebsd struct{}

func (*freebsd) prepare(sourcedir string, build bool, arches []*Arch) error {
	if sourcedir == "" {
		return fmt.Errorf("provide path to kernel checkout via -sourcedir flag (or make extract SOURCEDIR)")
	}
	if !build {
		return fmt.Errorf("freebsd requires -build flag")
	}
	return nil
}

func (*freebsd) prepareArch(arch *Arch) error {
	if err := os.Symlink(filepath.Join(arch.sourceDir, "sys", "amd64", "include"),
		filepath.Join(arch.buildDir, "machine")); err != nil {
		return fmt.Errorf("failed to create link: %v", err)
	}
	if err := os.Symlink(filepath.Join(arch.sourceDir, "sys", "x86", "include"),
		filepath.Join(arch.buildDir, "x86")); err != nil {
		return fmt.Errorf("failed to create link: %v", err)
	}
	return nil
}

func (*freebsd) processFile(arch *Arch, info *compiler.ConstInfo) (map[string]uint64, map[string]bool, error) {
	args := []string{
		"-fmessage-length=0",
		"-nostdinc",
		"-DGENOFFSET",
		"-D_KERNEL",
		"-D__BSD_VISIBLE=1",
		"-I", filepath.Join(arch.sourceDir, "sys"),
		"-I", filepath.Join(arch.sourceDir, "sys", "sys"),
		"-I", filepath.Join(arch.sourceDir, "sys", "amd64"),
		"-I", arch.buildDir,
	}
	for _, incdir := range info.Incdirs {
		args = append(args, "-I"+filepath.Join(arch.sourceDir, incdir))
	}
	if arch.includeDirs != "" {
		for _, dir := range strings.Split(arch.includeDirs, ",") {
			args = append(args, "-I"+dir)
		}
	}
	params := &extractParams{
		AddSource:     "#include <sys/syscall.h>",
		DeclarePrintf: true,
		TargetEndian:  arch.target.HostEndian,
	}
	return extract(info, "gcc", args, params)
}
<commit_msg>sys/syz-extract: clean up const generation on FreeBSD<commit_after>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/google/syzkaller/pkg/compiler"
)

type freebsd struct{}

func (*freebsd) prepare(sourcedir string, build bool, arches []*Arch) error {
	if sourcedir == "" {
		return fmt.Errorf("provide path to kernel checkout via -sourcedir flag (or make extract SOURCEDIR)")
	}
	if !build {
		return fmt.Errorf("freebsd requires -build flag")
	}
	return nil
}

func (*freebsd) prepareArch(arch *Arch) error {
	archName := arch.target.Arch
	// Use the the correct name for FreeBSD/i386
	if archName == "386" {
		archName = "i386"
	}
	if err := os.Symlink(filepath.Join(arch.sourceDir, "sys", archName, "include"),
		filepath.Join(arch.buildDir, "machine")); err != nil {
		return fmt.Errorf("failed to create link: %v", err)
	}
	if err := os.Symlink(filepath.Join(arch.sourceDir, "sys", "x86", "include"),
		filepath.Join(arch.buildDir, "x86")); err != nil {
		return fmt.Errorf("failed to create link: %v", err)
	}
	return nil
}

func (*freebsd) processFile(arch *Arch, info *compiler.ConstInfo) (map[string]uint64, map[string]bool, error) {
	args := []string{
		"-fmessage-length=0",
		"-nostdinc",
		"-DGENOFFSET",
		"-D_KERNEL",
		"-D__BSD_VISIBLE=1",
		"-I", filepath.Join(arch.sourceDir, "sys"),
		"-I", filepath.Join(arch.sourceDir, "sys", "sys"),
		"-I", arch.buildDir,
	}
	for _, incdir := range info.Incdirs {
		args = append(args, "-I"+filepath.Join(arch.sourceDir, incdir))
	}
	if arch.includeDirs != "" {
		for _, dir := range strings.Split(arch.includeDirs, ",") {
			args = append(args, "-I"+dir)
		}
	}
	args = append(args, arch.target.CFlags...)
	params := &extractParams{
		AddSource:     "#include <sys/syscall.h>",
		DeclarePrintf: true,
		TargetEndian:  arch.target.HostEndian,
	}
	cc := arch.target.CCompiler
	return extract(info, cc, args, params)
}
<|endoftext|>


<commit_before>/* https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/
Find the length of the longest substring T of a given string (consists of lowercase letters only)
such that every character in T appears no less than k times.

Example 1:

	Input:
	s = "aaabb", k = 3

	Output:
	3

	The longest substring is "aaa", as 'a' is repeated 3 times.

Example 2:

	Input:
	s = "ababbc", k = 2

	Output:
	5

	The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.
*/

package lstring

func longestSubstring(s string, k int) int {
	tmp := [26]int{}
	for i := range s {
		tmp[s[i]-97]++
	}

	for i := len(s); i >= k; i-- {
		for idx := i; idx < len(s); idx++ { // 去掉cache中不需要的tail
			tmp[s[idx]-97]--
		}
		subEnd := len(s) - i
		for j := 0; j <= subEnd; j++ {
			if j != 0 { // 去掉不需要的cache
				tmp[s[j-1]-97]--
			}

			flag := true
			for idx := range tmp {
				if tmp[idx] != 0 && tmp[idx] < k {
					flag = false
					break
				}
			}
			if last := j + i; 0 < last && last < len(s) { // 增加下一步的cache
				tmp[s[last]-97]++
			}
			if flag {
				return i
			}
		}

		for idx := 0; idx < len(s)-i; idx++ { // 补全head
			tmp[s[idx]-97]++
		}
	}
	return 0
}
<commit_msg>395. longestSubstring: Runtime: 0 ms, faster than 100.00%<commit_after>/* https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/
Find the length of the longest substring T of a given string (consists of lowercase letters only)
such that every character in T appears no less than k times.

Example 1:

	Input:
	s = "aaabb", k = 3

	Output:
	3

	The longest substring is "aaa", as 'a' is repeated 3 times.

Example 2:

	Input:
	s = "ababbc", k = 2

	Output:
	5

	The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.
*/

package lstring

func longestSubstring(s string, k int) int {
	max := func(x, y int) int {
		if x > y {
			return x
		}
		return y
	}

	var dfs func(s string, left, right int, k int) int
	dfs = func(s string, left, right int, k int) int {
		letters := [26]int{}
		for i := left; i < right; i++ {
			letters[s[i]-97]++
		}

		valid := true
		for i := 0; i < 26; i++ {
			if letters[i] > 0 && letters[i] < k {
				valid = false
				break
			}
		}
		if valid {
			return right - left
		}

		var length int
		start := left
		for i := left; i < right; i++ {
			if letters[s[i]-97] < k {
				length = max(length, dfs(s, start, i, k))
				start = i + 1
			}
		}
		return max(length, dfs(s, start, right, k))
	}

	return dfs(s, 0, len(s), k)
}

// Runtime: 336 ms, faster than 12.82%, Memory Usage: 2 MB, less than 100.00%
// func longestSubstring(s string, k int) int {
// 	tmp := [26]int{}
// 	for i := range s {
// 		tmp[s[i]-97]++
// 	}

// 	for i := len(s); i >= k; i-- {
// 		for idx := i; idx < len(s); idx++ { // 去掉cache中不需要的tail
// 			tmp[s[idx]-97]--
// 		}
// 		subEnd := len(s) - i
// 		for j := 0; j <= subEnd; j++ {
// 			if j != 0 { // 去掉不需要的cache
// 				tmp[s[j-1]-97]--
// 			}

// 			flag := true
// 			for idx := range tmp {
// 				if tmp[idx] != 0 && tmp[idx] < k {
// 					flag = false
// 					break
// 				}
// 			}
// 			if last := j + i; 0 < last && last < len(s) { // 增加下一步的cache
// 				tmp[s[last]-97]++
// 			}
// 			if flag {
// 				return i
// 			}
// 		}

// 		for idx := 0; idx < len(s)-i; idx++ { // 补全head
// 			tmp[s[idx]-97]++
// 		}
// 	}
// 	return 0
// }
<|endoftext|>


<commit_before>package elements

type Stackable interface {
	Add(*Component)
}

type Element interface {
	Add(Element)
	Next() Element
	Parent(Element)
	Root() Element
}

type DefaultElement struct {
	index int
	stack []Element
	root  Element
}

func (d *DefaultElement) Add(e Element) {
	d.stack = append(d.stack, e)
}

func (d *DefaultElement) Parent(p Element) {
	d.root = p
}

func (d *DefaultElement) Root() Element {
	return d.root
}

func (d *DefaultElement) Next() Element {
	index := d.index

	if len(d.stack) > d.index {
		d.index = d.index + 1
		return d.stack[index]
	}

	return nil
}

func NewDefaultElement() DefaultElement {
	d := DefaultElement{}
	d.stack = make([]Element, 0)
	return d
}

type Component struct {
	DefaultElement
	Typ        string
	Identifier string
	Alias      string
}

func NewComponent(l, r Element, typ, identifier, alias string) Element {
	d := NewDefaultElement()
	if l != nil {
		d.Add(l)
	}
	if r != nil {
		d.Add(r)
	}

	c := &Component{
		DefaultElement: d,
		Typ:            typ,
		Identifier:     identifier,
		Alias:          alias,
	}

	return c
}

type Matrix struct {
	DefaultElement
}

func NewMatrix(e1 Element) Element {
	d := NewDefaultElement()
	if e1 != nil {
		d.Add(e1)
	}

	m := &Matrix{
		DefaultElement: d,
	}

	return m
}
<commit_msg>Add child check to interface<commit_after>package elements

type Stackable interface {
	Add(*Component)
}

type Element interface {
	Add(Element)
	Next() Element
	Parent(Element)
	Root() Element
	HasChilds() bool
}

type DefaultElement struct {
	index int
	stack []Element
	root  Element
}

func (d *DefaultElement) Add(e Element) {
	d.stack = append(d.stack, e)
}

func (d *DefaultElement) Parent(p Element) {
	d.root = p
}

func (d *DefaultElement) Root() Element {
	return d.root
}

func (d *DefaultElement) Next() Element {
	index := d.index

	if len(d.stack) > d.index {
		d.index = d.index + 1
		return d.stack[index]
	}

	return nil
}

func (d *DefaultElement) HasChilds() bool {
	if len(d.stack) > 0 {
		return true
	}

	return false
}

func NewDefaultElement() DefaultElement {
	d := DefaultElement{}
	d.stack = make([]Element, 0)
	return d
}

type Component struct {
	DefaultElement
	Typ        string
	Identifier string
	Alias      string
}

func NewComponent(l, r Element, typ, identifier, alias string) Element {
	d := NewDefaultElement()
	if l != nil {
		d.Add(l)
	}
	if r != nil {
		d.Add(r)
	}

	c := &Component{
		DefaultElement: d,
		Typ:            typ,
		Identifier:     identifier,
		Alias:          alias,
	}

	return c
}

type Matrix struct {
	DefaultElement
}

func NewMatrix(e1 Element) Element {
	d := NewDefaultElement()
	if e1 != nil {
		d.Add(e1)
	}

	m := &Matrix{
		DefaultElement: d,
	}

	return m
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"github.com/FidelityInternational/chaos-galago/processor/Godeps/_workspace/src/chaos-galago/shared/utils"
	"github.com/FidelityInternational/chaos-galago/processor/Godeps/_workspace/src/github.com/cloudfoundry-community/go-cfclient"
	"github.com/FidelityInternational/chaos-galago/processor/utils"
	"os"
	"strconv"
	"time"
)

var (
	dbConnectionString string
	err                error
	config             *cfclient.Config
)

func init() {
	dbConnectionString, err = sharedUtils.GetDBConnectionDetails()
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}
	config = utils.LoadCFConfig()
	fmt.Println("Config loaded:")
	fmt.Println("ApiAddress: ", config.ApiAddress)
	fmt.Println("LoginAddress: ", config.LoginAddress)
	fmt.Println("Username: ", config.Username)
	fmt.Println("SkipSslValidation: ", config.SkipSslValidation)
}

func logError(err error) bool {
	if err != nil {
		fmt.Println("An error has occured")
		fmt.Println(err.Error())
		return true
	}
	return false
}

func main() {
	cfClient := cfclient.NewClient(config)
	ticker := time.NewTicker(1 * time.Minute)

	processServices(cfClient)
	for _ = range ticker.C {
		processServices(cfClient)
	}
}

func processServices(cfClient *cfclient.Client) {
	db, err := sql.Open("mysql", dbConnectionString)
	defer db.Close()
	if logError(err) {
		return
	}

	services := utils.GetBoundApps(db)

	for _, service := range services {
		if utils.ShouldProcess(service.Frequency, service.LastProcessed) {
			fmt.Printf("Processing chaos for %s\n", service.AppID)
			err = utils.UpdateLastProcessed(db, service.AppID, utils.TimeNow())
			if logError(err) {
				continue
			}
			if utils.ShouldRun(service.Probability) {
				fmt.Printf("Running chaos for %s\n", service.AppID)
				appInstances := cfClient.GetAppInstances(service.AppID)
				if utils.IsAppHealthy(appInstances) {
					fmt.Printf("App %s is Healthy\n", service.AppID)
					chaosInstance := strconv.Itoa(utils.PickAppInstance(appInstances))
					fmt.Printf("About to kill app instance: %s at index: %s\n", service.AppID, chaosInstance)
					cfClient.KillAppInstance(service.AppID, chaosInstance)
					err = utils.UpdateLastProcessed(db, service.AppID, utils.TimeNow())
					logError(err)
				} else {
					fmt.Printf("App %s is unhealthy, skipping\n", service.AppID)
				}
			} else {
				fmt.Printf("Not running chaos for %s\n", service.AppID)
				err = utils.UpdateLastProcessed(db, service.AppID, utils.TimeNow())
				logError(err)
			}
		} else {
			fmt.Printf("Skipping processing chaos for %s\n", service.AppID)
		}
	}
}
<commit_msg>remove pointless range assignment<commit_after>package main

import (
	"database/sql"
	"fmt"
	"github.com/FidelityInternational/chaos-galago/processor/Godeps/_workspace/src/chaos-galago/shared/utils"
	"github.com/FidelityInternational/chaos-galago/processor/Godeps/_workspace/src/github.com/cloudfoundry-community/go-cfclient"
	"github.com/FidelityInternational/chaos-galago/processor/utils"
	"os"
	"strconv"
	"time"
)

var (
	dbConnectionString string
	err                error
	config             *cfclient.Config
)

func init() {
	dbConnectionString, err = sharedUtils.GetDBConnectionDetails()
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}
	config = utils.LoadCFConfig()
	fmt.Println("Config loaded:")
	fmt.Println("ApiAddress: ", config.ApiAddress)
	fmt.Println("LoginAddress: ", config.LoginAddress)
	fmt.Println("Username: ", config.Username)
	fmt.Println("SkipSslValidation: ", config.SkipSslValidation)
}

func logError(err error) bool {
	if err != nil {
		fmt.Println("An error has occured")
		fmt.Println(err.Error())
		return true
	}
	return false
}

func main() {
	cfClient := cfclient.NewClient(config)
	ticker := time.NewTicker(1 * time.Minute)

	processServices(cfClient)
	for range ticker.C {
		processServices(cfClient)
	}
}

func processServices(cfClient *cfclient.Client) {
	db, err := sql.Open("mysql", dbConnectionString)
	defer db.Close()
	if logError(err) {
		return
	}

	services := utils.GetBoundApps(db)

	for _, service := range services {
		if utils.ShouldProcess(service.Frequency, service.LastProcessed) {
			fmt.Printf("Processing chaos for %s\n", service.AppID)
			err = utils.UpdateLastProcessed(db, service.AppID, utils.TimeNow())
			if logError(err) {
				continue
			}
			if utils.ShouldRun(service.Probability) {
				fmt.Printf("Running chaos for %s\n", service.AppID)
				appInstances := cfClient.GetAppInstances(service.AppID)
				if utils.IsAppHealthy(appInstances) {
					fmt.Printf("App %s is Healthy\n", service.AppID)
					chaosInstance := strconv.Itoa(utils.PickAppInstance(appInstances))
					fmt.Printf("About to kill app instance: %s at index: %s\n", service.AppID, chaosInstance)
					cfClient.KillAppInstance(service.AppID, chaosInstance)
					err = utils.UpdateLastProcessed(db, service.AppID, utils.TimeNow())
					logError(err)
				} else {
					fmt.Printf("App %s is unhealthy, skipping\n", service.AppID)
				}
			} else {
				fmt.Printf("Not running chaos for %s\n", service.AppID)
				err = utils.UpdateLastProcessed(db, service.AppID, utils.TimeNow())
				logError(err)
			}
		} else {
			fmt.Printf("Skipping processing chaos for %s\n", service.AppID)
		}
	}
}
<|endoftext|>


<commit_before>package application

import (
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
)

// StatickHandler handler to resolve work with static content from CDN
type StatickHandler struct {
	cdnroot    string
	tmpDirName string
}

// http://119226.selcdn.ru/bubble/ShootTheBubbleDevVK.html
// http://bubble-srv-dev.herokuapp.com/bubble/ShootTheBubbleDevVK.html

// NewStatickHandler create static handler
func NewStatickHandler(cdnroot string) (*StatickHandler, error) {
	tmpDirName, err := ioutil.TempDir("", "bubble_cache_")
	if err != nil {
		return nil, errors.Wrap(err, "can't create tmp dir for static")
	}
	return &StatickHandler{
		cdnroot:    cdnroot,
		tmpDirName: tmpDirName,
	}, nil
}

// Serve resolve content from CDN
func (sh StatickHandler) Serve(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer r.Body.Close()
	}
	filePath := r.URL.Path
	fullFilePath := filepath.ToSlash(sh.tmpDirName + filePath)
	if _, err := os.Stat(fullFilePath); os.IsNotExist(err) {
		dirToStoreFile := filepath.Dir(fullFilePath)
		if _, err = os.Stat(dirToStoreFile); os.IsNotExist(err) {
			err = os.MkdirAll(dirToStoreFile, 0777)
			if err != nil {
				panic(err)
			}
		}
		out, err := os.Create(fullFilePath)
		if err != nil {
			panic(err)
		}
		defer out.Close()
		resp, err := http.Get(sh.cdnroot + filePath)
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()
		_, err = io.Copy(out, resp.Body)
		if err != nil {
			panic(err)
		}
	}

	dat, err := ioutil.ReadFile(fullFilePath)
	if err != nil {
		panic(err)
	}
	ext := filepath.Ext(fullFilePath)
	w.Header().Set("Content-Type", mime.TypeByExtension(ext))
	_, err = w.Write(dat)
	if err != nil {
		panic(err)
	}
}

// Clear remove statick files
func (sh StatickHandler) Clear(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer r.Body.Close()
	}
	err := os.RemoveAll(sh.tmpDirName)
	if err != nil {
		panic(err)
	}
	JSON(w, "done")
}
<commit_msg>reuse http connection (#13)<commit_after>package application

import (
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/pkg/errors"
)

// StatickHandler handler to resolve work with static content from CDN
type StatickHandler struct {
	cdnroot    string
	tmpDirName string
	httpClien  *http.Client
}

// http://119226.selcdn.ru/bubble/ShootTheBubbleDevVK.html
// http://bubble-srv-dev.herokuapp.com/bubble/ShootTheBubbleDevVK.html

// NewStatickHandler create static handler
func NewStatickHandler(cdnroot string) (*StatickHandler, error) {
	tmpDirName, err := ioutil.TempDir("", "bubble_cache_")
	if err != nil {
		return nil, errors.Wrap(err, "can't create tmp dir for static")
	}
	return &StatickHandler{
		cdnroot:    cdnroot,
		tmpDirName: tmpDirName,
		httpClien: &http.Client{
			Transport: &http.Transport{
				MaxIdleConnsPerHost: 5,
			},
			Timeout: 5 * time.Second,
		},
	}, nil
}

// Serve resolve content from CDN
func (sh StatickHandler) Serve(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer r.Body.Close()
	}
	filePath := r.URL.Path
	fullFilePath := filepath.ToSlash(sh.tmpDirName + filePath)
	if _, err := os.Stat(fullFilePath); os.IsNotExist(err) {
		dirToStoreFile := filepath.Dir(fullFilePath)
		if _, err = os.Stat(dirToStoreFile); os.IsNotExist(err) {
			err = os.MkdirAll(dirToStoreFile, 0777)
			if err != nil {
				panic(err)
			}
		}
		out, err := os.Create(fullFilePath)
		if err != nil {
			panic(err)
		}
		defer out.Close()
		resp, err := sh.httpClien.Get(sh.cdnroot + filePath)
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()
		_, err = io.Copy(out, resp.Body)
		if err != nil {
			panic(err)
		}
	}

	dat, err := ioutil.ReadFile(fullFilePath)
	if err != nil {
		panic(err)
	}
	ext := filepath.Ext(fullFilePath)
	w.Header().Set("Content-Type", mime.TypeByExtension(ext))
	_, err = w.Write(dat)
	if err != nil {
		panic(err)
	}
}

// Clear remove statick files
func (sh StatickHandler) Clear(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer r.Body.Close()
	}
	err := os.RemoveAll(sh.tmpDirName)
	if err != nil {
		panic(err)
	}
	JSON(w, "done")
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/handlers"
)

func main() {
	listener, err := net.Listen("tcp4", constants.HOST+":"+constants.PORT)
	if err != nil {
		log.Println("Failed to open listener on port " + constants.PORT)
		log.Panic("Error was: " + err.Error())
	}
	defer listener.Close()

	log.Println("Listening for connections...")

	// Handle requests in a go routine
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Failed to accept request: " + err.Error())
			continue
		}
		go handlers.HandleRequest(conn)
	}
}
<commit_msg>Added comments and documentation.<commit_after>package main

import (
	"log"
	"net"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/handlers"
)

func main() {
	listener, err := net.Listen("tcp4", constants.HOST+":"+constants.PORT)  // The plugs only support IPv4.
	if err != nil {
		log.Println("Failed to open listener on port " + constants.PORT)
		log.Panic("Error was: " + err.Error())
	}
	defer listener.Close()

	log.Println("Listening for connections...")

	// Handle requests in a go routine
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Failed to accept request: " + err.Error())
			continue
		}
		go handlers.HandleRequest(conn)
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"testing"
)

// TestRegression tests a regression that was merged between versions 1.20.0 and 1.21.0
// The included app.Run line worked in 1.20.0, and then was broken in 1.21.0.
func TestVersionOneTwoOneRegression(t *testing.T) {
	// setup
	app := NewApp()
	app.Commands = []Command{{
		Name: "command",
		Flags: []Flag{
			StringFlag{
				Name: "flagone",
			},
		},
		Action: func(c *Context) error { return nil },
	}}

	// logic under test
	err := app.Run([]string{"cli", "command", "--flagone", "flagvalue", "docker", "image", "ls", "--no-trunc"})

	// assertions
	if err != nil {
		t.Errorf("did not expected an error, but there was one: %s", err)
	}
}
<commit_msg>update tests<commit_after>package cli

import (
	"testing"
)

// TestRegression tests a regression that was merged between versions 1.20.0 and 1.21.0
// The included app.Run line worked in 1.20.0, and then was broken in 1.21.0.
// Relevant PR: https://github.com/urfave/cli/pull/872
func TestVersionOneTwoOneRegression(t *testing.T) {
	testData := []struct {
		testCase    string
		appRunInput []string
	}{
		// assertion: empty input, when a required flag is present, errors
		{
			testCase:    "with_dash_dash",
			appRunInput: []string{"cli", "command", "--flagone", "flagvalue", "--", "docker", "image", "ls", "--no-trunc"},
		},
		{
			testCase:    "without_dash_dash",
			appRunInput: []string{"cli", "command", "--flagone", "flagvalue", "docker", "image", "ls", "--no-trunc"},
		},
	}
	for _, test := range testData {
		t.Run(test.testCase, func(t *testing.T) {
			// setup
			app := NewApp()
			app.Commands = []Command{{
				Name: "command",
				Flags: []Flag{
					StringFlag{
						Name: "flagone",
					},
				},
				Action: func(c *Context) error { return nil },
			}}

			// logic under test
			err := app.Run(test.appRunInput)

			// assertions
			if err != nil {
				t.Errorf("did not expected an error, but there was one: %s", err)
			}
		})
	}
}
<|endoftext|>


<commit_before>package errhandler

import (
	"github.com/caarlos0/log"
	"github.com/goreleaser/goreleaser/internal/middleware"
	"github.com/goreleaser/goreleaser/internal/pipe"
	"github.com/goreleaser/goreleaser/pkg/context"
)

// Handle handles an action error, ignoring and logging pipe skipped
// errors.
func Handle(action middleware.Action) middleware.Action {
	return func(ctx *context.Context) error {
		err := action(ctx)
		if err == nil {
			return nil
		}
		if pipe.IsSkip(err) {
			log.WithError(err).Warn("pipe skipped")
			return nil
		}
		return err
	}
}
<commit_msg>fix: make skip message more idiomatic (#3223)<commit_after>package errhandler

import (
	"github.com/caarlos0/log"
	"github.com/goreleaser/goreleaser/internal/middleware"
	"github.com/goreleaser/goreleaser/internal/pipe"
	"github.com/goreleaser/goreleaser/pkg/context"
)

// Handle handles an action error, ignoring and logging pipe skipped
// errors.
func Handle(action middleware.Action) middleware.Action {
	return func(ctx *context.Context) error {
		err := action(ctx)
		if err == nil {
			return nil
		}
		if pipe.IsSkip(err) {
			log.WithField("reason", err.Error()).Warn("pipe skipped")
			return nil
		}
		return err
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"testing"
)

// TestRegression tests a regression that was merged between versions 1.20.0 and 1.21.0
// The included app.Run line worked in 1.20.0, and then was broken in 1.21.0.
// Relevant PR: https://github.com/urfave/cli/pull/872
func TestVersionOneTwoOneRegression(t *testing.T) {
	testData := []struct {
		testCase    string
		appRunInput []string
	}{
		// assertion: empty input, when a required flag is present, errors
		{
			testCase:    "with_dash_dash",
			appRunInput: []string{"cli", "command", "--flagone", "flagvalue", "--", "docker", "image", "ls", "--no-trunc"},
		},
		{
			testCase:    "without_dash_dash",
			appRunInput: []string{"cli", "command", "--flagone", "flagvalue", "docker", "image", "ls", "--no-trunc"},
		},
	}
	for _, test := range testData {
		t.Run(test.testCase, func(t *testing.T) {
			// setup
			app := NewApp()
			app.Commands = []Command{{
				Name: "command",
				Flags: []Flag{
					StringFlag{
						Name: "flagone",
					},
				},
				Action: func(c *Context) error { return nil },
			}}

			// logic under test
			err := app.Run(test.appRunInput)

			// assertions
			if err != nil {
				t.Errorf("did not expected an error, but there was one: %s", err)
			}
		})
	}
}
<commit_msg>cleanup<commit_after>package cli

import (
	"testing"
)

// TestRegression tests a regression that was merged between versions 1.20.0 and 1.21.0
// The included app.Run line worked in 1.20.0, and then was broken in 1.21.0.
// Relevant PR: https://github.com/urfave/cli/pull/872
func TestVersionOneTwoOneRegression(t *testing.T) {
	testData := []struct {
		testCase    string
		appRunInput []string
	}{
		{
			testCase:    "with_dash_dash",
			appRunInput: []string{"cli", "command", "--flagone", "flagvalue", "--", "docker", "image", "ls", "--no-trunc"},
		},
		{
			testCase:    "without_dash_dash",
			appRunInput: []string{"cli", "command", "--flagone", "flagvalue", "docker", "image", "ls", "--no-trunc"},
		},
	}
	for _, test := range testData {
		t.Run(test.testCase, func(t *testing.T) {
			// setup
			app := NewApp()
			app.Commands = []Command{{
				Name: "command",
				Flags: []Flag{
					StringFlag{
						Name: "flagone",
					},
				},
				Action: func(c *Context) error { return nil },
			}}

			// logic under test
			err := app.Run(test.appRunInput)

			// assertions
			if err != nil {
				t.Errorf("did not expected an error, but there was one: %s", err)
			}
		})
	}
}
<|endoftext|>


<commit_before>package privatemessage

import (
	"errors"
	"koding/db/mongodb/modelhelper"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/common/response"

	"github.com/koding/bongo"
)

var ErrAccountIdNotSet = errors.New("acccountId is not defined")

func fetchParticipantIds(participantNames []string) ([]int64, error) {
	participantIds := make([]int64, len(participantNames))
	for i, participantName := range participantNames {
		account, err := modelhelper.GetAccount(participantName)
		if err != nil {
			return nil, err
		}
		a := models.NewAccount()
		a.Id = account.SocialApiId
		a.OldId = account.Id.Hex()
		a.Nick = account.Profile.Nickname
		// fetch or create social api id
		if a.Id == 0 {
			if err := a.FetchOrCreate(); err != nil {
				return nil, err
			}
		}
		participantIds[i] = a.Id
	}

	return participantIds, nil
}

func appendCreatorIdIntoParticipantList(participants []int64, authorId int64) []int64 {
	for _, participant := range participants {
		if participant == authorId {
			return participants
		}
	}

	return append(participants, authorId)
}

func Init(u *url.URL, h http.Header, req *models.PrivateMessageRequest) (int, http.Header, interface{}, error) {
	if req.AccountId == 0 {
		return response.NewBadRequest(ErrAccountIdNotSet)
	}

	cm := models.NewChannelMessage()
	cm.Body = req.Body
	participantIds, err := fetchParticipantIds(req.Recipients)
	if err != nil {
		return response.NewBadRequest(err)
	}

	// append creator to the recipients
	participantIds = appendCreatorIdIntoParticipantList(participantIds, req.AccountId)

	// author and atleast one recipient should be in the
	// recipient list
	if len(participantIds) < 1 {
		// user can send private message to themself
		return response.NewBadRequest(errors.New("you should define your recipients"))
	}

	if req.GroupName == "" {
		req.GroupName = models.Channel_KODING_NAME
	}

	//// first create the channel
	c := models.NewPrivateMessageChannel(req.AccountId, req.GroupName)
	if err := c.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	cm.TypeConstant = models.ChannelMessage_TYPE_PRIVATE_MESSAGE
	cm.AccountId = req.AccountId
	cm.InitialChannelId = c.Id
	if err := cm.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	messageContainer, err := cm.BuildEmptyMessageContainer()
	if err != nil {
		return response.NewBadRequest(err)
	}

	_, err = c.AddMessage(cm.Id)
	if err != nil {
		return response.NewBadRequest(err)
	}

	for _, participantId := range participantIds {
		_, err := c.AddParticipant(participantId)
		if err != nil {
			return response.NewBadRequest(err)
		}
	}

	cmc := models.NewChannelContainer()
	cmc.Channel = c
	cmc.IsParticipant = true
	cmc.LastMessage = messageContainer
	cmc.ParticipantCount = len(participantIds)
	participantOldIds, err := models.FetchAccountOldsIdByIdsFromCache(participantIds)
	if err != nil {
		return response.NewBadRequest(err)
	}

	cmc.ParticipantsPreview = participantOldIds

	return response.NewOK(cmc)
}

func Send(u *url.URL, h http.Header, req *models.PrivateMessageRequest) (int, http.Header, interface{}, error) {
	if req.AccountId == 0 {
		return response.NewBadRequest(ErrAccountIdNotSet)
	}

	// check channel existence
	c := models.NewChannel()
	if err := c.ById(req.ChannelId); err != nil {
		return response.NewBadRequest(err)
	}

	// check if sender is whether a participant of conversation
	cp := models.NewChannelParticipant()
	cp.ChannelId = c.Id
	cp.AccountId = req.AccountId
	if err := cp.FetchParticipant(); err != nil {
		return response.NewBadRequest(err)
	}

	// add private message
	cm := models.NewChannelMessage()
	cm.Body = req.Body
	cm.TypeConstant = models.ChannelMessage_TYPE_PRIVATE_MESSAGE
	cm.AccountId = req.AccountId
	cm.InitialChannelId = c.Id
	if err := cm.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	if _, err := c.AddMessage(cm.Id); err != nil {
		return response.NewBadRequest(err)
	}

	messageContainer, err := cm.BuildEmptyMessageContainer()
	if err != nil {
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelContainer()
	cmc.Channel = *c
	cmc.IsParticipant = true
	cmc.LastMessage = messageContainer

	return response.NewOK(cmc)
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)

	if q.AccountId == 0 || q.GroupName == "" {
		return response.NewBadRequest(errors.New("request is not valid"))
	}

	channelList, err := getPrivateMessageChannels(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	cc := models.NewChannelContainers()
	if err := cc.Fetch(channelList, q); err != nil {
		return response.NewBadRequest(err)
	}

	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage()
	cc.AddUnreadCount(q.AccountId)

	return response.HandleResultAndError(cc, cc.Err())
}

func getPrivateMessageChannels(q *request.Query) ([]models.Channel, error) {
	// build query for
	c := models.NewChannel()
	channelIds := make([]int64, 0)
	query := bongo.B.DB.
		Model(c).
		Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel_participant on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and "+
		"api.channel.group_name = ? and "+
		"api.channel.type_constant = ? and "+
		"api.channel_participant.status_constant = ?",
		q.AccountId,
		q.GroupName,
		models.Channel_TYPE_PRIVATE_MESSAGE,
		models.ChannelParticipant_STATUS_ACTIVE)

	// add exempt clause if needed
	if !q.ShowExempt {
		query = query.Where("api.channel.meta_bits = ?", models.Safe)
	}

	query = query.Limit(q.Limit).
		Offset(q.Skip).
		Order("api.channel.updated_at DESC")

	rows, err := query.Rows()
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var channelId int64
		err := rows.Scan(&channelId)
		if err == nil {
			channelIds = append(channelIds, channelId)
		}
	}

	channels, err := c.FetchByIds(channelIds)
	if err != nil {
		return nil, err
	}

	return channels, nil
}
<commit_msg>PrivateMessage: Change ChannelContainer Channel field to pointer<commit_after>package privatemessage

import (
	"errors"
	"koding/db/mongodb/modelhelper"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/common/response"

	"github.com/koding/bongo"
)

var ErrAccountIdNotSet = errors.New("acccountId is not defined")

func fetchParticipantIds(participantNames []string) ([]int64, error) {
	participantIds := make([]int64, len(participantNames))
	for i, participantName := range participantNames {
		account, err := modelhelper.GetAccount(participantName)
		if err != nil {
			return nil, err
		}
		a := models.NewAccount()
		a.Id = account.SocialApiId
		a.OldId = account.Id.Hex()
		a.Nick = account.Profile.Nickname
		// fetch or create social api id
		if a.Id == 0 {
			if err := a.FetchOrCreate(); err != nil {
				return nil, err
			}
		}
		participantIds[i] = a.Id
	}

	return participantIds, nil
}

func appendCreatorIdIntoParticipantList(participants []int64, authorId int64) []int64 {
	for _, participant := range participants {
		if participant == authorId {
			return participants
		}
	}

	return append(participants, authorId)
}

func Init(u *url.URL, h http.Header, req *models.PrivateMessageRequest) (int, http.Header, interface{}, error) {
	if req.AccountId == 0 {
		return response.NewBadRequest(ErrAccountIdNotSet)
	}

	cm := models.NewChannelMessage()
	cm.Body = req.Body
	participantIds, err := fetchParticipantIds(req.Recipients)
	if err != nil {
		return response.NewBadRequest(err)
	}

	// append creator to the recipients
	participantIds = appendCreatorIdIntoParticipantList(participantIds, req.AccountId)

	// author and atleast one recipient should be in the
	// recipient list
	if len(participantIds) < 1 {
		// user can send private message to themself
		return response.NewBadRequest(errors.New("you should define your recipients"))
	}

	if req.GroupName == "" {
		req.GroupName = models.Channel_KODING_NAME
	}

	//// first create the channel
	c := models.NewPrivateMessageChannel(req.AccountId, req.GroupName)
	if err := c.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	cm.TypeConstant = models.ChannelMessage_TYPE_PRIVATE_MESSAGE
	cm.AccountId = req.AccountId
	cm.InitialChannelId = c.Id
	if err := cm.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	messageContainer, err := cm.BuildEmptyMessageContainer()
	if err != nil {
		return response.NewBadRequest(err)
	}

	_, err = c.AddMessage(cm.Id)
	if err != nil {
		return response.NewBadRequest(err)
	}

	for _, participantId := range participantIds {
		_, err := c.AddParticipant(participantId)
		if err != nil {
			return response.NewBadRequest(err)
		}
	}

	cmc := models.NewChannelContainer()
	cmc.Channel = c
	cmc.IsParticipant = true
	cmc.LastMessage = messageContainer
	cmc.ParticipantCount = len(participantIds)
	participantOldIds, err := models.FetchAccountOldsIdByIdsFromCache(participantIds)
	if err != nil {
		return response.NewBadRequest(err)
	}

	cmc.ParticipantsPreview = participantOldIds

	return response.NewOK(cmc)
}

func Send(u *url.URL, h http.Header, req *models.PrivateMessageRequest) (int, http.Header, interface{}, error) {
	if req.AccountId == 0 {
		return response.NewBadRequest(ErrAccountIdNotSet)
	}

	// check channel existence
	c := models.NewChannel()
	if err := c.ById(req.ChannelId); err != nil {
		return response.NewBadRequest(err)
	}

	// check if sender is whether a participant of conversation
	cp := models.NewChannelParticipant()
	cp.ChannelId = c.Id
	cp.AccountId = req.AccountId
	if err := cp.FetchParticipant(); err != nil {
		return response.NewBadRequest(err)
	}

	// add private message
	cm := models.NewChannelMessage()
	cm.Body = req.Body
	cm.TypeConstant = models.ChannelMessage_TYPE_PRIVATE_MESSAGE
	cm.AccountId = req.AccountId
	cm.InitialChannelId = c.Id
	if err := cm.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	if _, err := c.AddMessage(cm.Id); err != nil {
		return response.NewBadRequest(err)
	}

	messageContainer, err := cm.BuildEmptyMessageContainer()
	if err != nil {
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelContainer()
	cmc.Channel = c
	cmc.IsParticipant = true
	cmc.LastMessage = messageContainer

	return response.NewOK(cmc)
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)

	if q.AccountId == 0 || q.GroupName == "" {
		return response.NewBadRequest(errors.New("request is not valid"))
	}

	channelList, err := getPrivateMessageChannels(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	cc := models.NewChannelContainers()
	if err := cc.Fetch(channelList, q); err != nil {
		return response.NewBadRequest(err)
	}

	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage()
	cc.AddUnreadCount(q.AccountId)

	return response.HandleResultAndError(cc, cc.Err())
}

func getPrivateMessageChannels(q *request.Query) ([]models.Channel, error) {
	// build query for
	c := models.NewChannel()
	channelIds := make([]int64, 0)
	query := bongo.B.DB.
		Model(c).
		Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel_participant on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and "+
		"api.channel.group_name = ? and "+
		"api.channel.type_constant = ? and "+
		"api.channel_participant.status_constant = ?",
		q.AccountId,
		q.GroupName,
		models.Channel_TYPE_PRIVATE_MESSAGE,
		models.ChannelParticipant_STATUS_ACTIVE)

	// add exempt clause if needed
	if !q.ShowExempt {
		query = query.Where("api.channel.meta_bits = ?", models.Safe)
	}

	query = query.Limit(q.Limit).
		Offset(q.Skip).
		Order("api.channel.updated_at DESC")

	rows, err := query.Rows()
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var channelId int64
		err := rows.Scan(&channelId)
		if err == nil {
			channelIds = append(channelIds, channelId)
		}
	}

	channels, err := c.FetchByIds(channelIds)
	if err != nil {
		return nil, err
	}

	return channels, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/ovh/cds/engine/api/worker"
	"github.com/ovh/cds/engine/log"
	"github.com/ovh/cds/sdk"
)

var (
	//VERSION is set with -ldflags "-X main.VERSION={{.cds.proj.version}}+{{.cds.version}}"
	VERSION = "snapshot"
	// WorkerID is a unique identifier for this worker
	WorkerID string
	// key is the token generated by the user owning the worker
	key         string
	name        string
	api         string
	model       int64
	hatchery    int64
	basedir     string
	bookedJobID int64
	logChan     chan sdk.Log
	// port of variable exporter HTTP server
	exportport int
	// current actionBuild is here to allow var export
	pbJob          sdk.PipelineBuildJob
	currentStep    int
	buildVariables []sdk.Variable
	// Git ssh configuration
	pkey           string
	gitsshPath     string
	startTimestamp time.Time
	nbActionsDone  int
	status         struct {
		Name      string    `json:"name"`
		Heartbeat time.Time `json:"heartbeat"`
		Status    string    `json:"status"`
		Model     int64     `json:"model"`
	}
	alive bool
)

var mainCmd = &cobra.Command{
	Use:   "worker",
	Short: "CDS Worker",
	Run: func(cmd *cobra.Command, args []string) {
		viper.SetEnvPrefix("cds")
		viper.AutomaticEnv()

		log.Initialize()

		log.Notice("What a good time to be alive")
		alive = true

		var err error

		name, err = os.Hostname()
		if err != nil {
			log.Notice("Cannot retrieve hostname: %s", err)
			return
		}

		hatchS := viper.GetString("hatchery")
		hatchery, err = strconv.ParseInt(hatchS, 10, 64)
		if err != nil {
			fmt.Printf("WARNING: Invalid hatchery ID (%s)", err)
		}

		api = viper.GetString("api")
		if api == "" {
			fmt.Printf("--api not provided, aborting.")
			return
		}

		key = viper.GetString("key")
		if key == "" {
			fmt.Printf("--key not provided, aborting.")
			return
		}

		givenName := viper.GetString("name")
		if givenName != "" {
			name = givenName
		}
		status.Name = name

		basedir = viper.GetString("basedir")
		if basedir == "" {
			basedir = os.TempDir()
		}

		bookedJobID = viper.GetInt64("booked_job_id")

		model = int64(viper.GetInt("model"))
		status.Model = model

		port, err := server()
		if err != nil {
			sdk.Exit("cannot bind port for worker export: %s", err)
		}
		exportport = port

		startTimestamp = time.Now()

		// start logger routine
		logChan = make(chan sdk.Log)
		go logger(logChan)

		go heartbeat()
		queuePolling()
	},
}

func init() {
	flags := mainCmd.Flags()

	flags.String("log-level", "notice", "Log Level : debug, info, notice, warning, critical")
	viper.BindPFlag("log_level", flags.Lookup("log-level"))

	flags.String("api", "", "URL of CDS API")
	viper.BindPFlag("api", flags.Lookup("api"))

	flags.String("key", "", "CDS KEY")
	viper.BindPFlag("key", flags.Lookup("key"))

	flags.Bool("single-use", false, "Exit after executing an action")
	viper.BindPFlag("single_use", flags.Lookup("single-use"))

	flags.String("name", "", "Name of worker")
	viper.BindPFlag("name", flags.Lookup("name"))

	flags.Int("model", 0, "Model of worker")
	viper.BindPFlag("model", flags.Lookup("model"))

	flags.Int("hatchery", 0, "Hatchery spawing worker")
	viper.BindPFlag("hatchery", flags.Lookup("hatchery"))

	flags.String("basedir", "", "Worker working directory")
	viper.BindPFlag("basedir", flags.Lookup("basedir"))

	flags.Int("ttl", 30, "Worker time to live (minutes)")
	viper.BindPFlag("ttl", flags.Lookup("ttl"))

	flags.Int("heartbeat", 10, "Worker heartbeat frequency")
	viper.BindPFlag("heartbeat", flags.Lookup("heartbeat"))

	flags.Int64("booked-job-id", 0, "Booked job id")
	viper.BindPFlag("booked_job_id", flags.Lookup("booked-job-id"))

	mainCmd.AddCommand(cmdExport)
	mainCmd.AddCommand(cmdUpload)
	mainCmd.AddCommand(versionCmd)
}

func main() {
	sdk.SetAgent(sdk.WorkerAgent)
	mainCmd.Execute()
}

// Will be removed when websocket conn is implemented
// for now, poll the /queue
func queuePolling() {
	firstViewQueue := true
	for {
		if WorkerID == "" {
			var info string
			if bookedJobID > 0 {
				info = fmt.Sprintf(", I was born to work on job %d", bookedJobID)
			}
			log.Notice("Registering on CDS engine%s", info)
			if err := register(api, name, key); err != nil {
				log.Notice("Cannot register: %s", err)
				time.Sleep(10 * time.Second)
				continue
			}
			alive = true
		}

		//We we've done nothing until ttl is over, let's exit
		if nbActionsDone == 0 && startTimestamp.Add(time.Duration(viper.GetInt("ttl"))*time.Minute).Before(time.Now()) {
			log.Notice("Time to exit.")
			unregister()
		}

		checkQueue(bookedJobID)
		if firstViewQueue {
			// if worker did not found booked job ID is first iteration
			// reset booked job to take another action
			bookedJobID = 0
		}

		firstViewQueue = false
		time.Sleep(4 * time.Second)
	}
}

func checkQueue(bookedJobID int64) {
	defer sdk.SetWorkerStatus(sdk.StatusWaiting)

	queue, err := sdk.GetBuildQueue()
	if err != nil {
		log.Warning("checkQueue> Cannot get build queue: %s", err)
		time.Sleep(5 * time.Second)
		WorkerID = ""
		return
	}

	log.Notice("checkQueue> %d actions in queue", len(queue))

	//Set the status to checking to avoid beeing killed while checking queue, actions and requirements
	sdk.SetWorkerStatus(sdk.StatusChecking)

	for i := range queue {
		if bookedJobID != 0 && queue[i].ID != bookedJobID {
			continue
		}

		requirementsOK := true
		// Check requirement
		log.Notice("checkQueue> Checking requirements for action [%d] %s", queue[i].ID, queue[i].Job.Action.Name)
		for _, r := range queue[i].Job.Action.Requirements {
			ok, err := checkRequirement(r)
			if err != nil {
				postCheckRequirementError(&r, err)
				requirementsOK = false
				continue
			}
			if !ok {
				requirementsOK = false
				continue
			}
		}

		if requirementsOK {
			t := ""
			if queue[i].ID != bookedJobID {
				t = ", this was my booked job"
			}
			log.Notice("checkQueue> Taking job %d%s", queue[i].ID, t)
			takeJob(queue[i], queue[i].ID == bookedJobID)
		}
	}

	if bookedJobID > 0 {
		log.Notice("checkQueue> worker born for work on job %d but job is not found in queue", bookedJobID)
	}

	if !viper.GetBool("single_use") {
		log.Notice("checkQueue> Nothing to do...")
	}
}

func postCheckRequirementError(r *sdk.Requirement, err error) {
	s := fmt.Sprintf("Error checking requirement Name=%s Type=%s Value=%s :%s", r.Name, r.Type, r.Value, err)
	sdk.Request("POST", "/queue/requirements/errors", []byte(s))
}

func takeJob(b sdk.PipelineBuildJob, isBooked bool) {
	in := worker.TakeForm{Time: time.Now()}
	if isBooked {
		in.BookedJobID = b.ID
	}

	bodyTake, errm := json.Marshal(in)
	if errm != nil {
		log.Notice("takeJob> Cannot marshal body: %s", errm)
	}

	nbActionsDone++
	gitsshPath = ""
	pkey = ""
	path := fmt.Sprintf("/queue/%d/take", b.ID)
	data, code, errr := sdk.Request("POST", path, bodyTake)
	if errr != nil {
		log.Notice("takeJob> Cannot take action %d : %s", b.Job.PipelineActionID, errr)
		return
	}
	if code != http.StatusOK {
		return
	}

	pbji := worker.PipelineBuildJobInfo{}
	if err := json.Unmarshal([]byte(data), &pbji); err != nil {
		log.Notice("takeJob> Cannot unmarshal action: %s", err)
		return
	}

	pbJob = pbji.PipelineBuildJob
	// Reset build variables
	buildVariables = nil
	start := time.Now()
	res := run(&pbji)
	res.RemoteTime = time.Now()
	res.Duration = sdk.Round(time.Since(start), time.Second).String()

	// Give time to buffered logs to be sent
	time.Sleep(3 * time.Second)

	path = fmt.Sprintf("/queue/%d/result", b.ID)
	body, errm := json.MarshalIndent(res, " ", " ")
	if errm != nil {
		log.Critical("takeJob> Cannot marshal result: %s", errm)
		unregister()
		return
	}

	code = 300
	var isThereAnyHopeLeft = 10
	for code >= 300 {
		var errre error
		_, code, errre = sdk.Request("POST", path, body)
		if code == http.StatusNotFound {
			log.Notice("takeJob> Cannot send build result: PipelineBuildJob does not exists anymore")
			unregister() // well...
			break
		}
		if errre == nil && code < 300 {
			fmt.Printf("BuildResult sent.")
			break
		}

		if errre != nil {
			log.Warning("takeJob> Cannot send build result: %s", errre)
		} else {
			log.Warning("takeJob> Cannot send build result: HTTP %d", code)
		}

		time.Sleep(5 * time.Second)
		isThereAnyHopeLeft--
		if isThereAnyHopeLeft < 0 {
			log.Notice("takeJob> Could not send built result 10 times, giving up")
			break
		}
	}

	if viper.GetBool("single_use") {
		// Give time to logs to be flushed
		time.Sleep(2 * time.Second)
		// Unregister from engine
		if err := unregister(); err != nil {
			log.Warning("takeJob> could not unregister: %s", err)
		}
	}

}

func heartbeat() {
	for {
		time.Sleep(time.Duration(viper.GetInt("heartbeat")) * time.Second)

		if !alive && viper.GetBool("single_use") {
			return
		}

		if WorkerID == "" {
			log.Notice("Disconnected from CDS engine, trying to register...")
			if err := register(api, name, key); err != nil {
				log.Notice("Cannot register: %s", err)
				continue
			}
		}

		_, code, err := sdk.Request("POST", "/worker/refresh", nil)
		if err != nil || code >= 300 {
			log.Notice("heartbeat> cannot refresh beat: %d %s", code, err)
			WorkerID = ""
		}
	}
}

func unregister() error {
	alive = false
	_, code, err := sdk.Request("POST", "/worker/unregister", nil)
	if err != nil {
		return err
	}
	if code > 300 {
		return fmt.Errorf("HTTP %d", code)
	}

	if viper.GetBool("single_use") {
		log.Notice("queuePolling> waiting 30min to be killed by hatchery, if not killed, worker will exit")
		time.Sleep(30 * time.Minute)
		os.Exit(0)
	}
	return nil
}
<commit_msg>fix (worker): do not wait if no hatchery (#401)<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/ovh/cds/engine/api/worker"
	"github.com/ovh/cds/engine/log"
	"github.com/ovh/cds/sdk"
)

var (
	//VERSION is set with -ldflags "-X main.VERSION={{.cds.proj.version}}+{{.cds.version}}"
	VERSION = "snapshot"
	// WorkerID is a unique identifier for this worker
	WorkerID string
	// key is the token generated by the user owning the worker
	key         string
	name        string
	api         string
	model       int64
	hatchery    int64
	basedir     string
	bookedJobID int64
	logChan     chan sdk.Log
	// port of variable exporter HTTP server
	exportport int
	// current actionBuild is here to allow var export
	pbJob          sdk.PipelineBuildJob
	currentStep    int
	buildVariables []sdk.Variable
	// Git ssh configuration
	pkey           string
	gitsshPath     string
	startTimestamp time.Time
	nbActionsDone  int
	status         struct {
		Name      string    `json:"name"`
		Heartbeat time.Time `json:"heartbeat"`
		Status    string    `json:"status"`
		Model     int64     `json:"model"`
	}
	alive bool
)

var mainCmd = &cobra.Command{
	Use:   "worker",
	Short: "CDS Worker",
	Run: func(cmd *cobra.Command, args []string) {
		viper.SetEnvPrefix("cds")
		viper.AutomaticEnv()

		log.Initialize()

		log.Notice("What a good time to be alive")
		alive = true

		var err error

		name, err = os.Hostname()
		if err != nil {
			log.Notice("Cannot retrieve hostname: %s", err)
			return
		}

		hatchS := viper.GetString("hatchery")
		hatchery, err = strconv.ParseInt(hatchS, 10, 64)
		if err != nil {
			fmt.Printf("WARNING: Invalid hatchery ID (%s)", err)
		}

		api = viper.GetString("api")
		if api == "" {
			fmt.Printf("--api not provided, aborting.")
			return
		}

		key = viper.GetString("key")
		if key == "" {
			fmt.Printf("--key not provided, aborting.")
			return
		}

		givenName := viper.GetString("name")
		if givenName != "" {
			name = givenName
		}
		status.Name = name

		basedir = viper.GetString("basedir")
		if basedir == "" {
			basedir = os.TempDir()
		}

		bookedJobID = viper.GetInt64("booked_job_id")

		model = int64(viper.GetInt("model"))
		status.Model = model

		port, err := server()
		if err != nil {
			sdk.Exit("cannot bind port for worker export: %s", err)
		}
		exportport = port

		startTimestamp = time.Now()

		// start logger routine
		logChan = make(chan sdk.Log)
		go logger(logChan)

		go heartbeat()
		queuePolling()
	},
}

func init() {
	flags := mainCmd.Flags()

	flags.String("log-level", "notice", "Log Level : debug, info, notice, warning, critical")
	viper.BindPFlag("log_level", flags.Lookup("log-level"))

	flags.String("api", "", "URL of CDS API")
	viper.BindPFlag("api", flags.Lookup("api"))

	flags.String("key", "", "CDS KEY")
	viper.BindPFlag("key", flags.Lookup("key"))

	flags.Bool("single-use", false, "Exit after executing an action")
	viper.BindPFlag("single_use", flags.Lookup("single-use"))

	flags.String("name", "", "Name of worker")
	viper.BindPFlag("name", flags.Lookup("name"))

	flags.Int("model", 0, "Model of worker")
	viper.BindPFlag("model", flags.Lookup("model"))

	flags.Int("hatchery", 0, "Hatchery spawing worker")
	viper.BindPFlag("hatchery", flags.Lookup("hatchery"))

	flags.String("basedir", "", "Worker working directory")
	viper.BindPFlag("basedir", flags.Lookup("basedir"))

	flags.Int("ttl", 30, "Worker time to live (minutes)")
	viper.BindPFlag("ttl", flags.Lookup("ttl"))

	flags.Int("heartbeat", 10, "Worker heartbeat frequency")
	viper.BindPFlag("heartbeat", flags.Lookup("heartbeat"))

	flags.Int64("booked-job-id", 0, "Booked job id")
	viper.BindPFlag("booked_job_id", flags.Lookup("booked-job-id"))

	mainCmd.AddCommand(cmdExport)
	mainCmd.AddCommand(cmdUpload)
	mainCmd.AddCommand(versionCmd)
}

func main() {
	sdk.SetAgent(sdk.WorkerAgent)
	mainCmd.Execute()
}

// Will be removed when websocket conn is implemented
// for now, poll the /queue
func queuePolling() {
	firstViewQueue := true
	for {
		if WorkerID == "" {
			var info string
			if bookedJobID > 0 {
				info = fmt.Sprintf(", I was born to work on job %d", bookedJobID)
			}
			log.Notice("Registering on CDS engine%s", info)
			if err := register(api, name, key); err != nil {
				log.Notice("Cannot register: %s", err)
				time.Sleep(10 * time.Second)
				continue
			}
			alive = true
		}

		//We we've done nothing until ttl is over, let's exit
		if nbActionsDone == 0 && startTimestamp.Add(time.Duration(viper.GetInt("ttl"))*time.Minute).Before(time.Now()) {
			log.Notice("Time to exit.")
			unregister()
		}

		checkQueue(bookedJobID)
		if firstViewQueue {
			// if worker did not found booked job ID is first iteration
			// reset booked job to take another action
			bookedJobID = 0
		}

		firstViewQueue = false
		time.Sleep(4 * time.Second)
	}
}

func checkQueue(bookedJobID int64) {
	defer sdk.SetWorkerStatus(sdk.StatusWaiting)

	queue, err := sdk.GetBuildQueue()
	if err != nil {
		log.Warning("checkQueue> Cannot get build queue: %s", err)
		time.Sleep(5 * time.Second)
		WorkerID = ""
		return
	}

	log.Notice("checkQueue> %d actions in queue", len(queue))

	//Set the status to checking to avoid beeing killed while checking queue, actions and requirements
	sdk.SetWorkerStatus(sdk.StatusChecking)

	for i := range queue {
		if bookedJobID != 0 && queue[i].ID != bookedJobID {
			continue
		}

		requirementsOK := true
		// Check requirement
		log.Notice("checkQueue> Checking requirements for action [%d] %s", queue[i].ID, queue[i].Job.Action.Name)
		for _, r := range queue[i].Job.Action.Requirements {
			ok, err := checkRequirement(r)
			if err != nil {
				postCheckRequirementError(&r, err)
				requirementsOK = false
				continue
			}
			if !ok {
				requirementsOK = false
				continue
			}
		}

		if requirementsOK {
			t := ""
			if queue[i].ID != bookedJobID {
				t = ", this was my booked job"
			}
			log.Notice("checkQueue> Taking job %d%s", queue[i].ID, t)
			takeJob(queue[i], queue[i].ID == bookedJobID)
		}
	}

	if bookedJobID > 0 {
		log.Notice("checkQueue> worker born for work on job %d but job is not found in queue", bookedJobID)
	}

	if !viper.GetBool("single_use") {
		log.Notice("checkQueue> Nothing to do...")
	}
}

func postCheckRequirementError(r *sdk.Requirement, err error) {
	s := fmt.Sprintf("Error checking requirement Name=%s Type=%s Value=%s :%s", r.Name, r.Type, r.Value, err)
	sdk.Request("POST", "/queue/requirements/errors", []byte(s))
}

func takeJob(b sdk.PipelineBuildJob, isBooked bool) {
	in := worker.TakeForm{Time: time.Now()}
	if isBooked {
		in.BookedJobID = b.ID
	}

	bodyTake, errm := json.Marshal(in)
	if errm != nil {
		log.Notice("takeJob> Cannot marshal body: %s", errm)
	}

	nbActionsDone++
	gitsshPath = ""
	pkey = ""
	path := fmt.Sprintf("/queue/%d/take", b.ID)
	data, code, errr := sdk.Request("POST", path, bodyTake)
	if errr != nil {
		log.Notice("takeJob> Cannot take action %d : %s", b.Job.PipelineActionID, errr)
		return
	}
	if code != http.StatusOK {
		return
	}

	pbji := worker.PipelineBuildJobInfo{}
	if err := json.Unmarshal([]byte(data), &pbji); err != nil {
		log.Notice("takeJob> Cannot unmarshal action: %s", err)
		return
	}

	pbJob = pbji.PipelineBuildJob
	// Reset build variables
	buildVariables = nil
	start := time.Now()
	res := run(&pbji)
	res.RemoteTime = time.Now()
	res.Duration = sdk.Round(time.Since(start), time.Second).String()

	// Give time to buffered logs to be sent
	time.Sleep(3 * time.Second)

	path = fmt.Sprintf("/queue/%d/result", b.ID)
	body, errm := json.MarshalIndent(res, " ", " ")
	if errm != nil {
		log.Critical("takeJob> Cannot marshal result: %s", errm)
		unregister()
		return
	}

	code = 300
	var isThereAnyHopeLeft = 10
	for code >= 300 {
		var errre error
		_, code, errre = sdk.Request("POST", path, body)
		if code == http.StatusNotFound {
			log.Notice("takeJob> Cannot send build result: PipelineBuildJob does not exists anymore")
			unregister() // well...
			break
		}
		if errre == nil && code < 300 {
			fmt.Printf("BuildResult sent.")
			break
		}

		if errre != nil {
			log.Warning("takeJob> Cannot send build result: %s", errre)
		} else {
			log.Warning("takeJob> Cannot send build result: HTTP %d", code)
		}

		time.Sleep(5 * time.Second)
		isThereAnyHopeLeft--
		if isThereAnyHopeLeft < 0 {
			log.Notice("takeJob> Could not send built result 10 times, giving up")
			break
		}
	}

	if viper.GetBool("single_use") {
		// Give time to logs to be flushed
		time.Sleep(2 * time.Second)
		// Unregister from engine
		if err := unregister(); err != nil {
			log.Warning("takeJob> could not unregister: %s", err)
		}
	}

}

func heartbeat() {
	for {
		time.Sleep(time.Duration(viper.GetInt("heartbeat")) * time.Second)

		if !alive && viper.GetBool("single_use") {
			return
		}

		if WorkerID == "" {
			log.Notice("Disconnected from CDS engine, trying to register...")
			if err := register(api, name, key); err != nil {
				log.Notice("Cannot register: %s", err)
				continue
			}
		}

		_, code, err := sdk.Request("POST", "/worker/refresh", nil)
		if err != nil || code >= 300 {
			log.Notice("heartbeat> cannot refresh beat: %d %s", code, err)
			WorkerID = ""
		}
	}
}

func unregister() error {
	alive = false
	_, code, err := sdk.Request("POST", "/worker/unregister", nil)
	if err != nil {
		return err
	}
	if code > 300 {
		return fmt.Errorf("HTTP %d", code)
	}

	if viper.GetBool("single_use") {
		if hatchery > 0 {
			log.Notice("unregister> waiting 30min to be killed by hatchery, if not killed, worker will exit")
			time.Sleep(30 * time.Minute)
		}
		log.Notice("unregister> worker will exit")
		time.Sleep(3 * time.Second)
		os.Exit(0)
	}
	return nil
}
<|endoftext|>