<commit_before>package weibo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"
	"strings"

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

const (
	libraryVersion  = "0.1"
	weiboApiVersion = "2"
	defaultBaseURL  = "https://api.weibo.com/"
	userAgent       = "go-weibo/" + libraryVersion
)

// A Client manages communication with the Weibo API.
type Client struct {
	// HTTP client used to communcate with the API.
	client *http.Client

	// Base URL for API requests.
	BaseURL *url.URL

	// User agent used when communicating with the Weibo API.
	UserAgent string

	// Services used for talking to different parts of the Weibo API.
	Statuses *StatusesService
}

// ListOptions specifies the optional parameters to various List methods that
// support pagination.
type ListOptions struct {
	// For paginated result sets, page of results to retrieve.
	Page int `url:"page,omitempty"`

	// For paginated result sets, the number of results to include per page.
	PerPage int `url:"count,omitempty"`
}

// addOptions adds the parameters in opt as URL query parameters to string.
// opt must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (string, error) {
	v := reflect.ValueOf(opt)
	if v.Kind() == reflect.Ptr && v.IsNil() {
		return s, nil
	}

	u, err := url.Parse(s)
	if err != nil {
		return s, err
	}

	qs, err := query.Values(opt)
	if err != nil {
		return s, err
	}

	u.RawQuery = qs.Encode()
	return u.String(), nil
}

// NewClient returns a new Weibo API client.  If a nil httpClient is
// provided, http.DefaultClient will be used. To use API methods which require
// authentication, provide an http.Client that will perform the authentication
// for you (such as that provided by goauth2 library).
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)

	c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent}
	c.Statuses = &StatusesService{client: c}

	return c
}

// NewRequest creates an API request.  A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If
// specified, the value pointed to by body is JSON encoded and included as the
// request body.
func (c *Client) NewRequest(method, urlString string, body interface{}) (*http.Request, error) {
	if strings.HasPrefix(urlString, "/") {
		urlString = weiboApiVersion + urlString
	} else {
		urlString = weiboApiVersion + "/" + urlString
	}

	rel, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)

	buf := new(bytes.Buffer)
	if body != nil {
		if err := json.NewEncoder(buf).Encode(body); err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	req.Header.Add("User-Agent", c.UserAgent)
	return req, nil
}

// Response is a Weibo API response.
// This wraps the standrad http.Response returned from Weibo.
// For future use, maybe.
type Response struct {
	*http.Response
}

// newResponse creates a new Response for the provided http.Response.
func newResponse(r *http.Response) *Response {
	response := &Response{Response: r}

	return response
}

// Do sends an API request and returns the API response.  The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occured.  If v implements the io.Writer
// interface, the raw response body will be written to v, without attempting
// to first decode it.
func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	response := newResponse(resp)

	if err := CheckResponse(resp); err != nil {
		// even though there was an error, we still return the response
		// in case the caller wants to inspect it further
		return response, err
	}

	if v != nil {
		if w, ok := v.(io.Writer); ok {
			io.Copy(w, resp.Body)
		} else {
			err = json.NewDecoder(resp.Body).Decode(v)
		}
	}

	return response, err
}

// An Error Response reports one or more errors caused by an API request.
//
// Weibo API docs: http://open.weibo.com/wiki/Error_code
type ErrorResponse struct {
	Response *http.Response // HTTP response that caused this error
	Message  string         `json:"message"` // error message
	Errors   []Error        `json:"errors"`  // more detail on individual errors
}

func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %v %+v",
		r.Response.Request.Method, r.Response.Request.URL,
		r.Response.StatusCode, r.Message, r.Errors)
}

// An Error reports more detail on individual error in an ErrorResponse.
//
// Weibo API docs: http://open.weibo.com/wiki/Error_code
type Error struct {
	Resource string `json:"resource"` // resource on which the error occured
	Field    string `json:"field"`    // field on which the error occured
	Code     string `json:"code"`     // validatian error code
}

func (e *Error) Error() string {
	return fmt.Sprintf("%v error caused by %v field on %v resource",
		e.Code, e.Field, e.Resource)
}

// CheckResponse checks the API response for errors, and returns them if
// present.  A response is considered an error if it has a status code outside
// the 200 range. API error responses are expected to have either no response
// body, or a JSON response body that maps to ErrorResponse.  Any other
// response body will be silently ignored.
func CheckResponse(r *http.Response) error {
	if c := r.StatusCode; 200 <= c && c <= 299 {
		return nil
	}
	errorResponse := &ErrorResponse{Response: r}
	data, err := ioutil.ReadAll(r.Body)
	if err == nil && data != nil {
		json.Unmarshal(data, errorResponse)
	}
	return errorResponse
}

// Bool is a helper routine that allocates a new bool value
// to store v and returns a pointer to it.
func Bool(v bool) *bool {
	p := new(bool)
	*p = v
	return p
}

// Int is a helper routine that allocates a new int32 value
// to store v and returns a pointer to it, but unlike Int32
// its argument value is an int.
func Int(v int) *int {
	p := new(int)
	*p = v
	return p
}

// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string {
	p := new(string)
	*p = v
	return p
}
<commit_msg>Change ErrorResponse struct as API docs descriped.<commit_after>package weibo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"
	"strings"

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

const (
	libraryVersion  = "0.1"
	weiboApiVersion = "2"
	defaultBaseURL  = "https://api.weibo.com/"
	userAgent       = "go-weibo/" + libraryVersion
)

// A Client manages communication with the Weibo API.
type Client struct {
	// HTTP client used to communcate with the API.
	client *http.Client

	// Base URL for API requests.
	BaseURL *url.URL

	// User agent used when communicating with the Weibo API.
	UserAgent string

	// Services used for talking to different parts of the Weibo API.
	Statuses *StatusesService
}

// ListOptions specifies the optional parameters to various List methods that
// support pagination.
type ListOptions struct {
	// For paginated result sets, page of results to retrieve.
	Page int `url:"page,omitempty"`

	// For paginated result sets, the number of results to include per page.
	PerPage int `url:"count,omitempty"`
}

// addOptions adds the parameters in opt as URL query parameters to string.
// opt must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (string, error) {
	v := reflect.ValueOf(opt)
	if v.Kind() == reflect.Ptr && v.IsNil() {
		return s, nil
	}

	u, err := url.Parse(s)
	if err != nil {
		return s, err
	}

	qs, err := query.Values(opt)
	if err != nil {
		return s, err
	}

	u.RawQuery = qs.Encode()
	return u.String(), nil
}

// NewClient returns a new Weibo API client.  If a nil httpClient is
// provided, http.DefaultClient will be used. To use API methods which require
// authentication, provide an http.Client that will perform the authentication
// for you (such as that provided by goauth2 library).
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)

	c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent}
	c.Statuses = &StatusesService{client: c}

	return c
}

// NewRequest creates an API request.  A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If
// specified, the value pointed to by body is JSON encoded and included as the
// request body.
func (c *Client) NewRequest(method, urlString string, body interface{}) (*http.Request, error) {
	if strings.HasPrefix(urlString, "/") {
		urlString = weiboApiVersion + urlString
	} else {
		urlString = weiboApiVersion + "/" + urlString
	}

	rel, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)

	buf := new(bytes.Buffer)
	if body != nil {
		if err := json.NewEncoder(buf).Encode(body); err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	req.Header.Add("User-Agent", c.UserAgent)
	return req, nil
}

// Response is a Weibo API response.
// This wraps the standrad http.Response returned from Weibo.
// For future use, maybe.
type Response struct {
	*http.Response
}

// newResponse creates a new Response for the provided http.Response.
func newResponse(r *http.Response) *Response {
	response := &Response{Response: r}

	return response
}

// Do sends an API request and returns the API response.  The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occured.  If v implements the io.Writer
// interface, the raw response body will be written to v, without attempting
// to first decode it.
func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	response := newResponse(resp)

	if err := CheckResponse(resp); err != nil {
		// even though there was an error, we still return the response
		// in case the caller wants to inspect it further
		return response, err
	}

	if v != nil {
		if w, ok := v.(io.Writer); ok {
			io.Copy(w, resp.Body)
		} else {
			err = json.NewDecoder(resp.Body).Decode(v)
		}
	}

	return response, err
}

// An Error Response reports one or more errors caused by an API request.
//
// Weibo API docs: http://open.weibo.com/wiki/Error_code
type ErrorResponse struct {
	Response   *http.Response // HTTP response that caused this error
	RequestURL string         `json:"request"`    // request on which the error occured
	ErrorCode  int            `json:"error_code"` // error_code
	Message    string         `json:"error"`      // error message
}

func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %v %v",
		r.Response.Request.Method, r.RequestURL,
		r.Response.StatusCode, r.ErrorCode, r.Message)
}

// CheckResponse checks the API response for errors, and returns them if
// present.  A response is considered an error if it has a status code outside
// the 200 range. API error responses are expected to have either no response
// body, or a JSON response body that maps to ErrorResponse.  Any other
// response body will be silently ignored.
func CheckResponse(r *http.Response) error {
	if c := r.StatusCode; 200 <= c && c <= 299 {
		return nil
	}
	errorResponse := &ErrorResponse{Response: r}
	data, err := ioutil.ReadAll(r.Body)
	if err == nil && data != nil {
		json.Unmarshal(data, errorResponse)
	}
	return errorResponse
}

// Bool is a helper routine that allocates a new bool value
// to store v and returns a pointer to it.
func Bool(v bool) *bool {
	p := new(bool)
	*p = v
	return p
}

// Int is a helper routine that allocates a new int32 value
// to store v and returns a pointer to it, but unlike Int32
// its argument value is an int.
func Int(v int) *int {
	p := new(int)
	*p = v
	return p
}

// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string {
	p := new(string)
	*p = v
	return p
}
<|endoftext|>


<commit_before>package main
import "net/http"
import "time"
import "github.com/PuerkitoBio/goquery"

func StyleGetTo(crawinstanceuuid,fireurl,uid string,pageno int,dbe *ExecTimeDbS)int,error{

  conf,err:=dbe.LoadConfigure()

  if err != nil {
    return 0,err
  }

  var cookie,ua string

  err=dbe.Dbc.QueryRow("SELECT crawcookie,crawua FROM crawinstance WHERE crawinstanceuuid=?",crawinstanceuuid).Scan(&cookie,&ua)

  if err != nil {
    return 0,err
  }

  req, err := http.NewRequest("GET", fireurl, nil)

  if err != nil {
    return 0,err
  }

  req.Header.Add("Cookie",cookie)

  req.Header.Add("User-Agent",ua)

  client := &http.Client{}

  resp, err := client.Do(req)

  if err != nil {
    return 0,err
  }

  body, err := ioutil.ReadAll(resp.Body)

  if err != nil {
    return 0,err
  }
  bds:=string(body)
  res, err =  dbe.Dbc.Exec("INSERT INTO crawbuffer(uid,time,crawinstanceuuid,firedurl,ctx,pageno) VALUES (?,?,?,?,?,?)",uid,time.Now().Unix(),crawinstanceuuid,fireurl,bds,pageno)

  if err != nil {
    return 0,err
  }

  return len(bds),nil

}

func StyleParseNextPage(crawinstanceuuid,fireurl,uid string,pageno int,dbe *ExecTimeDbS)int,error{

  var ctx string

  err:=dbe.Dbc.QueryRow("SELECT ctx FROM crawbuffer WHERE crawinstanceuuid=? AND uid=? AND pageno=? AND firedurl=?",crawinstanceuuid,uid,pageno,fireurl).Scan(&ctx)

  if err != nil {
    return 0,err
  }

}
<commit_msg>ParsePageNumber<commit_after>package main
import "net/http"
import "time"
import "github.com/PuerkitoBio/goquery"
import "strconv"

func StyleGetTo(crawinstanceuuid,fireurl,uid string,pageno int,dbe *ExecTimeDbS)int,error{

  conf,err:=dbe.LoadConfigure()

  if err != nil {
    return 0,err
  }

  var cookie,ua string

  err=dbe.Dbc.QueryRow("SELECT crawcookie,crawua FROM crawinstance WHERE crawinstanceuuid=?",crawinstanceuuid).Scan(&cookie,&ua)

  if err != nil {
    return 0,err
  }

  req, err := http.NewRequest("GET", fireurl, nil)

  if err != nil {
    return 0,err
  }

  req.Header.Add("Cookie",cookie)

  req.Header.Add("User-Agent",ua)

  client := &http.Client{}

  resp, err := client.Do(req)

  if err != nil {
    return 0,err
  }

  body, err := ioutil.ReadAll(resp.Body)

  if err != nil {
    return 0,err
  }
  bds:=string(body)
  res, err =  dbe.Dbc.Exec("INSERT INTO crawbuffer(uid,time,crawinstanceuuid,firedurl,ctx,pageno) VALUES (?,?,?,?,?,?)",uid,time.Now().Unix(),crawinstanceuuid,fireurl,bds,pageno)

  if err != nil {
    return 0,err
  }

  return len(bds),nil

}

func StyleParseNextPage(crawinstanceuuid,fireurl,uid string,pageno int,dbe *ExecTimeDbS)int,int,error{

  var ctx string

  err:=dbe.Dbc.QueryRow("SELECT ctx FROM crawbuffer WHERE crawinstanceuuid=? AND uid=? AND pageno=? AND firedurl=?",crawinstanceuuid,uid,pageno,fireurl).Scan(&ctx)

  if err != nil {
    return -1,err
  }

  gq:=goquery.NewDocumentFromReader(strings.NewReader(ctx))

  s:=gq.Find("div.pa#pagelist form div").First().Children().Last().Text()

  if s==""{
    return -1,errors.New("Assert Fail:no page count")
  }

  pagerx,err:=regexp.Compile(`(?:[\t\n\v\f\r ])*?(?P<currentpage>(?:\d)*)/(?P<maxpage>(?:\d)*)页`)
  //https://regex101.com/r/wQ6mY2/1

  if err != nil {
    return -1,err
  }

  sf:=pagerx.FindStringSubmatch(s)

  rs:=strconv.Atoi(sf[1])//maxpage
  cs:=strconv.Atoi(sf[0])//currentpage

  return cs,rs,nil
}
<|endoftext|>


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

package html

import (
	"fmt"
	"github.com/andreaskoch/allmark/path"
	"github.com/andreaskoch/allmark/repository"
	"github.com/andreaskoch/allmark/util"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	// filepreview: [*description text*](*file path*)
	filePreviewPattern = regexp.MustCompile(`filepreview: \[([^\]]+)\]\(([^)]+)\)`)
)

func renderFilePreview(fileIndex *repository.FileIndex, pathProvider *path.Provider, markdown string) string {

	for {

		found, matches := util.IsMatch(markdown, filePreviewPattern)
		if !found || (found && len(matches) != 3) {
			break
		}

		// parameters
		originalText := strings.TrimSpace(matches[0])
		title := strings.TrimSpace(matches[1])
		path := strings.TrimSpace(matches[2])

		// get the file path
		files := fileIndex.FilesByPath(path, allFiles)

		if len(files) == 0 {

			// file not found remove entry
			msg := fmt.Sprintf("", path)
			markdown = strings.Replace(markdown, originalText, msg, 1)
			continue

		}

		matchedFile := files[0]
		realFilePath := matchedFile.Path()
		fileRoute := pathProvider.GetWebRoute(matchedFile)
		displayPath := strings.TrimPrefix(path, "files/")
		linkTitle := fmt.Sprintf("%s (%s)", title, displayPath)

		// read the file
		content, contentType, err := getFileContent(realFilePath)
		if err != nil {

			// file not found remove entry
			msg := fmt.Sprintf("", path, err)
			markdown = strings.Replace(markdown, originalText, msg, 1)
			continue

		}

		// assemble the file preview code
		previewCode := fmt.Sprintf(`<section class="filepreview filepreview-%s">`, contentType)
		previewCode += fmt.Sprintf("\n
%s
\n", fileRoute, linkTitle, title)

		previewCode += "
\n"
		if contentType != "" {
			previewCode += fmt.Sprintf(`<code class="%s">%s</code>`, contentType, content)
		} else {
			previewCode += fmt.Sprintf("%s", content)
		}
		previewCode += "\n
"

		previewCode += fmt.Sprintf("
\n\n")

		// replace markdown with image gallery
		markdown = strings.Replace(markdown, originalText, previewCode, 1)

	}

	return markdown
}

func getFileContent(path string) (fileContent string, contentType string, err error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return "", "", err
	}

	fileContent = string(content)
	contentType = getFileType(path)

	return fileContent, contentType, nil
}

func getFileType(path string) string {

	// get the file extension
	extension := strings.ToLower(strings.TrimSpace(filepath.Ext(path)))

	// remove the leading dot
	extension = strings.TrimPrefix(extension, ".")

	return extension
}
<commit_msg>Bug fix for the filepreview extension. The file content must be html encoded - html tags must be escaped.<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package html

import (
	"fmt"
	"github.com/andreaskoch/allmark/path"
	"github.com/andreaskoch/allmark/repository"
	"github.com/andreaskoch/allmark/util"
	"html"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	// filepreview: [*description text*](*file path*)
	filePreviewPattern = regexp.MustCompile(`filepreview: \[([^\]]+)\]\(([^)]+)\)`)
)

func renderFilePreview(fileIndex *repository.FileIndex, pathProvider *path.Provider, markdown string) string {

	for {

		found, matches := util.IsMatch(markdown, filePreviewPattern)
		if !found || (found && len(matches) != 3) {
			break
		}

		// parameters
		originalText := strings.TrimSpace(matches[0])
		title := strings.TrimSpace(matches[1])
		path := strings.TrimSpace(matches[2])

		// get the file path
		files := fileIndex.FilesByPath(path, allFiles)

		if len(files) == 0 {

			// file not found remove entry
			msg := fmt.Sprintf("", path)
			markdown = strings.Replace(markdown, originalText, msg, 1)
			continue

		}

		matchedFile := files[0]
		realFilePath := matchedFile.Path()
		fileRoute := pathProvider.GetWebRoute(matchedFile)
		displayPath := strings.TrimPrefix(path, "files/")
		linkTitle := fmt.Sprintf("%s (%s)", title, displayPath)

		// read the file
		content, contentType, err := getFileContent(realFilePath)
		if err != nil {

			// file not found remove entry
			msg := fmt.Sprintf("", path, err)
			markdown = strings.Replace(markdown, originalText, msg, 1)
			continue

		}

		// assemble the file preview code
		previewCode := fmt.Sprintf(`<section class="filepreview filepreview-%s">`, contentType)
		previewCode += fmt.Sprintf("\n
%s
\n", fileRoute, linkTitle, title)

		previewCode += "
\n"
		if contentType != "" {
			previewCode += fmt.Sprintf(`<code class="%s">%s</code>`, contentType, content)
		} else {
			previewCode += fmt.Sprintf("%s", content)
		}
		previewCode += "\n
"

		previewCode += fmt.Sprintf("
\n\n")

		// replace markdown with image gallery
		markdown = strings.Replace(markdown, originalText, previewCode, 1)

	}

	return markdown
}

func getFileContent(path string) (fileContent string, contentType string, err error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return "", "", err
	}

	// convert to string
	fileContent = string(content)

	// escape html charachters
	fileContent = html.EscapeString(fileContent)

	// get the content type
	contentType = getFileType(path)

	return fileContent, contentType, nil
}

func getFileType(path string) string {

	// get the file extension
	extension := strings.ToLower(strings.TrimSpace(filepath.Ext(path)))

	// remove the leading dot
	extension = strings.TrimPrefix(extension, ".")

	return extension
}
<|endoftext|>


<commit_before>package runtime

import (
	"net/http"
	"strings"

	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
)

const metadataHeaderPrefix = "Grpc-Metadata-"
const metadataTrailerPrefix = "Grpc-Trailer-"

/*
AnnotateContext adds context information such as metadata from the request.

If there are no metadata headers in the request, then the context returned
will be the same context.
*/
func AnnotateContext(ctx context.Context, req *http.Request) context.Context {
	var pairs []string
	for key, vals := range req.Header {
		for _, val := range vals {
			if key == "Authorization" {
				pairs = append(pairs, key, val)
				continue
			}
			if strings.HasPrefix(key, metadataHeaderPrefix) {
				pairs = append(pairs, key[len(metadataHeaderPrefix):], val)
			}
		}
	}

	if len(pairs) == 0 {
		return ctx
	}
	return metadata.NewContext(ctx, metadata.Pairs(pairs...))
}

// ServerMetadata consists of metadata sent from gRPC server.
type ServerMetadata struct {
	HeaderMD  metadata.MD
	TrailerMD metadata.MD
}

type serverMetadataKey struct{}

// NewServerMetadataContext creates a new context with ServerMetadata
func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context {
	return context.WithValue(ctx, serverMetadataKey{}, md)
}

// ServerMetadataFromContext returns the ServerMetadata in ctx
func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) {
	md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata)
	return
}
<commit_msg>make Authorization header check case-insensitive to comply with RFC 2616 4.2<commit_after>package runtime

import (
	"net/http"
	"strings"

	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
)

const metadataHeaderPrefix = "Grpc-Metadata-"
const metadataTrailerPrefix = "Grpc-Trailer-"

/*
AnnotateContext adds context information such as metadata from the request.

If there are no metadata headers in the request, then the context returned
will be the same context.
*/
func AnnotateContext(ctx context.Context, req *http.Request) context.Context {
	var pairs []string
	for key, vals := range req.Header {
		for _, val := range vals {
			if strings.ToLower(key) == "authorization" {
				pairs = append(pairs, key, val)
				continue
			}
			if strings.HasPrefix(key, metadataHeaderPrefix) {
				pairs = append(pairs, key[len(metadataHeaderPrefix):], val)
			}
		}
	}

	if len(pairs) == 0 {
		return ctx
	}
	return metadata.NewContext(ctx, metadata.Pairs(pairs...))
}

// ServerMetadata consists of metadata sent from gRPC server.
type ServerMetadata struct {
	HeaderMD  metadata.MD
	TrailerMD metadata.MD
}

type serverMetadataKey struct{}

// NewServerMetadataContext creates a new context with ServerMetadata
func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context {
	return context.WithValue(ctx, serverMetadataKey{}, md)
}

// ServerMetadataFromContext returns the ServerMetadata in ctx
func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) {
	md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata)
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes 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 simulator

import (
	"fmt"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/autoscaler/cluster-autoscaler/utils/drain"
	api "k8s.io/kubernetes/pkg/api"
	apiv1 "k8s.io/kubernetes/pkg/api/v1"
	policyv1 "k8s.io/kubernetes/pkg/apis/policy/v1beta1"
	client "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)

// FastGetPodsToMove returns a list of pods that should be moved elsewhere if the node
// is drained. Raises error if there is an unreplicated pod and force option was not specified.
// Based on kubectl drain code. It makes an assumption that RC, DS, Jobs and RS were deleted
// along with their pods (no abandoned pods with dangling created-by annotation). Usefull for fast
// checks.
func FastGetPodsToMove(nodeInfo *schedulercache.NodeInfo, skipNodesWithSystemPods bool, skipNodesWithLocalStorage bool,
	pdbs []*policyv1.PodDisruptionBudget) ([]*apiv1.Pod, error) {
	pods, err := drain.GetPodsForDeletionOnNodeDrain(
		nodeInfo.Pods(),
		api.Codecs.UniversalDecoder(),
		false,
		skipNodesWithSystemPods,
		skipNodesWithLocalStorage,
		false,
		nil,
		0,
		time.Now())

	if err != nil {
		return pods, err
	}
	if err := checkPdbs(pods, pdbs); err != nil {
		return []*apiv1.Pod{}, err
	}

	return pods, nil
}

// DetailedGetPodsForMove returns a list of pods that should be moved elsewhere if the node
// is drained. Raises error if there is an unreplicated pod and force option was not specified.
// Based on kubectl drain code. It checks whether RC, DS, Jobs and RS that created these pods
// still exist.
func DetailedGetPodsForMove(nodeInfo *schedulercache.NodeInfo, skipNodesWithSystemPods bool,
	skipNodesWithLocalStorage bool, client client.Interface, minReplicaCount int32,
	pdbs []*policyv1.PodDisruptionBudget) ([]*apiv1.Pod, error) {
	pods, err := drain.GetPodsForDeletionOnNodeDrain(
		nodeInfo.Pods(),
		api.Codecs.UniversalDecoder(),
		false,
		skipNodesWithSystemPods,
		skipNodesWithLocalStorage,
		true,
		client,
		minReplicaCount,
		time.Now())
	if err != nil {
		return pods, err
	}
	if err := checkPdbs(pods, pdbs); err != nil {
		return []*apiv1.Pod{}, err
	}

	return pods, nil
}

func checkPdbs(pods []*apiv1.Pod, pdbs []*policyv1.PodDisruptionBudget) error {
	// TODO: make it more efficient.
	for _, pdb := range pdbs {
		selector, err := metav1.LabelSelectorAsSelector(pdb.Spec.Selector)
		if err != nil {
			return err
		}
		for _, pod := range pods {
			if selector.Matches(labels.Set(pod.Labels)) {
				if pdb.Status.PodDisruptionsAllowed < 1 {
					return fmt.Errorf("no enough pod disruption budget to move %s/%s", pod.Namespace, pod.Name)
				}
			}
		}
	}
	return nil
}
<commit_msg>Add checking namespace to matching pods with PDBs<commit_after>/*
Copyright 2015 The Kubernetes 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 simulator

import (
	"fmt"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/autoscaler/cluster-autoscaler/utils/drain"
	api "k8s.io/kubernetes/pkg/api"
	apiv1 "k8s.io/kubernetes/pkg/api/v1"
	policyv1 "k8s.io/kubernetes/pkg/apis/policy/v1beta1"
	client "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)

// FastGetPodsToMove returns a list of pods that should be moved elsewhere if the node
// is drained. Raises error if there is an unreplicated pod and force option was not specified.
// Based on kubectl drain code. It makes an assumption that RC, DS, Jobs and RS were deleted
// along with their pods (no abandoned pods with dangling created-by annotation). Usefull for fast
// checks.
func FastGetPodsToMove(nodeInfo *schedulercache.NodeInfo, skipNodesWithSystemPods bool, skipNodesWithLocalStorage bool,
	pdbs []*policyv1.PodDisruptionBudget) ([]*apiv1.Pod, error) {
	pods, err := drain.GetPodsForDeletionOnNodeDrain(
		nodeInfo.Pods(),
		api.Codecs.UniversalDecoder(),
		false,
		skipNodesWithSystemPods,
		skipNodesWithLocalStorage,
		false,
		nil,
		0,
		time.Now())

	if err != nil {
		return pods, err
	}
	if err := checkPdbs(pods, pdbs); err != nil {
		return []*apiv1.Pod{}, err
	}

	return pods, nil
}

// DetailedGetPodsForMove returns a list of pods that should be moved elsewhere if the node
// is drained. Raises error if there is an unreplicated pod and force option was not specified.
// Based on kubectl drain code. It checks whether RC, DS, Jobs and RS that created these pods
// still exist.
func DetailedGetPodsForMove(nodeInfo *schedulercache.NodeInfo, skipNodesWithSystemPods bool,
	skipNodesWithLocalStorage bool, client client.Interface, minReplicaCount int32,
	pdbs []*policyv1.PodDisruptionBudget) ([]*apiv1.Pod, error) {
	pods, err := drain.GetPodsForDeletionOnNodeDrain(
		nodeInfo.Pods(),
		api.Codecs.UniversalDecoder(),
		false,
		skipNodesWithSystemPods,
		skipNodesWithLocalStorage,
		true,
		client,
		minReplicaCount,
		time.Now())
	if err != nil {
		return pods, err
	}
	if err := checkPdbs(pods, pdbs); err != nil {
		return []*apiv1.Pod{}, err
	}

	return pods, nil
}

func checkPdbs(pods []*apiv1.Pod, pdbs []*policyv1.PodDisruptionBudget) error {
	// TODO: make it more efficient.
	for _, pdb := range pdbs {
		selector, err := metav1.LabelSelectorAsSelector(pdb.Spec.Selector)
		if err != nil {
			return err
		}
		for _, pod := range pods {
			if pod.Namespace == pdb.Namespace && selector.Matches(labels.Set(pod.Labels)) {
				if pdb.Status.PodDisruptionsAllowed < 1 {
					return fmt.Errorf("no enough pod disruption budget to move %s/%s", pod.Namespace, pod.Name)
				}
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes 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 version

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "1.17.0-beta.1"
<commit_msg>Bump Cluster Autoscaler version to 1.17-beta.2<commit_after>/*
Copyright 2016 The Kubernetes 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 version

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "1.17.0-beta.2"
<|endoftext|>


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

package diskformatter_test

import (
	"errors"
	"time"

	"github.com/juju/names"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/api/watcher"
	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/storage"
	coretesting "github.com/juju/juju/testing"
	"github.com/juju/juju/worker/diskformatter"
	"github.com/juju/testing"
)

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

type DiskFormatterWorkerSuite struct {
	coretesting.BaseSuite
}

func (s *DiskFormatterWorkerSuite) TestWorker(c *gc.C) {
	ids := []string{
		"0", "1", "2", "3", "4", "5",
	}

	blockDeviceResults := []params.BlockDeviceResult{{
		Result: storage.BlockDevice{
			Name:       "0",
			DeviceName: "sda",
			Label:      "dev0-label",
			UUID:       "9aade75c-6528-4acf-ab69-258b8dc51798",
		},
	}, {
		Result: storage.BlockDevice{
			Name:           "1",
			DeviceName:     "sdb",
			UUID:           "edc2348a-a2bc-4b15-b7f3-cb951b3489ad",
			FilesystemType: "btrfs",
		},
	}, {
		Result: storage.BlockDevice{
			Name:       "2",
			DeviceName: "sdc",
		},
	}, {
		Result: storage.BlockDevice{
			Name:       "3",
			DeviceName: "sdd",
		},
	}, {
		Result: storage.BlockDevice{
			Name:       "4",
			DeviceName: "sde",
		},
	}, {
		Error: &params.Error{
			Code:    params.CodeNotFound,
			Message: "block device 5 not found",
		},
	}}

	blockDeviceStorageInstanceResults := []params.StorageInstanceResult{{
		Result: storage.StorageInstance{
			Id:   "needs-a-filesystem",
			Kind: storage.StorageKindFilesystem,
		},
	}, {
		Result: storage.StorageInstance{
			Id:   "already-has-a-filesystem",
			Kind: storage.StorageKindFilesystem,
		},
	}, {
		Result: storage.StorageInstance{
			Id:   "doesnt-need-a-filesystem",
			Kind: storage.StorageKindBlock,
		},
	}, {
		Error: &params.Error{
			Code:    params.CodeNotAssigned,
			Message: "3 is not assigned to a storage instance",
		},
	}}

	accessor := &mockBlockDeviceAccessor{
		changes: make(chan []string),
		blockDevice: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
			expect := make([]names.DiskTag, len(ids))
			for i, id := range ids {
				expect[i] = names.NewDiskTag(id)
			}
			c.Assert(tags, gc.DeepEquals, expect)
			return params.BlockDeviceResults{blockDeviceResults}, nil
		},
		blockDeviceStorageInstance: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			expect := make([]names.DiskTag, 0, len(blockDeviceResults))
			for i, result := range blockDeviceResults {
				if result.Error != nil {
					continue
				}
				expect = append(expect, names.NewDiskTag(ids[i]))
			}
			c.Assert(tags, gc.DeepEquals, expect)
			return params.StorageInstanceResults{blockDeviceStorageInstanceResults}, nil
		},
	}

	testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4")

	w := diskformatter.NewWorker(accessor)
	accessor.changes <- ids
	done := make(chan struct{})
	go func() {
		w.Kill()
		w.Wait()
		close(done)
	}()

	select {
	case <-done:
		testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label")
	case <-time.After(coretesting.LongWait):
		c.Fatalf("timed out waiting for diskformatter to update")
	}
}

func (s *DiskFormatterWorkerSuite) TestMakeDefaultFilesystem(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevice: func([]names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
				Result: storage.BlockDevice{
					Name:       "0",
					DeviceName: "sda",
					Label:      "dev0-label",
					UUID:       "9aade75c-6528-4acf-ab69-258b8dc51798",
				},
			}}}, nil
		},
		blockDeviceStorageInstance: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			return params.StorageInstanceResults{[]params.StorageInstanceResult{{
				Result: storage.StorageInstance{
					Id:   "needs-a-filesystem",
					Kind: storage.StorageKindFilesystem,
				},
			}}}, nil
		},
	}

	testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4")
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.IsNil)
	testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label")
}

func (s *DiskFormatterWorkerSuite) TestBlockDeviceError(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevice: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{}, errors.New("BlockDevice failed")
		},
	}
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.ErrorMatches, "cannot get block devices: BlockDevice failed")
}

func (s *DiskFormatterWorkerSuite) TestBlockDeviceStorageInstanceError(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevice: func([]names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
				Result: storage.BlockDevice{Name: "0", DeviceName: "sda"},
			}}}, nil
		},
		blockDeviceStorageInstance: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			return params.StorageInstanceResults{}, errors.New("BlockDeviceStorageInstance failed")
		},
	}
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.ErrorMatches, "cannot get assigned storage instances: BlockDeviceStorageInstance failed")
}

func (s *DiskFormatterWorkerSuite) TestCannotMakeFilesystem(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevice: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
				Result: storage.BlockDevice{Name: "0", DeviceName: "sda"},
			}}}, nil
		},
		blockDeviceStorageInstance: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			return params.StorageInstanceResults{[]params.StorageInstanceResult{{
				Result: storage.StorageInstance{
					Id:   "needs-a-filesystem",
					Kind: storage.StorageKindFilesystem,
				},
			}}}, nil
		},
	}
	// Failure to create a filesystem should not cause the handler to error.
	testing.PatchExecutableThrowError(c, s, "mkfs.ext4", 1)
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.IsNil)
}

type mockBlockDeviceAccessor struct {
	changes                    chan []string
	blockDevice                func([]names.DiskTag) (params.BlockDeviceResults, error)
	blockDeviceStorageInstance func([]names.DiskTag) (params.StorageInstanceResults, error)
}

func (m *mockBlockDeviceAccessor) Changes() <-chan []string {
	return m.changes
}

func (m *mockBlockDeviceAccessor) Stop() error {
	return nil
}

func (m *mockBlockDeviceAccessor) Err() error {
	return nil
}

func (m *mockBlockDeviceAccessor) WatchBlockDevices() (watcher.StringsWatcher, error) {
	return m, nil
}

func (m *mockBlockDeviceAccessor) BlockDevice(tags []names.DiskTag) (params.BlockDeviceResults, error) {
	return m.blockDevice(tags)
}

func (m *mockBlockDeviceAccessor) BlockDeviceStorageInstance(tags []names.DiskTag) (params.StorageInstanceResults, error) {
	return m.blockDeviceStorageInstance(tags)
}
<commit_msg>worker/diskformatter: rename mock methods<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package diskformatter_test

import (
	"errors"
	"time"

	"github.com/juju/names"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/api/watcher"
	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/storage"
	coretesting "github.com/juju/juju/testing"
	"github.com/juju/juju/worker/diskformatter"
	"github.com/juju/testing"
)

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

type DiskFormatterWorkerSuite struct {
	coretesting.BaseSuite
}

func (s *DiskFormatterWorkerSuite) TestWorker(c *gc.C) {
	ids := []string{
		"0", "1", "2", "3", "4", "5",
	}

	blockDeviceResults := []params.BlockDeviceResult{{
		Result: storage.BlockDevice{
			Name:       "0",
			DeviceName: "sda",
			Label:      "dev0-label",
			UUID:       "9aade75c-6528-4acf-ab69-258b8dc51798",
		},
	}, {
		Result: storage.BlockDevice{
			Name:           "1",
			DeviceName:     "sdb",
			UUID:           "edc2348a-a2bc-4b15-b7f3-cb951b3489ad",
			FilesystemType: "btrfs",
		},
	}, {
		Result: storage.BlockDevice{
			Name:       "2",
			DeviceName: "sdc",
		},
	}, {
		Result: storage.BlockDevice{
			Name:       "3",
			DeviceName: "sdd",
		},
	}, {
		Result: storage.BlockDevice{
			Name:       "4",
			DeviceName: "sde",
		},
	}, {
		Error: &params.Error{
			Code:    params.CodeNotFound,
			Message: "block device 5 not found",
		},
	}}

	blockDeviceStorageInstanceResults := []params.StorageInstanceResult{{
		Result: storage.StorageInstance{
			Id:   "needs-a-filesystem",
			Kind: storage.StorageKindFilesystem,
		},
	}, {
		Result: storage.StorageInstance{
			Id:   "already-has-a-filesystem",
			Kind: storage.StorageKindFilesystem,
		},
	}, {
		Result: storage.StorageInstance{
			Id:   "doesnt-need-a-filesystem",
			Kind: storage.StorageKindBlock,
		},
	}, {
		Error: &params.Error{
			Code:    params.CodeNotAssigned,
			Message: "3 is not assigned to a storage instance",
		},
	}}

	accessor := &mockBlockDeviceAccessor{
		changes: make(chan []string),
		blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
			expect := make([]names.DiskTag, len(ids))
			for i, id := range ids {
				expect[i] = names.NewDiskTag(id)
			}
			c.Assert(tags, gc.DeepEquals, expect)
			return params.BlockDeviceResults{blockDeviceResults}, nil
		},
		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			expect := make([]names.DiskTag, 0, len(blockDeviceResults))
			for i, result := range blockDeviceResults {
				if result.Error != nil {
					continue
				}
				expect = append(expect, names.NewDiskTag(ids[i]))
			}
			c.Assert(tags, gc.DeepEquals, expect)
			return params.StorageInstanceResults{blockDeviceStorageInstanceResults}, nil
		},
	}

	testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4")

	w := diskformatter.NewWorker(accessor)
	accessor.changes <- ids
	done := make(chan struct{})
	go func() {
		w.Kill()
		w.Wait()
		close(done)
	}()

	select {
	case <-done:
		testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label")
	case <-time.After(coretesting.LongWait):
		c.Fatalf("timed out waiting for diskformatter to update")
	}
}

func (s *DiskFormatterWorkerSuite) TestMakeDefaultFilesystem(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevices: func([]names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
				Result: storage.BlockDevice{
					Name:       "0",
					DeviceName: "sda",
					Label:      "dev0-label",
					UUID:       "9aade75c-6528-4acf-ab69-258b8dc51798",
				},
			}}}, nil
		},
		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			return params.StorageInstanceResults{[]params.StorageInstanceResult{{
				Result: storage.StorageInstance{
					Id:   "needs-a-filesystem",
					Kind: storage.StorageKindFilesystem,
				},
			}}}, nil
		},
	}

	testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4")
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.IsNil)
	testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label")
}

func (s *DiskFormatterWorkerSuite) TestBlockDeviceError(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{}, errors.New("BlockDevice failed")
		},
	}
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.ErrorMatches, "cannot get block devices: BlockDevice failed")
}

func (s *DiskFormatterWorkerSuite) TestBlockDeviceStorageInstanceError(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevices: func([]names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
				Result: storage.BlockDevice{Name: "0", DeviceName: "sda"},
			}}}, nil
		},
		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			return params.StorageInstanceResults{}, errors.New("BlockDeviceStorageInstance failed")
		},
	}
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.ErrorMatches, "cannot get assigned storage instances: BlockDeviceStorageInstance failed")
}

func (s *DiskFormatterWorkerSuite) TestCannotMakeFilesystem(c *gc.C) {
	accessor := &mockBlockDeviceAccessor{
		blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
				Result: storage.BlockDevice{Name: "0", DeviceName: "sda"},
			}}}, nil
		},
		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
			return params.StorageInstanceResults{[]params.StorageInstanceResult{{
				Result: storage.StorageInstance{
					Id:   "needs-a-filesystem",
					Kind: storage.StorageKindFilesystem,
				},
			}}}, nil
		},
	}
	// Failure to create a filesystem should not cause the handler to error.
	testing.PatchExecutableThrowError(c, s, "mkfs.ext4", 1)
	formatter := diskformatter.NewDiskFormatter(accessor)
	err := formatter.Handle([]string{"0"})
	c.Assert(err, gc.IsNil)
}

type mockBlockDeviceAccessor struct {
	changes                     chan []string
	blockDevices                func([]names.DiskTag) (params.BlockDeviceResults, error)
	blockDeviceStorageInstances func([]names.DiskTag) (params.StorageInstanceResults, error)
}

func (m *mockBlockDeviceAccessor) Changes() <-chan []string {
	return m.changes
}

func (m *mockBlockDeviceAccessor) Stop() error {
	return nil
}

func (m *mockBlockDeviceAccessor) Err() error {
	return nil
}

func (m *mockBlockDeviceAccessor) WatchBlockDevices() (watcher.StringsWatcher, error) {
	return m, nil
}

func (m *mockBlockDeviceAccessor) BlockDevices(tags []names.DiskTag) (params.BlockDeviceResults, error) {
	return m.blockDevices(tags)
}

func (m *mockBlockDeviceAccessor) BlockDeviceStorageInstances(tags []names.DiskTag) (params.StorageInstanceResults, error) {
	return m.blockDeviceStorageInstances(tags)
}
<|endoftext|>


<commit_before>package collectors

import (
	"io/ioutil"
	"net/http"
	"os/exec"
	"reflect"
	"regexp"
	"runtime"
	"sync"
	"time"

	"bosun.org/metadata"
	"bosun.org/opentsdb"
	"bosun.org/slog"
)

type IntervalCollector struct {
	F        func() (opentsdb.MultiDataPoint, error)
	Interval time.Duration // defaults to DefaultFreq if unspecified
	Enable   func() bool
	name     string
	init     func()

	// internal use
	sync.Mutex
	enabled bool
}

func (c *IntervalCollector) Init() {
	if c.init != nil {
		c.init()
	}
}

func (c *IntervalCollector) Run(dpchan chan<- *opentsdb.DataPoint) {
	if c.Enable != nil {
		go func() {
			for {
				next := time.After(time.Minute * 5)
				c.Lock()
				c.enabled = c.Enable()
				c.Unlock()
				<-next
			}
		}()
	}
	tags := opentsdb.TagSet{"collector": c.Name(), "os": runtime.GOOS}
	for {
		interval := c.Interval
		if interval == 0 {
			interval = DefaultFreq
		}
		next := time.After(interval)
		if c.Enabled() {
			timeStart := time.Now()
			md, err := c.F()
			timeFinish := time.Since(timeStart)
			result := 0
			if err != nil {
				slog.Errorf("%v: %v", c.Name(), err)
				result = 1
			}
			Add(&md, "scollector.collector.duration", timeFinish.Seconds(), tags, metadata.Gauge, metadata.Second, "Duration in seconds for each collector run.")
			Add(&md, "scollector.collector.error", result, tags, metadata.Gauge, metadata.Ok, "Status of collector run. 1=Error, 0=Success.")
			for _, dp := range md {
				dpchan <- dp
			}
		}
		<-next
	}
}

func (c *IntervalCollector) Enabled() bool {
	if c.Enable == nil {
		return true
	}
	c.Lock()
	defer c.Unlock()
	return c.enabled
}

func (c *IntervalCollector) Name() string {
	if c.name != "" {
		return c.name
	}
	v := runtime.FuncForPC(reflect.ValueOf(c.F).Pointer())
	return v.Name()
}

func enableURL(url string, regexes ...string) func() bool {
	res := make([]*regexp.Regexp, len(regexes))
	for i, r := range regexes {
		res[i] = regexp.MustCompile(r)
	}
	return func() bool {
		resp, err := http.Get(url)
		if err != nil {
			return false
		}
		defer resp.Body.Close()
		if resp.StatusCode != 200 {
			return false
		}
		if len(res) == 0 {
			return true
		}
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return false
		}
		for _, r := range res {
			if !r.Match(b) {
				return false
			}
		}
		return true
	}
}

// enableExecutable returns true if name is an executable file in the
// environment's PATH.
func enableExecutable(name string) func() bool {
	return func() bool {
		_, err := exec.LookPath(name)
		return err == nil
	}
}
<commit_msg>cmd/scollector: scollector.* metrics disabled properly with DisableSelf<commit_after>package collectors

import (
	"io/ioutil"
	"net/http"
	"os/exec"
	"reflect"
	"regexp"
	"runtime"
	"sync"
	"time"

	"bosun.org/collect"
	"bosun.org/metadata"
	"bosun.org/opentsdb"
	"bosun.org/slog"
)

type IntervalCollector struct {
	F        func() (opentsdb.MultiDataPoint, error)
	Interval time.Duration // defaults to DefaultFreq if unspecified
	Enable   func() bool
	name     string
	init     func()

	// internal use
	sync.Mutex
	enabled bool
}

func (c *IntervalCollector) Init() {
	if c.init != nil {
		c.init()
	}
}

func (c *IntervalCollector) Run(dpchan chan<- *opentsdb.DataPoint) {
	if c.Enable != nil {
		go func() {
			for {
				next := time.After(time.Minute * 5)
				c.Lock()
				c.enabled = c.Enable()
				c.Unlock()
				<-next
			}
		}()
	}

	for {
		interval := c.Interval
		if interval == 0 {
			interval = DefaultFreq
		}
		next := time.After(interval)
		if c.Enabled() {
			timeStart := time.Now()
			md, err := c.F()
			timeFinish := time.Since(timeStart)
			result := 0
			if err != nil {
				slog.Errorf("%v: %v", c.Name(), err)
				result = 1
			}
			if !collect.DisableDefaultCollectors {
				tags := opentsdb.TagSet{"collector": c.Name(), "os": runtime.GOOS}
				Add(&md, "scollector.collector.duration", timeFinish.Seconds(), tags, metadata.Gauge, metadata.Second, "Duration in seconds for each collector run.")
				Add(&md, "scollector.collector.error", result, tags, metadata.Gauge, metadata.Ok, "Status of collector run. 1=Error, 0=Success.")
			}
			for _, dp := range md {
				dpchan <- dp
			}
		}
		<-next
	}
}

func (c *IntervalCollector) Enabled() bool {
	if c.Enable == nil {
		return true
	}
	c.Lock()
	defer c.Unlock()
	return c.enabled
}

func (c *IntervalCollector) Name() string {
	if c.name != "" {
		return c.name
	}
	v := runtime.FuncForPC(reflect.ValueOf(c.F).Pointer())
	return v.Name()
}

func enableURL(url string, regexes ...string) func() bool {
	res := make([]*regexp.Regexp, len(regexes))
	for i, r := range regexes {
		res[i] = regexp.MustCompile(r)
	}
	return func() bool {
		resp, err := http.Get(url)
		if err != nil {
			return false
		}
		defer resp.Body.Close()
		if resp.StatusCode != 200 {
			return false
		}
		if len(res) == 0 {
			return true
		}
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return false
		}
		for _, r := range res {
			if !r.Match(b) {
				return false
			}
		}
		return true
	}
}

// enableExecutable returns true if name is an executable file in the
// environment's PATH.
func enableExecutable(name string) func() bool {
	return func() bool {
		_, err := exec.LookPath(name)
		return err == nil
	}
}
<|endoftext|>


<commit_before>package tameshigiri

import "testing"

func (self *Assertion) ExampleEquals() {
    var t         = &testing.T{}
    var assertion = Assertion{ T: t }
    var expected  = 123
    var actual    = 123

    assertion.Equals(expected, actual, "Something must be wrong.")
}
<commit_msg>Updated the documentation.<commit_after>package tameshigiri

import "testing"

func ExampleAssertion() {
    var t         = &testing.T{}
    var assertion = Assertion{ T: t }
    var expected  = 123
    var actual    = 123

    assertion.Equals(expected, actual, "Something must be wrong.")
}
<|endoftext|>


<commit_before>package gateio

import (
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/gorilla/websocket"
	"github.com/thrasher-corp/gocryptotrader/common"
	"github.com/thrasher-corp/gocryptotrader/currency"
	exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
	"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
	"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
	"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
	log "github.com/thrasher-corp/gocryptotrader/logger"
)

const (
	gateioWebsocketEndpoint  = "wss://ws.gate.io/v3/"
	gatioWsMethodPing        = "ping"
	gateioWebsocketRateLimit = 120
)

// WsConnect initiates a websocket connection
func (g *Gateio) WsConnect() error {
	if !g.Websocket.IsEnabled() || !g.IsEnabled() {
		return errors.New(wshandler.WebsocketNotEnabled)
	}
	var dialer websocket.Dialer
	err := g.WebsocketConn.Dial(&dialer, http.Header{})
	if err != nil {
		return err
	}
	go g.WsHandleData()
	_, err = g.wsServerSignIn()
	if err != nil {
		log.Errorf("%v - authentication failed: %v", g.Name, err)
	}
	g.GenerateAuthenticatedSubscriptions()
	g.GenerateDefaultSubscriptions()
	return nil
}

func (g *Gateio) wsServerSignIn() (*WebsocketAuthenticationResponse, error) {
	if !g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
		return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", g.Name)
	}
	nonce := int(time.Now().Unix() * 1000)
	sigTemp := g.GenerateSignature(strconv.Itoa(nonce))
	signature := common.Base64Encode(sigTemp)
	signinWsRequest := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: "server.sign",
		Params: []interface{}{g.APIKey, signature, nonce},
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(signinWsRequest.ID, signinWsRequest)
	if err != nil {
		g.Websocket.SetCanUseAuthenticatedEndpoints(false)
		return nil, err
	}
	var response WebsocketAuthenticationResponse
	err = common.JSONDecode(resp, &response)
	if err != nil {
		g.Websocket.SetCanUseAuthenticatedEndpoints(false)
		return nil, err
	}
	if response.Result.Status == "success" {
		g.Websocket.SetCanUseAuthenticatedEndpoints(true)
	}
	return &response, nil
}

// WsHandleData handles all the websocket data coming from the websocket
// connection
func (g *Gateio) WsHandleData() {
	g.Websocket.Wg.Add(1)

	defer func() {
		g.Websocket.Wg.Done()
	}()

	for {
		select {
		case <-g.Websocket.ShutdownC:
			return

		default:
			resp, err := g.WebsocketConn.ReadMessage()
			if err != nil {
				g.Websocket.DataHandler <- err
				return
			}
			g.Websocket.TrafficAlert <- struct{}{}
			var result WebsocketResponse
			err = common.JSONDecode(resp.Raw, &result)
			if err != nil {
				g.Websocket.DataHandler <- err
				continue
			}

			if result.ID > 0 {
				g.WebsocketConn.AddResponseWithID(result.ID, resp.Raw)
				continue
			}

			if result.Error.Code != 0 {
				if common.StringContains(result.Error.Message, "authentication") {
					g.Websocket.DataHandler <- fmt.Errorf("%v - authentication failed: %v", g.Name, err)
					g.Websocket.SetCanUseAuthenticatedEndpoints(false)
					continue
				}
				g.Websocket.DataHandler <- fmt.Errorf("%v error %s",
					g.Name, result.Error.Message)
				continue
			}

			switch {
			case common.StringContains(result.Method, "ticker"):
				var ticker WebsocketTicker
				var c string
				err = common.JSONDecode(result.Params[1], &ticker)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[0], &c)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				g.Websocket.DataHandler <- wshandler.TickerData{
					Timestamp:  time.Now(),
					Pair:       currency.NewPairFromString(c),
					AssetType:  orderbook.Spot,
					Exchange:   g.GetName(),
					ClosePrice: ticker.Close,
					Quantity:   ticker.BaseVolume,
					OpenPrice:  ticker.Open,
					HighPrice:  ticker.High,
					LowPrice:   ticker.Low,
				}

			case common.StringContains(result.Method, "trades"):
				var trades []WebsocketTrade
				var c string
				err = common.JSONDecode(result.Params[1], &trades)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[0], &c)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				for i := range trades {
					g.Websocket.DataHandler <- wshandler.TradeData{
						Timestamp:    time.Now(),
						CurrencyPair: currency.NewPairFromString(c),
						AssetType:    orderbook.Spot,
						Exchange:     g.GetName(),
						Price:        trades[i].Price,
						Amount:       trades[i].Amount,
						Side:         trades[i].Type,
					}
				}

			case common.StringContains(result.Method, "depth"):
				var IsSnapshot bool
				var c string
				var data = make(map[string][][]string)
				err = common.JSONDecode(result.Params[0], &IsSnapshot)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[2], &c)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[1], &data)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				var asks, bids []orderbook.Item

				askData, askOk := data["asks"]
				for i := range askData {
					amount, _ := strconv.ParseFloat(askData[i][1], 64)
					price, _ := strconv.ParseFloat(askData[i][0], 64)
					asks = append(asks, orderbook.Item{
						Amount: amount,
						Price:  price,
					})
				}

				bidData, bidOk := data["bids"]
				for i := range bidData {
					amount, _ := strconv.ParseFloat(bidData[i][1], 64)
					price, _ := strconv.ParseFloat(bidData[i][0], 64)
					bids = append(bids, orderbook.Item{
						Amount: amount,
						Price:  price,
					})
				}

				if !askOk && !bidOk {
					g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access ask or bid data")
				}

				if IsSnapshot {
					if !askOk {
						g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access ask data")
					}

					if !bidOk {
						g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access bid data")
					}

					var newOrderBook orderbook.Base
					newOrderBook.Asks = asks
					newOrderBook.Bids = bids
					newOrderBook.AssetType = orderbook.Spot
					newOrderBook.Pair = currency.NewPairFromString(c)

					err = g.Websocket.Orderbook.LoadSnapshot(&newOrderBook,
						false)
					if err != nil {
						g.Websocket.DataHandler <- err
					}
				} else {
					err = g.Websocket.Orderbook.Update(
						&wsorderbook.WebsocketOrderbookUpdate{
							Asks:         asks,
							Bids:         bids,
							CurrencyPair: currency.NewPairFromString(c),
							UpdateTime:   time.Now(),
							AssetType:    orderbook.Spot,
						})
					if err != nil {
						g.Websocket.DataHandler <- err
					}
				}

				g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
					Pair:     currency.NewPairFromString(c),
					Asset:    orderbook.Spot,
					Exchange: g.GetName(),
				}

			case common.StringContains(result.Method, "kline"):
				var data []interface{}
				err = common.JSONDecode(result.Params[0], &data)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				open, _ := strconv.ParseFloat(data[1].(string), 64)
				closePrice, _ := strconv.ParseFloat(data[2].(string), 64)
				high, _ := strconv.ParseFloat(data[3].(string), 64)
				low, _ := strconv.ParseFloat(data[4].(string), 64)
				volume, _ := strconv.ParseFloat(data[5].(string), 64)

				g.Websocket.DataHandler <- wshandler.KlineData{
					Timestamp:  time.Now(),
					Pair:       currency.NewPairFromString(data[7].(string)),
					AssetType:  orderbook.Spot,
					Exchange:   g.GetName(),
					OpenPrice:  open,
					ClosePrice: closePrice,
					HighPrice:  high,
					LowPrice:   low,
					Volume:     volume,
				}
			}
		}
	}
}

// GenerateAuthenticatedSubscriptions Adds authenticated subscriptions to websocket to be handled by ManageSubscriptions()
func (g *Gateio) GenerateAuthenticatedSubscriptions() {
	if !g.Websocket.CanUseAuthenticatedEndpoints() {
		return
	}
	var channels = []string{"balance.subscribe", "order.subscribe"}
	var subscriptions []wshandler.WebsocketChannelSubscription
	enabledCurrencies := g.GetEnabledCurrencies()
	for i := range channels {
		for j := range enabledCurrencies {
			subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
				Channel:  channels[i],
				Currency: enabledCurrencies[j],
			})
		}
	}
	g.Websocket.SubscribeToChannels(subscriptions)
}

// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
func (g *Gateio) GenerateDefaultSubscriptions() {
	var channels = []string{"ticker.subscribe", "trades.subscribe", "depth.subscribe", "kline.subscribe"}
	var subscriptions []wshandler.WebsocketChannelSubscription
	enabledCurrencies := g.GetEnabledCurrencies()
	for i := range channels {
		for j := range enabledCurrencies {
			params := make(map[string]interface{})
			if strings.EqualFold(channels[i], "depth.subscribe") {
				params["limit"] = 30
				params["interval"] = "0.1"
			} else if strings.EqualFold(channels[i], "kline.subscribe") {
				params["interval"] = 1800
			}
			subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
				Channel:  channels[i],
				Currency: enabledCurrencies[j],
				Params:   params,
			})
		}
	}
	g.Websocket.SubscribeToChannels(subscriptions)
}

// Subscribe sends a websocket message to receive data from the channel
func (g *Gateio) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
	params := []interface{}{channelToSubscribe.Currency.String()}
	for i := range channelToSubscribe.Params {
		params = append(params, channelToSubscribe.Params[i])
	}

	subscribe := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: channelToSubscribe.Channel,
		Params: params,
	}

	resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
	if err != nil {
		return err
	}
	var response WebsocketAuthenticationResponse
	err = common.JSONDecode(resp, &response)
	if err != nil {
		return err
	}
	if response.Result.Status != "success" {
		return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
	}
	return nil
}

// Unsubscribe sends a websocket message to stop receiving data from the channel
func (g *Gateio) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
	unsbuscribeText := strings.Replace(channelToSubscribe.Channel, "subscribe", "unsubscribe", 1)
	subscribe := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: unsbuscribeText,
		Params: []interface{}{channelToSubscribe.Currency.String(), 1800},
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
	if err != nil {
		return err
	}
	var response WebsocketAuthenticationResponse
	err = common.JSONDecode(resp, &response)
	if err != nil {
		return err
	}
	if response.Result.Status != "success" {
		return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
	}
	return nil
}

func (g *Gateio) wsGetBalance(currencies []string) (*WsGetBalanceResponse, error) {
	if !g.Websocket.CanUseAuthenticatedEndpoints() {
		return nil, fmt.Errorf("%v not authorised to get balance", g.Name)
	}
	balanceWsRequest := wsGetBalanceRequest{
		ID:     g.WebsocketConn.GenerateMessageID(false),
		Method: "balance.query",
		Params: currencies,
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(balanceWsRequest.ID, balanceWsRequest)
	if err != nil {
		return nil, err
	}
	var balance WsGetBalanceResponse
	err = common.JSONDecode(resp, &balance)
	if err != nil {
		return &balance, err
	}

	return &balance, nil
}

func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrderQueryResult, error) {
	if !g.Websocket.CanUseAuthenticatedEndpoints() {
		return nil, fmt.Errorf("%v not authorised to get order info", g.Name)
	}
	order := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: "order.query",
		Params: []interface{}{
			market,
			offset,
			limit,
		},
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(order.ID, order)
	if err != nil {
		return nil, err
	}
	var orderQuery WebSocketOrderQueryResult
	err = common.JSONDecode(resp, &orderQuery)
	if err != nil {
		return &orderQuery, err
	}
	return &orderQuery, nil
}
<commit_msg>GateIO: Update websocket endpoint from certificate failure (#374)<commit_after>package gateio

import (
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/gorilla/websocket"
	"github.com/thrasher-corp/gocryptotrader/common"
	"github.com/thrasher-corp/gocryptotrader/currency"
	exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
	"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
	"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
	"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
	log "github.com/thrasher-corp/gocryptotrader/logger"
)

const (
	gateioWebsocketEndpoint  = "wss://ws.gateio.ws/v3/"
	gatioWsMethodPing        = "ping"
	gateioWebsocketRateLimit = 120
)

// WsConnect initiates a websocket connection
func (g *Gateio) WsConnect() error {
	if !g.Websocket.IsEnabled() || !g.IsEnabled() {
		return errors.New(wshandler.WebsocketNotEnabled)
	}
	var dialer websocket.Dialer
	err := g.WebsocketConn.Dial(&dialer, http.Header{})
	if err != nil {
		return err
	}
	go g.WsHandleData()
	_, err = g.wsServerSignIn()
	if err != nil {
		log.Errorf("%v - authentication failed: %v", g.Name, err)
	}
	g.GenerateAuthenticatedSubscriptions()
	g.GenerateDefaultSubscriptions()
	return nil
}

func (g *Gateio) wsServerSignIn() (*WebsocketAuthenticationResponse, error) {
	if !g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
		return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", g.Name)
	}
	nonce := int(time.Now().Unix() * 1000)
	sigTemp := g.GenerateSignature(strconv.Itoa(nonce))
	signature := common.Base64Encode(sigTemp)
	signinWsRequest := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: "server.sign",
		Params: []interface{}{g.APIKey, signature, nonce},
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(signinWsRequest.ID, signinWsRequest)
	if err != nil {
		g.Websocket.SetCanUseAuthenticatedEndpoints(false)
		return nil, err
	}
	var response WebsocketAuthenticationResponse
	err = common.JSONDecode(resp, &response)
	if err != nil {
		g.Websocket.SetCanUseAuthenticatedEndpoints(false)
		return nil, err
	}
	if response.Result.Status == "success" {
		g.Websocket.SetCanUseAuthenticatedEndpoints(true)
	}
	return &response, nil
}

// WsHandleData handles all the websocket data coming from the websocket
// connection
func (g *Gateio) WsHandleData() {
	g.Websocket.Wg.Add(1)

	defer func() {
		g.Websocket.Wg.Done()
	}()

	for {
		select {
		case <-g.Websocket.ShutdownC:
			return

		default:
			resp, err := g.WebsocketConn.ReadMessage()
			if err != nil {
				g.Websocket.DataHandler <- err
				return
			}
			g.Websocket.TrafficAlert <- struct{}{}
			var result WebsocketResponse
			err = common.JSONDecode(resp.Raw, &result)
			if err != nil {
				g.Websocket.DataHandler <- err
				continue
			}

			if result.ID > 0 {
				g.WebsocketConn.AddResponseWithID(result.ID, resp.Raw)
				continue
			}

			if result.Error.Code != 0 {
				if common.StringContains(result.Error.Message, "authentication") {
					g.Websocket.DataHandler <- fmt.Errorf("%v - authentication failed: %v", g.Name, err)
					g.Websocket.SetCanUseAuthenticatedEndpoints(false)
					continue
				}
				g.Websocket.DataHandler <- fmt.Errorf("%v error %s",
					g.Name, result.Error.Message)
				continue
			}

			switch {
			case common.StringContains(result.Method, "ticker"):
				var ticker WebsocketTicker
				var c string
				err = common.JSONDecode(result.Params[1], &ticker)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[0], &c)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				g.Websocket.DataHandler <- wshandler.TickerData{
					Timestamp:  time.Now(),
					Pair:       currency.NewPairFromString(c),
					AssetType:  orderbook.Spot,
					Exchange:   g.GetName(),
					ClosePrice: ticker.Close,
					Quantity:   ticker.BaseVolume,
					OpenPrice:  ticker.Open,
					HighPrice:  ticker.High,
					LowPrice:   ticker.Low,
				}

			case common.StringContains(result.Method, "trades"):
				var trades []WebsocketTrade
				var c string
				err = common.JSONDecode(result.Params[1], &trades)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[0], &c)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				for i := range trades {
					g.Websocket.DataHandler <- wshandler.TradeData{
						Timestamp:    time.Now(),
						CurrencyPair: currency.NewPairFromString(c),
						AssetType:    orderbook.Spot,
						Exchange:     g.GetName(),
						Price:        trades[i].Price,
						Amount:       trades[i].Amount,
						Side:         trades[i].Type,
					}
				}

			case common.StringContains(result.Method, "depth"):
				var IsSnapshot bool
				var c string
				var data = make(map[string][][]string)
				err = common.JSONDecode(result.Params[0], &IsSnapshot)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[2], &c)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				err = common.JSONDecode(result.Params[1], &data)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				var asks, bids []orderbook.Item

				askData, askOk := data["asks"]
				for i := range askData {
					amount, _ := strconv.ParseFloat(askData[i][1], 64)
					price, _ := strconv.ParseFloat(askData[i][0], 64)
					asks = append(asks, orderbook.Item{
						Amount: amount,
						Price:  price,
					})
				}

				bidData, bidOk := data["bids"]
				for i := range bidData {
					amount, _ := strconv.ParseFloat(bidData[i][1], 64)
					price, _ := strconv.ParseFloat(bidData[i][0], 64)
					bids = append(bids, orderbook.Item{
						Amount: amount,
						Price:  price,
					})
				}

				if !askOk && !bidOk {
					g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access ask or bid data")
				}

				if IsSnapshot {
					if !askOk {
						g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access ask data")
					}

					if !bidOk {
						g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access bid data")
					}

					var newOrderBook orderbook.Base
					newOrderBook.Asks = asks
					newOrderBook.Bids = bids
					newOrderBook.AssetType = orderbook.Spot
					newOrderBook.Pair = currency.NewPairFromString(c)

					err = g.Websocket.Orderbook.LoadSnapshot(&newOrderBook,
						false)
					if err != nil {
						g.Websocket.DataHandler <- err
					}
				} else {
					err = g.Websocket.Orderbook.Update(
						&wsorderbook.WebsocketOrderbookUpdate{
							Asks:         asks,
							Bids:         bids,
							CurrencyPair: currency.NewPairFromString(c),
							UpdateTime:   time.Now(),
							AssetType:    orderbook.Spot,
						})
					if err != nil {
						g.Websocket.DataHandler <- err
					}
				}

				g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
					Pair:     currency.NewPairFromString(c),
					Asset:    orderbook.Spot,
					Exchange: g.GetName(),
				}

			case common.StringContains(result.Method, "kline"):
				var data []interface{}
				err = common.JSONDecode(result.Params[0], &data)
				if err != nil {
					g.Websocket.DataHandler <- err
					continue
				}

				open, _ := strconv.ParseFloat(data[1].(string), 64)
				closePrice, _ := strconv.ParseFloat(data[2].(string), 64)
				high, _ := strconv.ParseFloat(data[3].(string), 64)
				low, _ := strconv.ParseFloat(data[4].(string), 64)
				volume, _ := strconv.ParseFloat(data[5].(string), 64)

				g.Websocket.DataHandler <- wshandler.KlineData{
					Timestamp:  time.Now(),
					Pair:       currency.NewPairFromString(data[7].(string)),
					AssetType:  orderbook.Spot,
					Exchange:   g.GetName(),
					OpenPrice:  open,
					ClosePrice: closePrice,
					HighPrice:  high,
					LowPrice:   low,
					Volume:     volume,
				}
			}
		}
	}
}

// GenerateAuthenticatedSubscriptions Adds authenticated subscriptions to websocket to be handled by ManageSubscriptions()
func (g *Gateio) GenerateAuthenticatedSubscriptions() {
	if !g.Websocket.CanUseAuthenticatedEndpoints() {
		return
	}
	var channels = []string{"balance.subscribe", "order.subscribe"}
	var subscriptions []wshandler.WebsocketChannelSubscription
	enabledCurrencies := g.GetEnabledCurrencies()
	for i := range channels {
		for j := range enabledCurrencies {
			subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
				Channel:  channels[i],
				Currency: enabledCurrencies[j],
			})
		}
	}
	g.Websocket.SubscribeToChannels(subscriptions)
}

// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
func (g *Gateio) GenerateDefaultSubscriptions() {
	var channels = []string{"ticker.subscribe", "trades.subscribe", "depth.subscribe", "kline.subscribe"}
	var subscriptions []wshandler.WebsocketChannelSubscription
	enabledCurrencies := g.GetEnabledCurrencies()
	for i := range channels {
		for j := range enabledCurrencies {
			params := make(map[string]interface{})
			if strings.EqualFold(channels[i], "depth.subscribe") {
				params["limit"] = 30
				params["interval"] = "0.1"
			} else if strings.EqualFold(channels[i], "kline.subscribe") {
				params["interval"] = 1800
			}
			subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
				Channel:  channels[i],
				Currency: enabledCurrencies[j],
				Params:   params,
			})
		}
	}
	g.Websocket.SubscribeToChannels(subscriptions)
}

// Subscribe sends a websocket message to receive data from the channel
func (g *Gateio) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
	params := []interface{}{channelToSubscribe.Currency.String()}
	for i := range channelToSubscribe.Params {
		params = append(params, channelToSubscribe.Params[i])
	}

	subscribe := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: channelToSubscribe.Channel,
		Params: params,
	}

	resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
	if err != nil {
		return err
	}
	var response WebsocketAuthenticationResponse
	err = common.JSONDecode(resp, &response)
	if err != nil {
		return err
	}
	if response.Result.Status != "success" {
		return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
	}
	return nil
}

// Unsubscribe sends a websocket message to stop receiving data from the channel
func (g *Gateio) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
	unsbuscribeText := strings.Replace(channelToSubscribe.Channel, "subscribe", "unsubscribe", 1)
	subscribe := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: unsbuscribeText,
		Params: []interface{}{channelToSubscribe.Currency.String(), 1800},
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
	if err != nil {
		return err
	}
	var response WebsocketAuthenticationResponse
	err = common.JSONDecode(resp, &response)
	if err != nil {
		return err
	}
	if response.Result.Status != "success" {
		return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
	}
	return nil
}

func (g *Gateio) wsGetBalance(currencies []string) (*WsGetBalanceResponse, error) {
	if !g.Websocket.CanUseAuthenticatedEndpoints() {
		return nil, fmt.Errorf("%v not authorised to get balance", g.Name)
	}
	balanceWsRequest := wsGetBalanceRequest{
		ID:     g.WebsocketConn.GenerateMessageID(false),
		Method: "balance.query",
		Params: currencies,
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(balanceWsRequest.ID, balanceWsRequest)
	if err != nil {
		return nil, err
	}
	var balance WsGetBalanceResponse
	err = common.JSONDecode(resp, &balance)
	if err != nil {
		return &balance, err
	}

	return &balance, nil
}

func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrderQueryResult, error) {
	if !g.Websocket.CanUseAuthenticatedEndpoints() {
		return nil, fmt.Errorf("%v not authorised to get order info", g.Name)
	}
	order := WebsocketRequest{
		ID:     g.WebsocketConn.GenerateMessageID(true),
		Method: "order.query",
		Params: []interface{}{
			market,
			offset,
			limit,
		},
	}
	resp, err := g.WebsocketConn.SendMessageReturnResponse(order.ID, order)
	if err != nil {
		return nil, err
	}
	var orderQuery WebSocketOrderQueryResult
	err = common.JSONDecode(resp, &orderQuery)
	if err != nil {
		return &orderQuery, err
	}
	return &orderQuery, nil
}
<|endoftext|>


<commit_before>package machine

import (
	"errors"

	"github.com/Sirupsen/logrus"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"

	// Force to load docker executor
	_ "gitlab.com/gitlab-org/gitlab-ci-multi-runner/executors/docker"
)

type machineExecutor struct {
	provider *machineProvider
	executor common.Executor
	build    *common.Build
	data     common.ExecutorData
	config   common.RunnerConfig
}

func (e *machineExecutor) log() (log *logrus.Entry) {
	log = e.build.Log()

	details, _ := e.build.ExecutorData.(*machineDetails)
	if details == nil {
		details, _ = e.data.(*machineDetails)
	}
	if details != nil {
		log = log.WithFields(logrus.Fields{
			"docker":    e.config.Docker.DockerCredentials.Host,
			"name":      details.Name,
			"usedcount": details.UsedCount,
			"created":   details.Created,
		})
	}

	return
}

func (e *machineExecutor) Shell() *common.ShellScriptInfo {
	if e.executor == nil {
		return nil
	}
	return e.executor.Shell()
}

func (e *machineExecutor) Prepare(globalConfig *common.Config, config *common.RunnerConfig, build *common.Build) (err error) {
	e.build = build

	// Use the machine
	e.config, e.data, err = e.provider.Use(config, build.ExecutorData)
	if err != nil {
		return err
	}

	// TODO: Currently the docker-machine doesn't support multiple builds
	build.ProjectRunnerID = 0
	if details, _ := build.ExecutorData.(*machineDetails); details != nil {
		build.Hostname = details.Name
	} else if details, _ := e.data.(*machineDetails); details != nil {
		build.Hostname = details.Name
	}

	e.log().Infoln("Starting docker-machine build...")

	// Create original executor
	e.executor = e.provider.provider.Create()
	if e.executor == nil {
		return errors.New("failed to create an executor")
	}
	return e.executor.Prepare(globalConfig, &e.config, build)
}

func (e *machineExecutor) Run(cmd common.ExecutorCommand) error {
	if e.executor == nil {
		return errors.New("missing executor")
	}
	return e.executor.Run(cmd)
}

func (e *machineExecutor) Finish(err error) {
	if e.executor != nil {
		e.executor.Finish(err)
	}
	e.log().Infoln("Finished docker-machine build:", err)
}

func (e *machineExecutor) Cleanup() {
	// Cleanup executor if were created
	if e.executor != nil {
		e.executor.Cleanup()
	}

	// Release allocated machine
	if e.data != "" {
		e.provider.Release(&e.config, e.data)
		e.data = nil
	}
}

func init() {
	common.RegisterExecutor("docker+machine", newMachineProvider("docker"))
	common.RegisterExecutor("docker-ssh+machine", newMachineProvider("docker-ssh"))
}
<commit_msg>Make fmt happy<commit_after>package machine

import (
	"errors"

	"github.com/Sirupsen/logrus"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"

	// Force to load docker executor
	_ "gitlab.com/gitlab-org/gitlab-ci-multi-runner/executors/docker"
)

type machineExecutor struct {
	provider *machineProvider
	executor common.Executor
	build    *common.Build
	data     common.ExecutorData
	config   common.RunnerConfig
}

func (e *machineExecutor) log() (log *logrus.Entry) {
	log = e.build.Log()

	details, _ := e.build.ExecutorData.(*machineDetails)
	if details == nil {
		details, _ = e.data.(*machineDetails)
	}
	if details != nil {
		log = log.WithFields(logrus.Fields{
			"docker":    e.config.Docker.DockerCredentials.Host,
			"name":      details.Name,
			"usedcount": details.UsedCount,
			"created":   details.Created,
		})
	}

	return
}

func (e *machineExecutor) Shell() *common.ShellScriptInfo {
	if e.executor == nil {
		return nil
	}
	return e.executor.Shell()
}

func (e *machineExecutor) Prepare(globalConfig *common.Config, config *common.RunnerConfig, build *common.Build) (err error) {
	e.build = build

	// Use the machine
	e.config, e.data, err = e.provider.Use(config, build.ExecutorData)
	if err != nil {
		return err
	}

	// TODO: Currently the docker-machine doesn't support multiple builds
	build.ProjectRunnerID = 0
	if details, _ := build.ExecutorData.(*machineDetails); details != nil {
		build.Hostname = details.Name
	} else if details, _ := e.data.(*machineDetails); details != nil {
		build.Hostname = details.Name
	}

	e.log().Infoln("Starting docker-machine build...")

	// Create original executor
	e.executor = e.provider.provider.Create()
	if e.executor == nil {
		return errors.New("failed to create an executor")
	}
	return e.executor.Prepare(globalConfig, &e.config, build)
}

func (e *machineExecutor) Run(cmd common.ExecutorCommand) error {
	if e.executor == nil {
		return errors.New("missing executor")
	}
	return e.executor.Run(cmd)
}

func (e *machineExecutor) Finish(err error) {
	if e.executor != nil {
		e.executor.Finish(err)
	}
	e.log().Infoln("Finished docker-machine build:", err)
}

func (e *machineExecutor) Cleanup() {
	// Cleanup executor if were created
	if e.executor != nil {
		e.executor.Cleanup()
	}

	// Release allocated machine
	if e.data != "" {
		e.provider.Release(&e.config, e.data)
		e.data = nil
	}
}

func init() {
	common.RegisterExecutor("docker+machine", newMachineProvider("docker"))
	common.RegisterExecutor("docker-ssh+machine", newMachineProvider("docker-ssh"))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/jzipfler/htw-ava/server"
	"github.com/jzipfler/htw-ava/utils"
)

var (
	filename    string
	managerName string
	logFile     string
	ipAddress   string
	port        int
	managedFile *os.File
	force       bool
)

func init() {
	flag.StringVar(&filename, "filename", "path/to/file.txt", "A file that is managed by this process.")
	flag.StringVar(&managerName, "name", "Manager A", "Define the name of this manager.")
	flag.StringVar(&logFile, "logFile", "path/to/logfile.txt", "This parameter can be used to print the logging output to the given file.")
	flag.StringVar(&ipAddress, "ipAddress", "127.0.0.1", "The ip address of the actual starting node.")
	flag.IntVar(&port, "port", 15100, "The port of the actual starting node.")
	flag.BoolVar(&force, "force", false, "If force is enabled, the programm removes a existing management file and creates a new one without asking.")
}

func main() {

	flag.Parse()

	if filename == "path/to/file.txt" {
		log.Printf("A filename is required.\n%s\n\n", utils.ERROR_FOOTER)
		flag.Usage()
		os.Exit(0)
	}

	utils.InitializeLogger(logFile, "")
	utils.PrintMessage(fmt.Sprintf("File \"%s\" is now managed by this process.", filename))

	if exists := utils.CheckIfFileExists(filename); exists {
		if !force {
			if deleteIt := askForToDeleteFile(); !deleteIt {
				fmt.Println("Do not delete the file and exit the program.")
				utils.PrintMessage(fmt.Sprintf("The file \"%s\" already exists and should not be deleted.", filename))
				os.Exit(0)
			}
		}
		if err := os.Remove(filename); err != nil {
			log.Fatalf("%s\n%s\n", err.Error(), utils.ERROR_FOOTER)
		}
		utils.PrintMessage(fmt.Sprintf("Removed the file \"%s\"", filename))
	}

	managedFile, err := os.Create(filename)
	utils.PrintMessage(fmt.Sprintf("Created the file \"%s\"", filename))
	if err != nil {
		log.Fatalf("%s\n%s\n", err.Error(), utils.ERROR_FOOTER)
	}

	managedFile.WriteString("000000\n")
	utils.PrintMessage("Wrote 000000 to the file.")

	managedFile.Close()

	for i := 0; i <= 100; i++ {
		if numbers, err := utils.IncreaseNumbersFromFirstLine(filename, 6); err != nil {
			log.Fatalln(err.Error())
		} else {
			fmt.Println(numbers)
		}
	}

	for i := 0; i <= 101; i++ {
		if numbers, err := utils.DecreaseNumbersFromFirstLine(filename, 6); err != nil {
			log.Println(err.Error())
		} else {
			fmt.Println(numbers)
		}
	}

	os.Exit(0)

	serverObject := server.New()

	serverObject.SetClientName(managerName)
	serverObject.SetIpAddressAsString(ipAddress)
	serverObject.SetPort(port)
	serverObject.SetUsedProtocol("tcp")

	if err := server.StartServer(serverObject, nil); err != nil {
		log.Fatalln("Could not start server. --> Exit.")
		os.Exit(1)
	}
	defer server.StopServer()
}

func askForToDeleteFile() bool {
	var input string
	fmt.Printf("Would you like to delete the file \"%s\"? (y/j/n)", filename)
	fmt.Print("\nInput: ")
	if _, err := fmt.Scanln(&input); err == nil {
		switch input {
		case "y", "j":
			fmt.Println("File gets deleted.")
			return true
		case "n":
			fmt.Println(input)
			return false
		default:
			fmt.Println("Please only insert y/j for \"YES\" or n for \"NO\".\n" + utils.ERROR_FOOTER)
			fmt.Println("Assume a \"n\" as input.")
			return false
		}
	} else {
		fmt.Println("Please only insert y/j for \"YES\" or n for \"NO\".\n" + utils.ERROR_HEADER)
	}
	return false
}
<commit_msg>Added a example for the AppendStringToFile function in the current version of the fileManager<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/jzipfler/htw-ava/server"
	"github.com/jzipfler/htw-ava/utils"
)

var (
	filename    string
	managerName string
	logFile     string
	ipAddress   string
	port        int
	managedFile *os.File
	force       bool
)

func init() {
	flag.StringVar(&filename, "filename", "path/to/file.txt", "A file that is managed by this process.")
	flag.StringVar(&managerName, "name", "Manager A", "Define the name of this manager.")
	flag.StringVar(&logFile, "logFile", "path/to/logfile.txt", "This parameter can be used to print the logging output to the given file.")
	flag.StringVar(&ipAddress, "ipAddress", "127.0.0.1", "The ip address of the actual starting node.")
	flag.IntVar(&port, "port", 15100, "The port of the actual starting node.")
	flag.BoolVar(&force, "force", false, "If force is enabled, the programm removes a existing management file and creates a new one without asking.")
}

func main() {

	flag.Parse()

	if filename == "path/to/file.txt" {
		log.Printf("A filename is required.\n%s\n\n", utils.ERROR_FOOTER)
		flag.Usage()
		os.Exit(0)
	}

	utils.InitializeLogger(logFile, "")
	utils.PrintMessage(fmt.Sprintf("File \"%s\" is now managed by this process.", filename))

	if exists := utils.CheckIfFileExists(filename); exists {
		if !force {
			if deleteIt := askForToDeleteFile(); !deleteIt {
				fmt.Println("Do not delete the file and exit the program.")
				utils.PrintMessage(fmt.Sprintf("The file \"%s\" already exists and should not be deleted.", filename))
				os.Exit(0)
			}
		}
		if err := os.Remove(filename); err != nil {
			log.Fatalf("%s\n%s\n", err.Error(), utils.ERROR_FOOTER)
		}
		utils.PrintMessage(fmt.Sprintf("Removed the file \"%s\"", filename))
	}

	managedFile, err := os.Create(filename)
	utils.PrintMessage(fmt.Sprintf("Created the file \"%s\"", filename))
	if err != nil {
		log.Fatalf("%s\n%s\n", err.Error(), utils.ERROR_FOOTER)
	}

	managedFile.WriteString("000000\n")
	utils.PrintMessage("Wrote 000000 to the file.")

	managedFile.Close()

	for i := 0; i <= 100; i++ {
		if numbers, err := utils.IncreaseNumbersFromFirstLine(filename, 6); err != nil {
			log.Fatalln(err.Error())
		} else {
			fmt.Println(numbers)
		}
	}

	for i := 0; i <= 101; i++ {
		if numbers, err := utils.DecreaseNumbersFromFirstLine(filename, 6); err != nil {
			log.Println(err.Error())
		} else {
			fmt.Println(numbers)
		}
	}

	if err := utils.AppendStringToFile(filename, "Hier könnte Ihre Werbung stehen", false); err != nil {
		log.Fatalln(err)
	}
	if err := utils.AppendStringToFile(filename, " ::::: Oder vieles mehr!", true); err != nil {
		log.Fatalln(err)
	}
	if err := utils.AppendStringToFile(filename, "Das stimmt!", true); err != nil {
		log.Fatalln(err)
	}
	os.Exit(0)

	serverObject := server.New()

	serverObject.SetClientName(managerName)
	serverObject.SetIpAddressAsString(ipAddress)
	serverObject.SetPort(port)
	serverObject.SetUsedProtocol("tcp")

	if err := server.StartServer(serverObject, nil); err != nil {
		log.Fatalln("Could not start server. --> Exit.")
		os.Exit(1)
	}
	defer server.StopServer()
}

func askForToDeleteFile() bool {
	var input string
	fmt.Printf("Would you like to delete the file \"%s\"? (y/j/n)", filename)
	fmt.Print("\nInput: ")
	if _, err := fmt.Scanln(&input); err == nil {
		switch input {
		case "y", "j":
			fmt.Println("File gets deleted.")
			return true
		case "n":
			fmt.Println(input)
			return false
		default:
			fmt.Println("Please only insert y/j for \"YES\" or n for \"NO\".\n" + utils.ERROR_FOOTER)
			fmt.Println("Assume a \"n\" as input.")
			return false
		}
	} else {
		fmt.Println("Please only insert y/j for \"YES\" or n for \"NO\".\n" + utils.ERROR_HEADER)
	}
	return false
}
<|endoftext|>