<commit_before>package firego

import (
	"bytes"
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	_url "net/url"
	"strings"
	"time"
)

var TimeoutDuration = 30 * time.Second

type ErrTimeout struct {
	error
}

// query parameter constants
const (
	authParam    = "auth"
	formatParam  = "format"
	shallowParam = "shallow"
	formatVal    = "export"
)

// Firebase represents a location in the cloud
type Firebase struct {
	url          string
	params       _url.Values
	client       *http.Client
	watching     bool
	stopWatching chan struct{}
}

func sanitizeURL(url string) string {
	if !strings.HasPrefix(url, "https://") && !strings.HasPrefix(url, "http://") {
		url = "https://" + url
	}

	if strings.HasSuffix(url, "/") {
		url = url[:len(url)-1]
	}

	return url
}

// New creates a new Firebase reference
func New(url string) *Firebase {

	var tr *http.Transport
	tr = &http.Transport{
		DisableKeepAlives: true, // https://code.google.com/p/go/issues/detail?id=3514
		Dial: func(network, address string) (net.Conn, error) {
			start := time.Now()
			c, err := net.DialTimeout(network, address, TimeoutDuration)
			tr.ResponseHeaderTimeout = TimeoutDuration - time.Since(start)
			return c, err
		},
	}

	return &Firebase{
		url:          sanitizeURL(url),
		params:       _url.Values{},
		client:       &http.Client{Transport: tr},
		stopWatching: make(chan struct{}),
	}
}

// String returns the string representation of the
// Firebase reference
func (fb *Firebase) String() string {
	return fb.url
}

// Child creates a new Firebase reference for the requested
// child string
func (fb *Firebase) Child(child string) *Firebase {
	return &Firebase{
		url:          fb.url + "/" + child,
		params:       fb.params,
		client:       fb.client,
		stopWatching: make(chan struct{}),
	}
}

// Shallow limits the depth of the data returned when calling Value.
// If the data at the location is a JSON primitive (string, number or boolean),
// its value will be returned. If the data is a JSON object, the values
// for each key will be truncated to true.
//
// Reference https://www.firebase.com/docs/rest/api/#section-param-shallow
func (fb *Firebase) Shallow(v bool) {
	if v {
		fb.params.Set(shallowParam, "true")
	} else {
		fb.params.Del(shallowParam)
	}
}

// IncludePriority determines whether or not to ask Firebase
// for the values priority. By default, the priority is not returned
//
//		# Include Priority
//		ref.IncludePriority(true)
//		# Exclude Priority
//		ref.IncludePriority(false)
func (fb *Firebase) IncludePriority(v bool) {
	if v {
		fb.params.Set(formatParam, formatVal)
	} else {
		fb.params.Del(formatParam)
	}
}

func (fb *Firebase) makeRequest(method string, body []byte) (*http.Request, error) {
	path := fb.url + "/.json"

	if len(fb.params) > 0 {
		path += "?" + fb.params.Encode()
	}
	return http.NewRequest(method, path, bytes.NewReader(body))
}

func (fb *Firebase) doRequest(method string, body []byte) ([]byte, error) {
	req, err := fb.makeRequest(method, body)
	if err != nil {
		return nil, err
	}

	resp, err := fb.client.Do(req)
	switch err := err.(type) {
	default:
		return nil, err
	case nil:
		// carry on
	case *_url.Error:
		e1, ok := err.Err.(net.Error)
		if !ok {
			return nil, err
		}
		if e1.Timeout() {
			return nil, ErrTimeout{err}
		}
	case net.Error:
		if err.Timeout() {
			return nil, ErrTimeout{err}
		}
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode/200 != 1 {
		return nil, errors.New(string(respBody))
	}
	return respBody, nil
}
<commit_msg>doRequest: add comments in error handling<commit_after>package firego

import (
	"bytes"
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	_url "net/url"
	"strings"
	"time"
)

var TimeoutDuration = 30 * time.Second

type ErrTimeout struct {
	error
}

// query parameter constants
const (
	authParam    = "auth"
	formatParam  = "format"
	shallowParam = "shallow"
	formatVal    = "export"
)

// Firebase represents a location in the cloud
type Firebase struct {
	url          string
	params       _url.Values
	client       *http.Client
	watching     bool
	stopWatching chan struct{}
}

func sanitizeURL(url string) string {
	if !strings.HasPrefix(url, "https://") && !strings.HasPrefix(url, "http://") {
		url = "https://" + url
	}

	if strings.HasSuffix(url, "/") {
		url = url[:len(url)-1]
	}

	return url
}

// New creates a new Firebase reference
func New(url string) *Firebase {

	var tr *http.Transport
	tr = &http.Transport{
		DisableKeepAlives: true, // https://code.google.com/p/go/issues/detail?id=3514
		Dial: func(network, address string) (net.Conn, error) {
			start := time.Now()
			c, err := net.DialTimeout(network, address, TimeoutDuration)
			tr.ResponseHeaderTimeout = TimeoutDuration - time.Since(start)
			return c, err
		},
	}

	return &Firebase{
		url:          sanitizeURL(url),
		params:       _url.Values{},
		client:       &http.Client{Transport: tr},
		stopWatching: make(chan struct{}),
	}
}

// String returns the string representation of the
// Firebase reference
func (fb *Firebase) String() string {
	return fb.url
}

// Child creates a new Firebase reference for the requested
// child string
func (fb *Firebase) Child(child string) *Firebase {
	return &Firebase{
		url:          fb.url + "/" + child,
		params:       fb.params,
		client:       fb.client,
		stopWatching: make(chan struct{}),
	}
}

// Shallow limits the depth of the data returned when calling Value.
// If the data at the location is a JSON primitive (string, number or boolean),
// its value will be returned. If the data is a JSON object, the values
// for each key will be truncated to true.
//
// Reference https://www.firebase.com/docs/rest/api/#section-param-shallow
func (fb *Firebase) Shallow(v bool) {
	if v {
		fb.params.Set(shallowParam, "true")
	} else {
		fb.params.Del(shallowParam)
	}
}

// IncludePriority determines whether or not to ask Firebase
// for the values priority. By default, the priority is not returned
//
//		# Include Priority
//		ref.IncludePriority(true)
//		# Exclude Priority
//		ref.IncludePriority(false)
func (fb *Firebase) IncludePriority(v bool) {
	if v {
		fb.params.Set(formatParam, formatVal)
	} else {
		fb.params.Del(formatParam)
	}
}

func (fb *Firebase) makeRequest(method string, body []byte) (*http.Request, error) {
	path := fb.url + "/.json"

	if len(fb.params) > 0 {
		path += "?" + fb.params.Encode()
	}
	return http.NewRequest(method, path, bytes.NewReader(body))
}

func (fb *Firebase) doRequest(method string, body []byte) ([]byte, error) {
	req, err := fb.makeRequest(method, body)
	if err != nil {
		return nil, err
	}

	resp, err := fb.client.Do(req)
	switch err := err.(type) {
	default:
		return nil, err
	case nil:
		// carry on

	case *_url.Error:
		// `http.Client.Do` will return a `url.Error` that wraps a `net.Error`
		// when exceeding it's `Transport`'s `ResponseHeadersTimeout`
		e1, ok := err.Err.(net.Error)
		if ok && e1.Timeout() {
			return nil, ErrTimeout{err}
		}

		return nil, err

	case net.Error:
		// `http.Client.Do` will return a `net.Error` directly when Dial times
		// out, or when the Client's RoundTripper otherwise returns an err
		if err.Timeout() {
			return nil, ErrTimeout{err}
		}

		return nil, err
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode/200 != 1 {
		return nil, errors.New(string(respBody))
	}
	return respBody, nil
}
<|endoftext|>


<commit_before>// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.

package backup

import (
	"context"
	"fmt"
	"sync"

	"github.com/opentracing/opentracing-go"
	"github.com/pingcap/errors"
	"github.com/pingcap/failpoint"
	backuppb "github.com/pingcap/kvproto/pkg/brpb"
	"github.com/pingcap/kvproto/pkg/metapb"
	berrors "github.com/pingcap/tidb/br/pkg/errors"
	"github.com/pingcap/tidb/br/pkg/logutil"
	"github.com/pingcap/tidb/br/pkg/redact"
	"github.com/pingcap/tidb/br/pkg/rtree"
	"github.com/pingcap/tidb/br/pkg/utils"
	"go.uber.org/zap"
)

// pushDown wraps a backup task.
type pushDown struct {
	mgr    ClientMgr
	respCh chan responseAndStore
	errCh  chan error
}

type responseAndStore struct {
	Resp  *backuppb.BackupResponse
	Store *metapb.Store
}

func (r responseAndStore) GetResponse() *backuppb.BackupResponse {
	return r.Resp
}

func (r responseAndStore) GetStore() *metapb.Store {
	return r.Store
}

// newPushDown creates a push down backup.
func newPushDown(mgr ClientMgr, capacity int) *pushDown {
	return &pushDown{
		mgr:    mgr,
		respCh: make(chan responseAndStore, capacity),
		errCh:  make(chan error, capacity),
	}
}

// FullBackup make a full backup of a tikv cluster.
func (push *pushDown) pushBackup(
	ctx context.Context,
	req backuppb.BackupRequest,
	stores []*metapb.Store,
	progressCallBack func(ProgressUnit),
) (rtree.RangeTree, error) {
	if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil {
		span1 := span.Tracer().StartSpan("pushDown.pushBackup", opentracing.ChildOf(span.Context()))
		defer span1.Finish()
		ctx = opentracing.ContextWithSpan(ctx, span1)
	}

	// Push down backup tasks to all tikv instances.
	res := rtree.NewRangeTree()
	failpoint.Inject("noop-backup", func(_ failpoint.Value) {
		logutil.CL(ctx).Warn("skipping normal backup, jump to fine-grained backup, meow :3", logutil.Key("start-key", req.StartKey), logutil.Key("end-key", req.EndKey))
		failpoint.Return(res, nil)
	})

	wg := new(sync.WaitGroup)
	for _, s := range stores {
		store := s
		storeID := s.GetId()
		lctx := logutil.ContextWithField(ctx, zap.Uint64("store-id", storeID))
		if s.GetState() != metapb.StoreState_Up {
			logutil.CL(lctx).Warn("skip store", zap.Stringer("State", s.GetState()))
			continue
		}
		client, err := push.mgr.GetBackupClient(lctx, storeID)
		if err != nil {
			// BR should be able to backup even some of stores disconnected.
			// The regions managed by this store can be retried at fine-grained backup then.
			logutil.CL(lctx).Warn("fail to connect store, skipping", zap.Error(err))
			return res, nil
		}
		wg.Add(1)
		go func() {
			defer wg.Done()
			err := SendBackup(
				lctx, storeID, client, req,
				func(resp *backuppb.BackupResponse) error {
					// Forward all responses (including error).
					push.respCh <- responseAndStore{
						Resp:  resp,
						Store: store,
					}
					return nil
				},
				func() (backuppb.BackupClient, error) {
					logutil.CL(lctx).Warn("reset the connection in push")
					return push.mgr.ResetBackupClient(lctx, storeID)
				})
			// Disconnected stores can be ignored.
			if err != nil {
				push.errCh <- err
				return
			}
		}()
	}

	go func() {
		wg.Wait()
		// TODO: test concurrent receive response and close channel.
		close(push.respCh)
	}()

	for {
		select {
		case respAndStore, ok := <-push.respCh:
			resp := respAndStore.GetResponse()
			store := respAndStore.GetStore()
			if !ok {
				// Finished.
				return res, nil
			}
			failpoint.Inject("backup-storage-error", func(val failpoint.Value) {
				msg := val.(string)
				logutil.CL(ctx).Debug("failpoint backup-storage-error injected.", zap.String("msg", msg))
				resp.Error = &backuppb.Error{
					Msg: msg,
				}
			})
			failpoint.Inject("tikv-rw-error", func(val failpoint.Value) {
				msg := val.(string)
				logutil.CL(ctx).Debug("failpoint tikv-rw-error injected.", zap.String("msg", msg))
				resp.Error = &backuppb.Error{
					Msg: msg,
				}
			})
			if resp.GetError() == nil {
				// None error means range has been backuped successfully.
				res.Put(
					resp.GetStartKey(), resp.GetEndKey(), resp.GetFiles())

				// Update progress
				progressCallBack(RegionUnit)
			} else {
				errPb := resp.GetError()
				switch v := errPb.Detail.(type) {
				case *backuppb.Error_KvError:
					logutil.CL(ctx).Warn("backup occur kv error", zap.Reflect("error", v))

				case *backuppb.Error_RegionError:
					logutil.CL(ctx).Warn("backup occur region error", zap.Reflect("error", v))

				case *backuppb.Error_ClusterIdError:
					logutil.CL(ctx).Error("backup occur cluster ID error", zap.Reflect("error", v))
					return res, errors.Annotatef(berrors.ErrKVClusterIDMismatch, "%v", errPb)
				default:
					if utils.MessageIsRetryableStorageError(errPb.GetMsg()) {
						logutil.CL(ctx).Warn("backup occur storage error", zap.String("error", errPb.GetMsg()))
						continue
					}
					if utils.MessageIsNotFoundStorageError(errPb.GetMsg()) {
						errMsg := fmt.Sprintf("File or directory not found error occurs on TiKV Node(store id: %v; Address: %s)", store.GetId(), redact.String(store.GetAddress()))
						logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg),
							zap.String("work around", "please ensure br and tikv node share a same disk and the user of br and tikv has same uid."))
					}
					if utils.MessageIsPermissionDeniedStorageError(errPb.GetMsg()) {
						errMsg := fmt.Sprintf("I/O permission denied error occurs on TiKV Node(store id: %v; Address: %s)", store.GetId(), redact.String(store.GetAddress()))
						logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg),
							zap.String("work around", "please ensure tikv has permission to read from & write to the storage."))
					}
					return res, errors.Annotatef(berrors.ErrKVStorage, "error happen in store %v at %s: %s",
						store.GetId(),
						redact.String(store.GetAddress()),
						errPb.Msg,
					)
				}
			}
		case err := <-push.errCh:
			if !berrors.Is(err, berrors.ErrFailedToConnect) {
				return res, errors.Annotatef(err, "failed to backup range [%s, %s)", redact.Key(req.StartKey), redact.Key(req.EndKey))
			}
			logutil.CL(ctx).Warn("skipping disconnected stores", logutil.ShortError(err))
			return res, nil
		}
	}
}
<commit_msg>br: give error message to user clearly when fail to backup without local storage directory/file (#30431)<commit_after>// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.

package backup

import (
	"context"
	"fmt"
	"sync"

	"github.com/opentracing/opentracing-go"
	"github.com/pingcap/errors"
	"github.com/pingcap/failpoint"
	backuppb "github.com/pingcap/kvproto/pkg/brpb"
	"github.com/pingcap/kvproto/pkg/metapb"
	berrors "github.com/pingcap/tidb/br/pkg/errors"
	"github.com/pingcap/tidb/br/pkg/logutil"
	"github.com/pingcap/tidb/br/pkg/redact"
	"github.com/pingcap/tidb/br/pkg/rtree"
	"github.com/pingcap/tidb/br/pkg/utils"
	"go.uber.org/zap"
)

// pushDown wraps a backup task.
type pushDown struct {
	mgr    ClientMgr
	respCh chan responseAndStore
	errCh  chan error
}

type responseAndStore struct {
	Resp  *backuppb.BackupResponse
	Store *metapb.Store
}

func (r responseAndStore) GetResponse() *backuppb.BackupResponse {
	return r.Resp
}

func (r responseAndStore) GetStore() *metapb.Store {
	return r.Store
}

// newPushDown creates a push down backup.
func newPushDown(mgr ClientMgr, capacity int) *pushDown {
	return &pushDown{
		mgr:    mgr,
		respCh: make(chan responseAndStore, capacity),
		errCh:  make(chan error, capacity),
	}
}

// FullBackup make a full backup of a tikv cluster.
func (push *pushDown) pushBackup(
	ctx context.Context,
	req backuppb.BackupRequest,
	stores []*metapb.Store,
	progressCallBack func(ProgressUnit),
) (rtree.RangeTree, error) {
	if span := opentracing.SpanFromContext(ctx); span != nil && span.Tracer() != nil {
		span1 := span.Tracer().StartSpan("pushDown.pushBackup", opentracing.ChildOf(span.Context()))
		defer span1.Finish()
		ctx = opentracing.ContextWithSpan(ctx, span1)
	}

	// Push down backup tasks to all tikv instances.
	res := rtree.NewRangeTree()
	failpoint.Inject("noop-backup", func(_ failpoint.Value) {
		logutil.CL(ctx).Warn("skipping normal backup, jump to fine-grained backup, meow :3", logutil.Key("start-key", req.StartKey), logutil.Key("end-key", req.EndKey))
		failpoint.Return(res, nil)
	})

	wg := new(sync.WaitGroup)
	for _, s := range stores {
		store := s
		storeID := s.GetId()
		lctx := logutil.ContextWithField(ctx, zap.Uint64("store-id", storeID))
		if s.GetState() != metapb.StoreState_Up {
			logutil.CL(lctx).Warn("skip store", zap.Stringer("State", s.GetState()))
			continue
		}
		client, err := push.mgr.GetBackupClient(lctx, storeID)
		if err != nil {
			// BR should be able to backup even some of stores disconnected.
			// The regions managed by this store can be retried at fine-grained backup then.
			logutil.CL(lctx).Warn("fail to connect store, skipping", zap.Error(err))
			return res, nil
		}
		wg.Add(1)
		go func() {
			defer wg.Done()
			err := SendBackup(
				lctx, storeID, client, req,
				func(resp *backuppb.BackupResponse) error {
					// Forward all responses (including error).
					push.respCh <- responseAndStore{
						Resp:  resp,
						Store: store,
					}
					return nil
				},
				func() (backuppb.BackupClient, error) {
					logutil.CL(lctx).Warn("reset the connection in push")
					return push.mgr.ResetBackupClient(lctx, storeID)
				})
			// Disconnected stores can be ignored.
			if err != nil {
				push.errCh <- err
				return
			}
		}()
	}

	go func() {
		wg.Wait()
		// TODO: test concurrent receive response and close channel.
		close(push.respCh)
	}()

	for {
		select {
		case respAndStore, ok := <-push.respCh:
			resp := respAndStore.GetResponse()
			store := respAndStore.GetStore()
			if !ok {
				// Finished.
				return res, nil
			}
			failpoint.Inject("backup-storage-error", func(val failpoint.Value) {
				msg := val.(string)
				logutil.CL(ctx).Debug("failpoint backup-storage-error injected.", zap.String("msg", msg))
				resp.Error = &backuppb.Error{
					Msg: msg,
				}
			})
			failpoint.Inject("tikv-rw-error", func(val failpoint.Value) {
				msg := val.(string)
				logutil.CL(ctx).Debug("failpoint tikv-rw-error injected.", zap.String("msg", msg))
				resp.Error = &backuppb.Error{
					Msg: msg,
				}
			})
			if resp.GetError() == nil {
				// None error means range has been backuped successfully.
				res.Put(
					resp.GetStartKey(), resp.GetEndKey(), resp.GetFiles())

				// Update progress
				progressCallBack(RegionUnit)
			} else {
				errPb := resp.GetError()
				switch v := errPb.Detail.(type) {
				case *backuppb.Error_KvError:
					logutil.CL(ctx).Warn("backup occur kv error", zap.Reflect("error", v))

				case *backuppb.Error_RegionError:
					logutil.CL(ctx).Warn("backup occur region error", zap.Reflect("error", v))

				case *backuppb.Error_ClusterIdError:
					logutil.CL(ctx).Error("backup occur cluster ID error", zap.Reflect("error", v))
					return res, errors.Annotatef(berrors.ErrKVClusterIDMismatch, "%v", errPb)
				default:
					if utils.MessageIsRetryableStorageError(errPb.GetMsg()) {
						logutil.CL(ctx).Warn("backup occur storage error", zap.String("error", errPb.GetMsg()))
						continue
					}
					var errMsg string
					if utils.MessageIsNotFoundStorageError(errPb.GetMsg()) {
						errMsg = fmt.Sprintf("File or directory not found on TiKV Node (store id: %v; Address: %s). "+
							"work around:please ensure br and tikv nodes share a same storage and the user of br and tikv has same uid.",
							store.GetId(), redact.String(store.GetAddress()))
						logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg))
					}
					if utils.MessageIsPermissionDeniedStorageError(errPb.GetMsg()) {
						errMsg = fmt.Sprintf("I/O permission denied error occurs on TiKV Node(store id: %v; Address: %s). "+
							"work around:please ensure tikv has permission to read from & write to the storage.",
							store.GetId(), redact.String(store.GetAddress()))
						logutil.CL(ctx).Error("", zap.String("error", berrors.ErrKVStorage.Error()+": "+errMsg))
					}

					if len(errMsg) <= 0 {
						errMsg = errPb.Msg
					}
					return res, errors.Annotatef(berrors.ErrKVStorage, "error happen in store %v at %s: %s %s",
						store.GetId(),
						redact.String(store.GetAddress()),
						req.StorageBackend.String(),
						errMsg,
					)
				}
			}
		case err := <-push.errCh:
			if !berrors.Is(err, berrors.ErrFailedToConnect) {
				return res, errors.Annotatef(err, "failed to backup range [%s, %s)", redact.Key(req.StartKey), redact.Key(req.EndKey))
			}
			logutil.CL(ctx).Warn("skipping disconnected stores", logutil.ShortError(err))
			return res, nil
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"testing"
)

func TestCenter(t *testing.T) {
	tests := []struct {
		x, y, width, height int
		want                Point
	}{
		{700, 1412, 843, 823, Point{1122, 1824}},
		{383, 1044, 1353, 1331, Point{1060, 1710}},
		{1137, 1277, 825, 977, Point{1550, 1766}},
		{1096, 1322, 1156, 1157, Point{1674, 1901}},
		{799, 1871, 549, 570, Point{1074, 2156}},
	}

	for _, test := range tests {
		got := Center(test.x, test.y, test.width, test.height)
		if got != test.want {
			t.Errorf("Center failed: got: %v, test.want: %v", got, test.want)
		}
	}

}

func TestRatio(t *testing.T) {
	tests := []struct {
		x, y int
		want float32
	}{
		{1, 2, 0.5},
		{2, 1, 2},
		{1920, 1080, 1.7777777777},
		{1, 0, 0.0},
	}

	for _, test := range tests {
		got, _ := Ratio(test.x, test.y)
		if got != test.want {
			t.Errorf("got: %v, want: %v", got, test.want)
		}
	}
}

func TestDirection(t *testing.T) {
	tests := []struct {
		ratio         float32
		wantDirection int
		wantBadness   float32
	}{
		{1920.0 / 1080.0, VIRTICAL, 0.777777777},
		{1080.0 / 1920.0, HORIZONTAL, 0.4375},
		{1920.0 / 1840.0, STAY, 0.0},
		{1920.0 / 2000.0, STAY, 0.0},
	}

	for i, test := range tests {
		t.Run(fmt.Sprintf("test:%v", i), func(t *testing.T) {
			d, b := Direction(test.ratio)
			if d != test.wantDirection {
				t.Fatalf("Direciton failed: got: %v, want: %v", d, test.wantDirection)
			}
			if b != test.wantBadness {
				t.Errorf("Badness failed: got: %v, want: %v", b, test.wantBadness)
			}
		})
	}
}
<commit_msg>added TestPlacement.<commit_after>package main

import (
	"fmt"
	"math"
	"testing"
)

func TestCenter(t *testing.T) {
	tests := []struct {
		x, y, width, height int
		want                Point
	}{
		{700, 1412, 843, 823, Point{1122, 1824}},
		{383, 1044, 1353, 1331, Point{1060, 1710}},
		{1137, 1277, 825, 977, Point{1550, 1766}},
		{1096, 1322, 1156, 1157, Point{1674, 1901}},
		{799, 1871, 549, 570, Point{1074, 2156}},
	}

	for _, test := range tests {
		got := Center(test.x, test.y, test.width, test.height)
		if got != test.want {
			t.Errorf("Center failed: got: %v, test.want: %v", got, test.want)
		}
	}

}

func TestRatio(t *testing.T) {
	tests := []struct {
		x, y int
		want float64
	}{
		{1, 2, 0.5},
		{2, 1, 2},
		{1920, 1080, 1.7777777777777777},
		{1, 0, 0.0},
	}

	for _, test := range tests {
		got, _ := Ratio(test.x, test.y)
		if got != test.want {
			t.Errorf("got: %v, want: %v", got, test.want)
		}
	}
}

func TestDirection(t *testing.T) {
	tests := []struct {
		ratio         float64
		wantDirection int
		wantBadness   float64
	}{
		{1920.0 / 1080.0, VIRTICAL, math.Abs(math.Log10(1920.0 / 1080.0))},
		{1080.0 / 1920.0, HORIZONTAL, math.Abs(math.Log10(1080.0 / 1920.0))},
		{1.0 / 1920.0, HORIZONTAL, 1},
		{1920.0 / 1.0, VIRTICAL, 1},
		{1920.0 / 1840.0, STAY, 0.0},
		{1920.0 / 2000.0, STAY, 0.0},
	}

	for i, test := range tests {
		t.Run(fmt.Sprintf("test:%v", i), func(t *testing.T) {
			d, b := Direction(test.ratio)
			if d != test.wantDirection {
				t.Fatalf("Direction failed: got: %v, want: %v", d, test.wantDirection)
			}
			if b != test.wantBadness {
				t.Errorf("Badness failed: got: %v, want: %v", b, test.wantBadness)
			}
		})
	}
}

func TestPlacement(t *testing.T) {
	tests := []struct {
		x, y, rx, ry int
		want         int
	}{
		{1, 1, 2, 2, WEST},
		{2, 1, 2, 2, NORTH},
		{2, 2, 2, 2, ON_TARGET},
		{2, 2, 1, 2, EAST},
		{2, 2, 2, 1, SOUTH},
	}

	for _, test := range tests {
		got := Placement(test.x, test.y, test.rx, test.ry)
		if got != test.want {
			t.Errorf("Wrong Placement: got: %v, want: %v", got, test.want)
		}
	}
}
<|endoftext|>


<commit_before>package bootstrap

import (
	"os"
	"path/filepath"

	"github.com/asticode/go-astilectron"
	"github.com/pkg/errors"
)

// Run runs the bootstrap
func Run(o Options) (err error) {
	// Create astilectron
	var a *astilectron.Astilectron
	if a, err = astilectron.New(o.AstilectronOptions); err != nil {
		return errors.Wrap(err, "creating new astilectron failed")
	}
	defer a.Close()
	a.HandleSignals()

	// Adapt astilectron
	if o.AdaptAstilectron != nil {
		o.AdaptAstilectron(a)
	}

	// Base directory path default to executable path
	if o.BaseDirectoryPath == "" {
		if o.BaseDirectoryPath, err = os.Executable(); err != nil {
			return errors.Wrap(err, "getting executable path failed")
		}
		o.BaseDirectoryPath = filepath.Dir(o.BaseDirectoryPath)
	}

	// Provision
	if err = provision(o.BaseDirectoryPath, o.RestoreAssets, o.CustomProvision); err != nil {
		return errors.Wrap(err, "provisioning failed")
	}

	// Start
	if err = a.Start(); err != nil {
		return errors.Wrap(err, "starting astilectron failed")
	}

	// Serve or handle messages
	var url string
	if o.MessageHandler == nil {
		var ln = serve(o.BaseDirectoryPath, o.AdaptRouter, o.TemplateData)
		defer ln.Close()
		url = "http://" + ln.Addr().String() + o.Homepage
	} else {
		url = filepath.Join(o.BaseDirectoryPath, "resources", "app", o.Homepage)
	}

	// Debug
	if o.Debug {
		o.WindowOptions.Width = astilectron.PtrInt(*o.WindowOptions.Width + 700)
	}

	// Init window
	var w *astilectron.Window
	if w, err = a.NewWindow(url, o.WindowOptions); err != nil {
		return errors.Wrap(err, "new window failed")
	}

	// Handle messages
	if o.MessageHandler != nil {
		w.On(astilectron.EventNameWindowEventMessage, handleMessages(w, o.MessageHandler))
	}

	// Adapt window
	if o.AdaptWindow != nil {
		o.AdaptWindow(w)
	}

	// Create window
	if err = w.Create(); err != nil {
		return errors.Wrap(err, "creating window failed")
	}

	// Debug
	if o.Debug {
		if err = w.OpenDevTools(); err != nil {
			return errors.Wrap(err, "opening dev tools failed")
		}
	}

	// Blocking pattern
	a.Wait()
	return
}
<commit_msg>Moved bootstrap window adapter<commit_after>package bootstrap

import (
	"os"
	"path/filepath"

	"github.com/asticode/go-astilectron"
	"github.com/pkg/errors"
)

// Run runs the bootstrap
func Run(o Options) (err error) {
	// Create astilectron
	var a *astilectron.Astilectron
	if a, err = astilectron.New(o.AstilectronOptions); err != nil {
		return errors.Wrap(err, "creating new astilectron failed")
	}
	defer a.Close()
	a.HandleSignals()

	// Adapt astilectron
	if o.AdaptAstilectron != nil {
		o.AdaptAstilectron(a)
	}

	// Base directory path default to executable path
	if o.BaseDirectoryPath == "" {
		if o.BaseDirectoryPath, err = os.Executable(); err != nil {
			return errors.Wrap(err, "getting executable path failed")
		}
		o.BaseDirectoryPath = filepath.Dir(o.BaseDirectoryPath)
	}

	// Provision
	if err = provision(o.BaseDirectoryPath, o.RestoreAssets, o.CustomProvision); err != nil {
		return errors.Wrap(err, "provisioning failed")
	}

	// Start
	if err = a.Start(); err != nil {
		return errors.Wrap(err, "starting astilectron failed")
	}

	// Serve or handle messages
	var url string
	if o.MessageHandler == nil {
		var ln = serve(o.BaseDirectoryPath, o.AdaptRouter, o.TemplateData)
		defer ln.Close()
		url = "http://" + ln.Addr().String() + o.Homepage
	} else {
		url = filepath.Join(o.BaseDirectoryPath, "resources", "app", o.Homepage)
	}

	// Debug
	if o.Debug {
		o.WindowOptions.Width = astilectron.PtrInt(*o.WindowOptions.Width + 700)
	}

	// Init window
	var w *astilectron.Window
	if w, err = a.NewWindow(url, o.WindowOptions); err != nil {
		return errors.Wrap(err, "new window failed")
	}

	// Handle messages
	if o.MessageHandler != nil {
		w.On(astilectron.EventNameWindowEventMessage, handleMessages(w, o.MessageHandler))
	}

	// Create window
	if err = w.Create(); err != nil {
		return errors.Wrap(err, "creating window failed")
	}

	// Adapt window
	if o.AdaptWindow != nil {
		o.AdaptWindow(w)
	}

	// Debug
	if o.Debug {
		if err = w.OpenDevTools(); err != nil {
			return errors.Wrap(err, "opening dev tools failed")
		}
	}

	// Blocking pattern
	a.Wait()
	return
}
<|endoftext|>


<commit_before>/* Copyright 2017 Google Inc.

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

    https://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 service

import (
	"errors"
	"fmt"
	"path"

	log "github.com/golang/glog"
	"github.com/google/link022/agent/syscmd"
	"github.com/google/link022/agent/util/ocutil"
	"github.com/google/link022/generated/ocstruct"
)

const (
	commonConfigTemplate = `
interface=%s
# Driver; nl80211 is used with all Linux mac80211 drivers.
driver=nl80211
hw_mode=%s
channel=%d

`

	bssConfigTemplate = `
# bssid for multiple wlans, the format is like "wlan0_1"
# For the first wlan, there should be no bssid field, otherwise hostapd
# will fail to start.
bss=%s_%d
`

	wlanConfigTemplate = `ssid=%s
bridge=%s
ap_isolate=%d
`

	authConfigTemplate = `ieee8021x=1
auth_algs=1
wpa=2
rsn_pairwise=CCMP
wpa_key_mgmt=WPA-EAP
macaddr_acl=0
auth_server_addr=%s
auth_server_port=%d
auth_server_shared_secret=%s
nas_identifier=%s
`
)

// configHostapd configures the hostapd program on this device based on the given AP configuration.
func configHostapd(apConfig *ocstruct.Device, wlanINTFName string) error {
	hostname := *apConfig.Hostname
	apRadios := apConfig.Radios
	if apRadios == nil || len(apRadios.Radio) == 0 {
		log.Error("No radio configuration found.")
		return errors.New("no radio configuration found")
	}

	if len(apRadios.Radio) > 1 {
		log.Errorf("Invalid radio number, expected: 1, actual: %d.", len(apRadios.Radio))
		return errors.New("not supporting multiple radios")
	}

	authServerConfigs := ocutil.RadiusServers(apConfig)
	for _, apRadio := range apRadios.Radio {
		radioConfig := apRadio.Config
		wlanConfigs := wlanWithOpFreq(apConfig, radioConfig.OperatingFrequency)

		// Genearte hostapd configuration.
		hostapdConfig := hostapdConfigFile(radioConfig, authServerConfigs, wlanConfigs, wlanINTFName, hostname)

		// Save the hostapd configuration file.
		configFileName := hostapdConfFileName(wlanINTFName)
		if err := syscmd.SaveToFile(runFolder, configFileName, hostapdConfig); err != nil {
			return err
		}

		// Start hostapd.
		if err := cmdRunner.StartHostapd(path.Join(runFolder, configFileName)); err != nil {
			return err
		}
	}

	return nil
}

// hostapdConfigFile generates the content of hostapd configuration file based on the given configuration.
func hostapdConfigFile(radioConfig *ocstruct.OpenconfigOfficeAp_Radios_Radio_Config,
	authServerConfigs map[string]*ocstruct.OpenconfigOfficeAp_System_Aaa_ServerGroups_ServerGroup_Servers_Server,
	wlanConfigs []*ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config,
	wlanINTFName string, hostname string) string {
	log.Infof("Generating hostapd configuration for radio %v...", *radioConfig.Id)
	hostapdConfig := ""

	// Generate common configuration.
	radioHWMode := hostapdHardwareMode(radioConfig.OperatingFrequency)
	commonConfig := fmt.Sprintf(commonConfigTemplate, wlanINTFName, radioHWMode, *radioConfig.Channel)
	hostapdConfig += commonConfig

	// Generate wlan configuration.
	for i, wlanConfig := range wlanConfigs {
		wlanName := *wlanConfig.Name
		log.Infof("Adding hostapd configuration for WLAN %v...", wlanName)

		if i > 0 {
			// Add BSS configuration.
			bssConfig := fmt.Sprintf(bssConfigTemplate, wlanINTFName, i)
			hostapdConfig += bssConfig
		}

		// Add WLAN configuration.
		wlanBridgeName := getBridgeName(int(*wlanConfig.VlanId))

		wlanStationIsolation := 0
		if wlanConfig.StationIsolation != nil{
			if *wlanConfig.StationIsolation {
				wlanStationIsolation = 1
			} else {
				wlanStationIsolation = 0
			}
		}

		hostapdWLANConfig := fmt.Sprintf(wlanConfigTemplate, wlanName, wlanBridgeName, wlanStationIsolation)
		hostapdConfig += hostapdWLANConfig

		// Add AUTH configuration.
		if wlanConfig.Opmode == ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config_Opmode_WPA2_ENTERPRISE {
			// Add radius configuration.
			authServerConfig := authServerConfigs[wlanName]
			// TODO: Add validation to ensure authServerConfig exists.
			radiusServerAddr := *authServerConfig.Address
			radiusServerPort := *authServerConfig.Radius.Config.AuthPort
			radiusSecret := *authServerConfig.Radius.Config.SecretKey
			authConfig := fmt.Sprintf(authConfigTemplate, radiusServerAddr, radiusServerPort, radiusSecret, hostname)
			hostapdConfig += authConfig
		}
		// TODO: Add validation to block WPA2_PERSONAL.
	}

	log.Info("Generated hostapd configuration.")
	return hostapdConfig
}

func hostapdHardwareMode(opFrequency ocstruct.E_OpenconfigWifiTypes_OPERATING_FREQUENCY) string {
	if opFrequency == ocstruct.OpenconfigWifiTypes_OPERATING_FREQUENCY_FREQ_2GHZ ||
		opFrequency == ocstruct.OpenconfigWifiTypes_OPERATING_FREQUENCY_FREQ_2_5_GHZ {
		return "g"
	}
	return "a"
}

func wlanWithOpFreq(apConfig *ocstruct.Device,
	targetFreq ocstruct.E_OpenconfigWifiTypes_OPERATING_FREQUENCY) []*ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config {
	var matchedWLANs []*ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config

	wlans := apConfig.Ssids
	if wlans == nil || len(wlans.Ssid) == 0 {
		// No WLAN on this AP.
		return matchedWLANs
	}

	for _, wlan := range wlans.Ssid {
		wlanConfig := wlan.Config
		if wlanConfig.OperatingFrequency == ocstruct.OpenconfigWifiTypes_OPERATING_FREQUENCY_FREQ_2_5_GHZ ||
			wlanConfig.OperatingFrequency == targetFreq {
			matchedWLANs = append(matchedWLANs, wlanConfig)
		}
	}
	return matchedWLANs
}
func hostapdConfFileName(wlanINTFName string) string {
	return fmt.Sprintf("hostapd_%s.conf", wlanINTFName)
}
<commit_msg>simpilfied if block<commit_after>/* Copyright 2017 Google Inc.

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

    https://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 service

import (
	"errors"
	"fmt"
	"path"

	log "github.com/golang/glog"
	"github.com/google/link022/agent/syscmd"
	"github.com/google/link022/agent/util/ocutil"
	"github.com/google/link022/generated/ocstruct"
)

const (
	commonConfigTemplate = `
interface=%s
# Driver; nl80211 is used with all Linux mac80211 drivers.
driver=nl80211
hw_mode=%s
channel=%d

`

	bssConfigTemplate = `
# bssid for multiple wlans, the format is like "wlan0_1"
# For the first wlan, there should be no bssid field, otherwise hostapd
# will fail to start.
bss=%s_%d
`

	wlanConfigTemplate = `ssid=%s
bridge=%s
ap_isolate=%d
`

	authConfigTemplate = `ieee8021x=1
auth_algs=1
wpa=2
rsn_pairwise=CCMP
wpa_key_mgmt=WPA-EAP
macaddr_acl=0
auth_server_addr=%s
auth_server_port=%d
auth_server_shared_secret=%s
nas_identifier=%s
`
)

// configHostapd configures the hostapd program on this device based on the given AP configuration.
func configHostapd(apConfig *ocstruct.Device, wlanINTFName string) error {
	hostname := *apConfig.Hostname
	apRadios := apConfig.Radios
	if apRadios == nil || len(apRadios.Radio) == 0 {
		log.Error("No radio configuration found.")
		return errors.New("no radio configuration found")
	}

	if len(apRadios.Radio) > 1 {
		log.Errorf("Invalid radio number, expected: 1, actual: %d.", len(apRadios.Radio))
		return errors.New("not supporting multiple radios")
	}

	authServerConfigs := ocutil.RadiusServers(apConfig)
	for _, apRadio := range apRadios.Radio {
		radioConfig := apRadio.Config
		wlanConfigs := wlanWithOpFreq(apConfig, radioConfig.OperatingFrequency)

		// Genearte hostapd configuration.
		hostapdConfig := hostapdConfigFile(radioConfig, authServerConfigs, wlanConfigs, wlanINTFName, hostname)

		// Save the hostapd configuration file.
		configFileName := hostapdConfFileName(wlanINTFName)
		if err := syscmd.SaveToFile(runFolder, configFileName, hostapdConfig); err != nil {
			return err
		}

		// Start hostapd.
		if err := cmdRunner.StartHostapd(path.Join(runFolder, configFileName)); err != nil {
			return err
		}
	}

	return nil
}

// hostapdConfigFile generates the content of hostapd configuration file based on the given configuration.
func hostapdConfigFile(radioConfig *ocstruct.OpenconfigOfficeAp_Radios_Radio_Config,
	authServerConfigs map[string]*ocstruct.OpenconfigOfficeAp_System_Aaa_ServerGroups_ServerGroup_Servers_Server,
	wlanConfigs []*ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config,
	wlanINTFName string, hostname string) string {
	log.Infof("Generating hostapd configuration for radio %v...", *radioConfig.Id)
	hostapdConfig := ""

	// Generate common configuration.
	radioHWMode := hostapdHardwareMode(radioConfig.OperatingFrequency)
	commonConfig := fmt.Sprintf(commonConfigTemplate, wlanINTFName, radioHWMode, *radioConfig.Channel)
	hostapdConfig += commonConfig

	// Generate wlan configuration.
	for i, wlanConfig := range wlanConfigs {
		wlanName := *wlanConfig.Name
		log.Infof("Adding hostapd configuration for WLAN %v...", wlanName)

		if i > 0 {
			// Add BSS configuration.
			bssConfig := fmt.Sprintf(bssConfigTemplate, wlanINTFName, i)
			hostapdConfig += bssConfig
		}

		// Add WLAN configuration.
		wlanBridgeName := getBridgeName(int(*wlanConfig.VlanId))

		wlanStationIsolation := 0
		if wlanConfig.StationIsolation != nil && *wlanConfig.StationIsolation{
				wlanStationIsolation = 1
		}

		hostapdWLANConfig := fmt.Sprintf(wlanConfigTemplate, wlanName, wlanBridgeName, wlanStationIsolation)
		hostapdConfig += hostapdWLANConfig

		// Add AUTH configuration.
		if wlanConfig.Opmode == ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config_Opmode_WPA2_ENTERPRISE {
			// Add radius configuration.
			authServerConfig := authServerConfigs[wlanName]
			// TODO: Add validation to ensure authServerConfig exists.
			radiusServerAddr := *authServerConfig.Address
			radiusServerPort := *authServerConfig.Radius.Config.AuthPort
			radiusSecret := *authServerConfig.Radius.Config.SecretKey
			authConfig := fmt.Sprintf(authConfigTemplate, radiusServerAddr, radiusServerPort, radiusSecret, hostname)
			hostapdConfig += authConfig
		}
		// TODO: Add validation to block WPA2_PERSONAL.
	}

	log.Info("Generated hostapd configuration.")
	return hostapdConfig
}

func hostapdHardwareMode(opFrequency ocstruct.E_OpenconfigWifiTypes_OPERATING_FREQUENCY) string {
	if opFrequency == ocstruct.OpenconfigWifiTypes_OPERATING_FREQUENCY_FREQ_2GHZ ||
		opFrequency == ocstruct.OpenconfigWifiTypes_OPERATING_FREQUENCY_FREQ_2_5_GHZ {
		return "g"
	}
	return "a"
}

func wlanWithOpFreq(apConfig *ocstruct.Device,
	targetFreq ocstruct.E_OpenconfigWifiTypes_OPERATING_FREQUENCY) []*ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config {
	var matchedWLANs []*ocstruct.OpenconfigOfficeAp_Ssids_Ssid_Config

	wlans := apConfig.Ssids
	if wlans == nil || len(wlans.Ssid) == 0 {
		// No WLAN on this AP.
		return matchedWLANs
	}

	for _, wlan := range wlans.Ssid {
		wlanConfig := wlan.Config
		if wlanConfig.OperatingFrequency == ocstruct.OpenconfigWifiTypes_OPERATING_FREQUENCY_FREQ_2_5_GHZ ||
			wlanConfig.OperatingFrequency == targetFreq {
			matchedWLANs = append(matchedWLANs, wlanConfig)
		}
	}
	return matchedWLANs
}
func hostapdConfFileName(wlanINTFName string) string {
	return fmt.Sprintf("hostapd_%s.conf", wlanINTFName)
}
<|endoftext|>


<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package driver

import (
	"database/sql"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/os/gtime"
)

// MyDriver is a custom database driver, which is used for testing only.
// For simplifying the unit testing case purpose, MyDriver struct inherits the mysql driver
// gdb.DriverMysql and overwrites its functions DoQuery and DoExec.
// So if there's any sql execution, it goes through MyDriver.DoQuery/MyDriver.DoExec firstly
// and then gdb.DriverMysql.DoQuery/gdb.DriverMysql.DoExec.
// You can call it sql "HOOK" or "HiJack" as your will.
type MyDriver struct {
	*gdb.DriverMysql
}

var (
	// customDriverName is my driver name, which is used for registering.
	customDriverName = "MyDriver"
)

func init() {
	// It here registers my custom driver in package initialization function "init".
	// You can later use this type in the database configuration.
	if err := gdb.Register(customDriverName, &MyDriver{}); err != nil {
		panic(err)
	}
}

// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *MyDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
	return &MyDriver{
		&gdb.DriverMysql{
			Core: core,
		},
	}, nil
}

// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoQuery(link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
	tsMilli := gtime.TimestampMilli()
	rows, err = d.DriverMysql.DoQuery(link, sql, args...)
	link.Exec(
		"INSERT INTO `%s`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
		gdb.FormatSqlWithArgs(sql, args),
		gtime.TimestampMilli()-tsMilli,
		gtime.Now(),
		err,
	)
	return
}

// DoExec commits the query string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoExec(link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
	tsMilli := gtime.TimestampMilli()
	result, err = d.DriverMysql.DoExec(link, sql, args...)
	link.Exec(
		"INSERT INTO `%s`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
		gdb.FormatSqlWithArgs(sql, args),
		gtime.TimestampMilli()-tsMilli,
		gtime.Now(),
		err,
	)
	return
}
<commit_msg>gdb driver example updates<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package driver

import (
	"database/sql"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/os/gtime"
)

// MyDriver is a custom database driver, which is used for testing only.
// For simplifying the unit testing case purpose, MyDriver struct inherits the mysql driver
// gdb.DriverMysql and overwrites its functions DoQuery and DoExec.
// So if there's any sql execution, it goes through MyDriver.DoQuery/MyDriver.DoExec firstly
// and then gdb.DriverMysql.DoQuery/gdb.DriverMysql.DoExec.
// You can call it sql "HOOK" or "HiJack" as your will.
type MyDriver struct {
	*gdb.DriverMysql
}

var (
	// customDriverName is my driver name, which is used for registering.
	customDriverName = "MyDriver"
)

func init() {
	// It here registers my custom driver in package initialization function "init".
	// You can later use this type in the database configuration.
	if err := gdb.Register(customDriverName, &MyDriver{}); err != nil {
		panic(err)
	}
}

// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *MyDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
	return &MyDriver{
		&gdb.DriverMysql{
			Core: core,
		},
	}, nil
}

// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoQuery(link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
	tsMilli := gtime.TimestampMilli()
	rows, err = d.DriverMysql.DoQuery(link, sql, args...)
	link.Exec(
		"INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
		gdb.FormatSqlWithArgs(sql, args),
		gtime.TimestampMilli()-tsMilli,
		gtime.Now(),
		err,
	)
	return
}

// DoExec commits the query string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoExec(link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
	tsMilli := gtime.TimestampMilli()
	result, err = d.DriverMysql.DoExec(link, sql, args...)
	link.Exec(
		"INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
		gdb.FormatSqlWithArgs(sql, args),
		gtime.TimestampMilli()-tsMilli,
		gtime.Now(),
		err,
	)
	return
}
<|endoftext|>


<commit_before>package test

import (
	"testing"

	"github.com/onsi/ginkgo"
	gomega "github.com/onsi/gomega"

	"k8s.io/component-base/logs"
	ginkgowrapper "k8s.io/kubernetes/test/e2e/framework/ginkgowrapper"

	// test sources
	_ "github.com/phoenixking25/multi-tenancy/benchmarks/e2e/tests/block_ns_quotas"
	_ "github.com/realshuting/multi-tenancy/benchmarks/e2e/tests/block_cluster_resources"
	_ "github.com/realshuting/multi-tenancy/benchmarks/e2e/tests/configure_ns_quotas"
)

// RunE2ETests runs the multi-tenancy benchmark tests
func RunE2ETests(t *testing.T) {
	logs.InitLogs()
	defer logs.FlushLogs()

	gomega.RegisterFailHandler(ginkgowrapper.Fail)
	ginkgo.RunSpecs(t, "Multi-Tenancy Benchmarks")
}
<commit_msg>added test with change in path<commit_after>package test

import (
	"testing"

	"github.com/onsi/ginkgo"
	gomega "github.com/onsi/gomega"

	"k8s.io/component-base/logs"
	ginkgowrapper "k8s.io/kubernetes/test/e2e/framework/ginkgowrapper"

	// test sources
	_ "github.com/realshuting/multi-tenancy/benchmarks/e2e/tests/block_cluster_resources"
	_ "github.com/realshuting/multi-tenancy/benchmarks/e2e/tests/block_ns_quotas"
	_ "github.com/realshuting/multi-tenancy/benchmarks/e2e/tests/configure_ns_quotas"
)

// RunE2ETests runs the multi-tenancy benchmark tests
func RunE2ETests(t *testing.T) {
	logs.InitLogs()
	defer logs.FlushLogs()

	gomega.RegisterFailHandler(ginkgowrapper.Fail)
	ginkgo.RunSpecs(t, "Multi-Tenancy Benchmarks")
}
<|endoftext|>


<commit_before>package converter

import (
	"strings"
	"time"
)

func convertDateFrom(layout string, value string) (string, error) {
	t, err := time.Parse("02.01.2006", value)
	if err != nil {
		return "", err
	}
	return t.Format("02/01/2006"), nil
}

func convertThousandAndCommaSeparator(value string) string {
	value = strings.Replace(value, ".", "", -1)
	value = strings.Replace(value, ",", ".", -1)
	return value
}

func abs(value string) string {
	return strings.TrimLeft(value, "-")
}

func isNegative(value string) bool {
	return value[0:1] == "-"
}
<commit_msg>Fixed bug with not used layout string<commit_after>package converter

import (
	"strings"
	"time"
)

func convertDateFrom(layout string, value string) (string, error) {
	t, err := time.Parse(layout, value)
	if err != nil {
		return "", err
	}
	return t.Format("02/01/2006"), nil
}

func convertThousandAndCommaSeparator(value string) string {
	value = strings.Replace(value, ".", "", -1)
	value = strings.Replace(value, ",", ".", -1)
	return value
}

func abs(value string) string {
	return strings.TrimLeft(value, "-")
}

func isNegative(value string) bool {
	return value[0:1] == "-"
}
<|endoftext|>


<commit_before>package bridge

import (
	"fmt"
	"net"

	log "github.com/Sirupsen/logrus"
	"github.com/vishvananda/netlink"
)

var bridgeNetworks []*net.IPNet

func init() {
	// Here we don't follow the convention of using the 1st IP of the range for the gateway.
	// This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges.
	// In theory this shouldn't matter - in practice there's bound to be a few scripts relying
	// on the internal addressing or other stupid things like that.
	// They shouldn't, but hey, let's not break them unless we really have to.
	for _, addr := range []string{
		"172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
		"10.0.42.1/16",   // Don't even try using the entire /8, that's too intrusive
		"10.1.42.1/16",
		"10.42.42.1/16",
		"172.16.42.1/24",
		"172.16.43.1/24",
		"172.16.44.1/24",
		"10.0.42.1/24",
		"10.0.43.1/24",
		"192.168.42.1/24",
		"192.168.43.1/24",
		"192.168.44.1/24",
	} {
		ip, net, err := net.ParseCIDR(addr)
		if err != nil {
			log.Errorf("Failed to parse address %s", addr)
			continue
		}
		net.IP = ip
		bridgeNetworks = append(bridgeNetworks, net)
	}
}

func SetupBridgeIPv4(i *Interface) error {
	bridgeIPv4, err := electBridgeIPv4(i.Config)
	if err != nil {
		return err
	}

	log.Debugf("Creating bridge interface %q with network %s", i.Config.BridgeName, bridgeIPv4)
	if err := netlink.AddrAdd(i.Link, &netlink.Addr{bridgeIPv4, ""}); err != nil {
		return fmt.Errorf("Failed to add IPv4 address %s to bridge: %v", bridgeIPv4, err)
	}

	return nil
}

func electBridgeIPv4(config *Configuration) (*net.IPNet, error) {
	// Use the requested IPv4 CIDR when available.
	if config.AddressIPv4 != nil {
		return config.AddressIPv4, nil
	}

	// We don't check for an error here, because we don't really care if we
	// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
	// is nil. It either doesn't exist, or we can't read it for some reason.
	nameservers := []string{}
	if resolvConf, _ := readResolvConf(); resolvConf != nil {
		nameservers = append(nameservers, getNameserversAsCIDR(resolvConf)...)
	}

	// Try to automatically elect appropriate brige IPv4 settings.
	for _, n := range bridgeNetworks {
		if err := checkNameserverOverlaps(nameservers, n); err == nil {
			if err := checkRouteOverlaps(n); err == nil {
				return n, nil
			}
		}
	}

	return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName)
}

func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
	for _, ns := range nameservers {
		_, nsNetwork, err := net.ParseCIDR(ns)
		if err != nil {
			return err
		}
		if networkOverlaps(toCheck, nsNetwork) {
			return fmt.Errorf("Requested network %s overlaps with name server")
		}
	}
	return nil
}

func checkRouteOverlaps(toCheck *net.IPNet) error {
	networks, err := netlink.RouteList(nil, netlink.FAMILY_V4)
	if err != nil {
		return err
	}

	for _, network := range networks {
		// TODO Is that right?
		if network.Dst != nil && networkOverlaps(toCheck, network.Dst) {
			return fmt.Errorf("Requested network %s overlaps with an existing network")
		}
	}
	return nil
}

func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
		return true
	}
	if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
		return true
	}
	return false
}

func networkRange(network *net.IPNet) (net.IP, net.IP) {
	var netIP net.IP
	if network.IP.To4() != nil {
		netIP = network.IP.To4()
	} else if network.IP.To16() != nil {
		netIP = network.IP.To16()
	} else {
		return nil, nil
	}

	lastIP := make([]byte, len(netIP), len(netIP))
	for i := 0; i < len(netIP); i++ {
		lastIP[i] = netIP[i] | ^network.Mask[i]
	}
	return netIP.Mask(network.Mask), net.IP(lastIP)
}
<commit_msg>Fix minor static analysis issue in setup_ipv4.go<commit_after>package bridge

import (
	"fmt"
	"net"

	log "github.com/Sirupsen/logrus"
	"github.com/vishvananda/netlink"
)

var bridgeNetworks []*net.IPNet

func init() {
	// Here we don't follow the convention of using the 1st IP of the range for the gateway.
	// This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges.
	// In theory this shouldn't matter - in practice there's bound to be a few scripts relying
	// on the internal addressing or other stupid things like that.
	// They shouldn't, but hey, let's not break them unless we really have to.
	for _, addr := range []string{
		"172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
		"10.0.42.1/16",   // Don't even try using the entire /8, that's too intrusive
		"10.1.42.1/16",
		"10.42.42.1/16",
		"172.16.42.1/24",
		"172.16.43.1/24",
		"172.16.44.1/24",
		"10.0.42.1/24",
		"10.0.43.1/24",
		"192.168.42.1/24",
		"192.168.43.1/24",
		"192.168.44.1/24",
	} {
		ip, net, err := net.ParseCIDR(addr)
		if err != nil {
			log.Errorf("Failed to parse address %s", addr)
			continue
		}
		net.IP = ip
		bridgeNetworks = append(bridgeNetworks, net)
	}
}

func SetupBridgeIPv4(i *Interface) error {
	bridgeIPv4, err := electBridgeIPv4(i.Config)
	if err != nil {
		return err
	}

	log.Debugf("Creating bridge interface %q with network %s", i.Config.BridgeName, bridgeIPv4)
	if err := netlink.AddrAdd(i.Link, &netlink.Addr{bridgeIPv4, ""}); err != nil {
		return fmt.Errorf("Failed to add IPv4 address %s to bridge: %v", bridgeIPv4, err)
	}

	return nil
}

func electBridgeIPv4(config *Configuration) (*net.IPNet, error) {
	// Use the requested IPv4 CIDR when available.
	if config.AddressIPv4 != nil {
		return config.AddressIPv4, nil
	}

	// We don't check for an error here, because we don't really care if we
	// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
	// is nil. It either doesn't exist, or we can't read it for some reason.
	nameservers := []string{}
	if resolvConf, _ := readResolvConf(); resolvConf != nil {
		nameservers = append(nameservers, getNameserversAsCIDR(resolvConf)...)
	}

	// Try to automatically elect appropriate brige IPv4 settings.
	for _, n := range bridgeNetworks {
		if err := checkNameserverOverlaps(nameservers, n); err == nil {
			if err := checkRouteOverlaps(n); err == nil {
				return n, nil
			}
		}
	}

	return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName)
}

func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
	for _, ns := range nameservers {
		_, nsNetwork, err := net.ParseCIDR(ns)
		if err != nil {
			return err
		}
		if networkOverlaps(toCheck, nsNetwork) {
			return fmt.Errorf("Requested network %s overlaps with name server", toCheck.String())
		}
	}
	return nil
}

func checkRouteOverlaps(toCheck *net.IPNet) error {
	networks, err := netlink.RouteList(nil, netlink.FAMILY_V4)
	if err != nil {
		return err
	}

	for _, network := range networks {
		// TODO Is that right?
		if network.Dst != nil && networkOverlaps(toCheck, network.Dst) {
			return fmt.Errorf("Requested network %s overlaps with an existing network", toCheck.String())
		}
	}
	return nil
}

func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
		return true
	}
	if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
		return true
	}
	return false
}

func networkRange(network *net.IPNet) (net.IP, net.IP) {
	var netIP net.IP
	if network.IP.To4() != nil {
		netIP = network.IP.To4()
	} else if network.IP.To16() != nil {
		netIP = network.IP.To16()
	} else {
		return nil, nil
	}

	lastIP := make([]byte, len(netIP), len(netIP))
	for i := 0; i < len(netIP); i++ {
		lastIP[i] = netIP[i] | ^network.Mask[i]
	}
	return netIP.Mask(network.Mask), net.IP(lastIP)
}
<|endoftext|>


<commit_before>// Author: Conor Raftery
// Date: 2017-09-27

package main

import "fmt"

func main(){

	for i := 1; i <= 100; i++ {
		//if number can be divided by 3
		if i%3 == 0 {
			//if number can be divided by 15 (3*5)
			if i%5 == 0 {
				fmt.Println("FizzBuzz")
			} else {
				fmt.Println("Fizz")
			}
			//if number can be divided by 5
		} else if i%5 == 0 {
			fmt.Println("Buzz")
		} else {
			fmt.Println(i)
		}
	}
}<commit_msg>Task 3 Complete<commit_after>// Author: Conor Raftery
// Date: 2017-09-27

package main

import "fmt"

func main(){

	for i := 1; i <= 100; i++ {
		//if number can be divided by 3
		if i%3 == 0 {
			//if number can be divided by 15 (3*5)
			if i%5 == 0 {
				fmt.Println("FizzBuzz")
			} else {
				fmt.Println("Fizz")
			}
			//if number can be divided by 5
		} else if i%5 == 0 {
			fmt.Println("Buzz")
		} else {
			fmt.Println(i)
		}
	}
}<|endoftext|>


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

package gcloud

import (
	"fmt"
	"math/rand"
	"strings"
	"time"

	"golang.org/x/crypto/ssh/agent"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"

	"github.com/coreos/mantle/util"
)

func (a *API) vmname() string {
	return fmt.Sprintf("%s-%x", a.options.BaseName, rand.Int63())
}

// Taken from: https://github.com/golang/build/blob/master/buildlet/gce.go
func (a *API) mkinstance(userdata, name string, keys []*agent.Key) *compute.Instance {
	var metadataItems []*compute.MetadataItems
	if len(keys) > 0 {
		var sshKeys string
		for i, key := range keys {
			sshKeys += fmt.Sprintf("%d:%s\n", i, key)
		}

		metadataItems = append(metadataItems, &compute.MetadataItems{
			Key:   "ssh-keys",
			Value: &sshKeys,
		})
	}

	instancePrefix := "https://www.googleapis.com/compute/v1/projects/" + a.options.Project

	instance := &compute.Instance{
		Name:        name,
		MachineType: instancePrefix + "/zones/" + a.options.Zone + "/machineTypes/" + a.options.MachineType,
		Metadata: &compute.Metadata{
			Items: metadataItems,
		},
		Tags: &compute.Tags{
			// Apparently you need this tag in addition to the
			// firewall rules to open the port because these ports
			// are special?
			Items: []string{"https-server", "http-server"},
		},
		Disks: []*compute.AttachedDisk{
			{
				AutoDelete: true,
				Boot:       true,
				Type:       "PERSISTENT",
				InitializeParams: &compute.AttachedDiskInitializeParams{
					DiskName:    name,
					SourceImage: a.options.Image,
					DiskType:    "/zones/" + a.options.Zone + "/diskTypes/" + a.options.DiskType,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			&compute.NetworkInterface{
				AccessConfigs: []*compute.AccessConfig{
					&compute.AccessConfig{
						Type: "ONE_TO_ONE_NAT",
						Name: "External NAT",
					},
				},
				Network: instancePrefix + "/global/networks/" + a.options.Network,
			},
		},
	}
	// add cloud config
	if userdata != "" {
		instance.Metadata.Items = append(instance.Metadata.Items, &compute.MetadataItems{
			Key:   "user-data",
			Value: &userdata,
		})
	}

	return instance

}

type doable interface {
	Do(opts ...googleapi.CallOption) (*compute.Operation, error)
}

func (a *API) waitop(operation string, do doable) error {
	retry := func() error {
		op, err := do.Do()
		if err != nil {
			return err
		}

		switch op.Status {
		case "PENDING", "RUNNING":
			return fmt.Errorf("Operation %q is %q", operation, op.Status)
		case "DONE":
			if op.Error != nil {
				for _, operr := range op.Error.Errors {
					return fmt.Errorf("Error creating instance: %+v", operr)
				}
				return fmt.Errorf("Operation %q failed to start", op.Status)
			}

			return nil
		}

		return fmt.Errorf("Unknown operation status %q: %+v", op.Status, op)
	}

	// 5 minutes
	if err := util.Retry(30, 10*time.Second, retry); err != nil {
		return fmt.Errorf("Failed to wait for operation %q: %v", operation, err)
	}

	return nil
}

// CreateInstance creates a Google Compute Engine instance.
func (a *API) CreateInstance(userdata string, keys []*agent.Key) (*compute.Instance, error) {
	name := a.vmname()
	inst := a.mkinstance(userdata, name, keys)

	plog.Debugf("Creating instance %q", name)

	op, err := a.compute.Instances.Insert(a.options.Project, a.options.Zone, inst).Do()
	if err != nil {
		return nil, fmt.Errorf("failed to request new GCE instance: %v\n", err)
	}

	doable := a.compute.ZoneOperations.Get(a.options.Project, a.options.Zone, op.Name)
	if err := a.waitop(op.Name, doable); err != nil {
		return nil, err
	}

	inst, err = a.compute.Instances.Get(a.options.Project, a.options.Zone, name).Do()
	if err != nil {
		return nil, fmt.Errorf("failed getting instance %s details after creation: %v", name, err)
	}

	plog.Debugf("Created instance %q", name)

	return inst, nil
}

func (a *API) TerminateInstance(name string) error {
	plog.Debugf("Terminating instance %q", name)

	_, err := a.compute.Instances.Delete(a.options.Project, a.options.Zone, name).Do()
	return err
}

func (a *API) ListInstances(prefix string) ([]*compute.Instance, error) {
	var instances []*compute.Instance

	list, err := a.compute.Instances.List(a.options.Project, a.options.Zone).Do()
	if err != nil {
		return nil, err
	}

	for _, inst := range list.Items {
		if !strings.HasPrefix(inst.Name, prefix) {
			continue
		}

		instances = append(instances, inst)
	}

	return instances, nil
}

// Taken from: https://github.com/golang/build/blob/master/buildlet/gce.go
func InstanceIPs(inst *compute.Instance) (intIP, extIP string) {
	for _, iface := range inst.NetworkInterfaces {
		if strings.HasPrefix(iface.NetworkIP, "10.") {
			intIP = iface.NetworkIP
		}
		for _, accessConfig := range iface.AccessConfigs {
			if accessConfig.Type == "ONE_TO_ONE_NAT" {
				extIP = accessConfig.NatIP
			}
		}
	}
	return
}
<commit_msg>platform/api/gcloud: slight increase default gce node root disk size<commit_after>// Copyright 2016 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gcloud

import (
	"fmt"
	"math/rand"
	"strings"
	"time"

	"golang.org/x/crypto/ssh/agent"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"

	"github.com/coreos/mantle/util"
)

func (a *API) vmname() string {
	return fmt.Sprintf("%s-%x", a.options.BaseName, rand.Int63())
}

// Taken from: https://github.com/golang/build/blob/master/buildlet/gce.go
func (a *API) mkinstance(userdata, name string, keys []*agent.Key) *compute.Instance {
	var metadataItems []*compute.MetadataItems
	if len(keys) > 0 {
		var sshKeys string
		for i, key := range keys {
			sshKeys += fmt.Sprintf("%d:%s\n", i, key)
		}

		metadataItems = append(metadataItems, &compute.MetadataItems{
			Key:   "ssh-keys",
			Value: &sshKeys,
		})
	}

	instancePrefix := "https://www.googleapis.com/compute/v1/projects/" + a.options.Project

	instance := &compute.Instance{
		Name:        name,
		MachineType: instancePrefix + "/zones/" + a.options.Zone + "/machineTypes/" + a.options.MachineType,
		Metadata: &compute.Metadata{
			Items: metadataItems,
		},
		Tags: &compute.Tags{
			// Apparently you need this tag in addition to the
			// firewall rules to open the port because these ports
			// are special?
			Items: []string{"https-server", "http-server"},
		},
		Disks: []*compute.AttachedDisk{
			{
				AutoDelete: true,
				Boot:       true,
				Type:       "PERSISTENT",
				InitializeParams: &compute.AttachedDiskInitializeParams{
					DiskName:    name,
					SourceImage: a.options.Image,
					DiskType:    "/zones/" + a.options.Zone + "/diskTypes/" + a.options.DiskType,
					DiskSizeGb:  12,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			&compute.NetworkInterface{
				AccessConfigs: []*compute.AccessConfig{
					&compute.AccessConfig{
						Type: "ONE_TO_ONE_NAT",
						Name: "External NAT",
					},
				},
				Network: instancePrefix + "/global/networks/" + a.options.Network,
			},
		},
	}
	// add cloud config
	if userdata != "" {
		instance.Metadata.Items = append(instance.Metadata.Items, &compute.MetadataItems{
			Key:   "user-data",
			Value: &userdata,
		})
	}

	return instance

}

type doable interface {
	Do(opts ...googleapi.CallOption) (*compute.Operation, error)
}

func (a *API) waitop(operation string, do doable) error {
	retry := func() error {
		op, err := do.Do()
		if err != nil {
			return err
		}

		switch op.Status {
		case "PENDING", "RUNNING":
			return fmt.Errorf("Operation %q is %q", operation, op.Status)
		case "DONE":
			if op.Error != nil {
				for _, operr := range op.Error.Errors {
					return fmt.Errorf("Error creating instance: %+v", operr)
				}
				return fmt.Errorf("Operation %q failed to start", op.Status)
			}

			return nil
		}

		return fmt.Errorf("Unknown operation status %q: %+v", op.Status, op)
	}

	// 5 minutes
	if err := util.Retry(30, 10*time.Second, retry); err != nil {
		return fmt.Errorf("Failed to wait for operation %q: %v", operation, err)
	}

	return nil
}

// CreateInstance creates a Google Compute Engine instance.
func (a *API) CreateInstance(userdata string, keys []*agent.Key) (*compute.Instance, error) {
	name := a.vmname()
	inst := a.mkinstance(userdata, name, keys)

	plog.Debugf("Creating instance %q", name)

	op, err := a.compute.Instances.Insert(a.options.Project, a.options.Zone, inst).Do()
	if err != nil {
		return nil, fmt.Errorf("failed to request new GCE instance: %v\n", err)
	}

	doable := a.compute.ZoneOperations.Get(a.options.Project, a.options.Zone, op.Name)
	if err := a.waitop(op.Name, doable); err != nil {
		return nil, err
	}

	inst, err = a.compute.Instances.Get(a.options.Project, a.options.Zone, name).Do()
	if err != nil {
		return nil, fmt.Errorf("failed getting instance %s details after creation: %v", name, err)
	}

	plog.Debugf("Created instance %q", name)

	return inst, nil
}

func (a *API) TerminateInstance(name string) error {
	plog.Debugf("Terminating instance %q", name)

	_, err := a.compute.Instances.Delete(a.options.Project, a.options.Zone, name).Do()
	return err
}

func (a *API) ListInstances(prefix string) ([]*compute.Instance, error) {
	var instances []*compute.Instance

	list, err := a.compute.Instances.List(a.options.Project, a.options.Zone).Do()
	if err != nil {
		return nil, err
	}

	for _, inst := range list.Items {
		if !strings.HasPrefix(inst.Name, prefix) {
			continue
		}

		instances = append(instances, inst)
	}

	return instances, nil
}

// Taken from: https://github.com/golang/build/blob/master/buildlet/gce.go
func InstanceIPs(inst *compute.Instance) (intIP, extIP string) {
	for _, iface := range inst.NetworkInterfaces {
		if strings.HasPrefix(iface.NetworkIP, "10.") {
			intIP = iface.NetworkIP
		}
		for _, accessConfig := range iface.AccessConfigs {
			if accessConfig.Type == "ONE_TO_ONE_NAT" {
				extIP = accessConfig.NatIP
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>/*
Copyright AppsCode Inc. and Contributors

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 v1alpha2

import (
	"fmt"
	"math"
	"strconv"
	"time"

	"kubedb.dev/apimachinery/apis"
	catalog "kubedb.dev/apimachinery/apis/catalog/v1alpha1"
	"kubedb.dev/apimachinery/apis/kubedb"
	"kubedb.dev/apimachinery/crds"

	"gomodules.xyz/pointer"
	core "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	appslister "k8s.io/client-go/listers/apps/v1"
	kmapi "kmodules.xyz/client-go/api/v1"
	"kmodules.xyz/client-go/apiextensions"
	core_util "kmodules.xyz/client-go/core/v1"
	meta_util "kmodules.xyz/client-go/meta"
	appcat "kmodules.xyz/custom-resources/apis/appcatalog/v1alpha1"
	mona "kmodules.xyz/monitoring-agent-api/api/v1"
	ofst "kmodules.xyz/offshoot-api/api/v1"
)

func (_ Postgres) CustomResourceDefinition() *apiextensions.CustomResourceDefinition {
	return crds.MustCustomResourceDefinition(SchemeGroupVersion.WithResource(ResourcePluralPostgres))
}

var _ apis.ResourceInfo = &Postgres{}

func (p Postgres) OffshootName() string {
	return p.Name
}

func (p Postgres) OffshootSelectors() map[string]string {
	return map[string]string{
		meta_util.NameLabelKey:      p.ResourceFQN(),
		meta_util.InstanceLabelKey:  p.Name,
		meta_util.ManagedByLabelKey: kubedb.GroupName,
	}
}

func (p Postgres) OffshootLabels() map[string]string {
	out := p.OffshootSelectors()
	out[meta_util.ComponentLabelKey] = ComponentDatabase
	return meta_util.FilterKeys(kubedb.GroupName, out, p.Labels)
}

func (p Postgres) ResourceFQN() string {
	return fmt.Sprintf("%s.%s", ResourcePluralPostgres, kubedb.GroupName)
}

func (p Postgres) ResourceShortCode() string {
	return ResourceCodePostgres
}

func (p Postgres) ResourceKind() string {
	return ResourceKindPostgres
}

func (p Postgres) ResourceSingular() string {
	return ResourceSingularPostgres
}

func (p Postgres) ResourcePlural() string {
	return ResourcePluralPostgres
}

func (p Postgres) ServiceName() string {
	return p.OffshootName()
}

func (p Postgres) StandbyServiceName() string {
	return meta_util.NameWithPrefix(p.ServiceName(), "standby")
}

func (p Postgres) GoverningServiceName() string {
	return meta_util.NameWithSuffix(p.ServiceName(), "pods")
}

type postgresApp struct {
	*Postgres
}

func (r postgresApp) Name() string {
	return r.Postgres.Name
}

func (r postgresApp) Type() appcat.AppType {
	return appcat.AppType(fmt.Sprintf("%s/%s", kubedb.GroupName, ResourceSingularPostgres))
}

func (p Postgres) AppBindingMeta() appcat.AppBindingMeta {
	return &postgresApp{&p}
}

type postgresStatsService struct {
	*Postgres
}

func (p postgresStatsService) GetNamespace() string {
	return p.Postgres.GetNamespace()
}

func (p postgresStatsService) ServiceName() string {
	return p.OffshootName() + "-stats"
}

func (p postgresStatsService) ServiceMonitorName() string {
	return p.ServiceName()
}

func (p postgresStatsService) ServiceMonitorAdditionalLabels() map[string]string {
	return p.OffshootLabels()
}

func (p postgresStatsService) Path() string {
	return DefaultStatsPath
}

func (p postgresStatsService) Scheme() string {
	return ""
}

func (p Postgres) StatsService() mona.StatsAccessor {
	return &postgresStatsService{&p}
}

func (p Postgres) StatsServiceLabels() map[string]string {
	lbl := meta_util.FilterKeys(kubedb.GroupName, p.OffshootSelectors(), p.Labels)
	lbl[LabelRole] = RoleStats
	return lbl
}

func (p *Postgres) SetDefaults(postgresVersion *catalog.PostgresVersion, topology *core_util.Topology) {
	if p == nil {
		return
	}

	if p.Spec.StorageType == "" {
		p.Spec.StorageType = StorageTypeDurable
	}
	if p.Spec.TerminationPolicy == "" {
		p.Spec.TerminationPolicy = TerminationPolicyDelete
	}

	if p.Spec.LeaderElection == nil {
		p.Spec.LeaderElection = &PostgreLeaderElectionConfig{
			//we have set this default to 33554432. if the difference between primary and replica is more then this,
			//the replica node is going to manually sync itself.
			Period:                   metav1.Duration{Duration: 100 * time.Millisecond},
			MaximumLagBeforeFailover: 32 * 1024 * 1024,
			ElectionTick:             10,
			HeartbeatTick:            1,
		}
	}

	if p.Spec.PodTemplate.Spec.ServiceAccountName == "" {
		p.Spec.PodTemplate.Spec.ServiceAccountName = p.OffshootName()
	}

	if p.Spec.TLS != nil {
		if p.Spec.SSLMode == "" {
			p.Spec.SSLMode = PostgresSSLModeVerifyFull
		}
		if p.Spec.ClientAuthMode == "" {
			p.Spec.ClientAuthMode = ClientAuthModeMD5
		}
	} else {
		if p.Spec.SSLMode == "" {
			p.Spec.SSLMode = PostgresSSLModeDisable
		}
		if p.Spec.ClientAuthMode == "" {
			p.Spec.ClientAuthMode = ClientAuthModeMD5
		}
	}

	if p.Spec.PodTemplate.Spec.ContainerSecurityContext == nil {
		p.Spec.PodTemplate.Spec.ContainerSecurityContext = &core.SecurityContext{
			RunAsUser:  postgresVersion.Spec.SecurityContext.RunAsUser,
			RunAsGroup: postgresVersion.Spec.SecurityContext.RunAsUser,
			Privileged: pointer.BoolP(false),
			Capabilities: &core.Capabilities{
				Add: []core.Capability{"IPC_LOCK", "SYS_RESOURCE"},
			},
		}
	} else {
		if p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser == nil {
			p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser = postgresVersion.Spec.SecurityContext.RunAsUser
		}
		if p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup == nil {
			p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser
		}
	}

	if p.Spec.PodTemplate.Spec.SecurityContext == nil {
		p.Spec.PodTemplate.Spec.SecurityContext = &core.PodSecurityContext{
			RunAsUser:  p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser,
			RunAsGroup: p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup,
		}
	} else {
		if p.Spec.PodTemplate.Spec.SecurityContext.RunAsUser == nil {
			p.Spec.PodTemplate.Spec.SecurityContext.RunAsUser = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser
		}
		if p.Spec.PodTemplate.Spec.SecurityContext.RunAsGroup == nil {
			p.Spec.PodTemplate.Spec.SecurityContext.RunAsGroup = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup
		}
	}
	// Need to set FSGroup equal to  p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup.
	// So that /var/pv directory have the group permission for the RunAsGroup user GID.
	// Otherwise, We will get write permission denied.
	p.Spec.PodTemplate.Spec.SecurityContext.FSGroup = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup

	p.Spec.Monitor.SetDefaults()
	p.SetTLSDefaults()
	SetDefaultResourceLimits(&p.Spec.PodTemplate.Spec.Resources, DefaultResources)
	p.setDefaultAffinity(&p.Spec.PodTemplate, p.OffshootSelectors(), topology)
}

// setDefaultAffinity
func (p *Postgres) setDefaultAffinity(podTemplate *ofst.PodTemplateSpec, labels map[string]string, topology *core_util.Topology) {
	if podTemplate == nil {
		return
	} else if podTemplate.Spec.Affinity != nil {
		// Update topologyKey fields according to Kubernetes version
		topology.ConvertAffinity(podTemplate.Spec.Affinity)
		return
	}

	podTemplate.Spec.Affinity = &core.Affinity{
		PodAntiAffinity: &core.PodAntiAffinity{
			PreferredDuringSchedulingIgnoredDuringExecution: []core.WeightedPodAffinityTerm{
				// Prefer to not schedule multiple pods on the same node
				{
					Weight: 100,
					PodAffinityTerm: core.PodAffinityTerm{
						Namespaces: []string{p.Namespace},
						LabelSelector: &metav1.LabelSelector{
							MatchLabels: labels,
						},
						TopologyKey: core.LabelHostname,
					},
				},
				// Prefer to not schedule multiple pods on the node with same zone
				{
					Weight: 50,
					PodAffinityTerm: core.PodAffinityTerm{
						Namespaces: []string{p.Namespace},
						LabelSelector: &metav1.LabelSelector{
							MatchLabels: labels,
						},
						TopologyKey: topology.LabelZone,
					},
				},
			},
		},
	}
}

func (p *Postgres) SetTLSDefaults() {
	if p.Spec.TLS == nil || p.Spec.TLS.IssuerRef == nil {
		return
	}
	p.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(p.Spec.TLS.Certificates, string(PostgresServerCert), p.CertificateName(PostgresServerCert))
	p.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(p.Spec.TLS.Certificates, string(PostgresClientCert), p.CertificateName(PostgresClientCert))
	p.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(p.Spec.TLS.Certificates, string(PostgresMetricsExporterCert), p.CertificateName(PostgresMetricsExporterCert))
}

func (p *PostgresSpec) GetPersistentSecrets() []string {
	if p == nil {
		return nil
	}

	var secrets []string
	if p.AuthSecret != nil {
		secrets = append(secrets, p.AuthSecret.Name)
	}
	return secrets
}

func (p *Postgres) ReplicasAreReady(lister appslister.StatefulSetLister) (bool, string, error) {
	// Desire number of statefulSets
	expectedItems := 1
	return checkReplicas(lister.StatefulSets(p.Namespace), labels.SelectorFromSet(p.OffshootLabels()), expectedItems)
}

// CertificateName returns the default certificate name and/or certificate secret name for a certificate alias
func (p *Postgres) CertificateName(alias PostgresCertificateAlias) string {
	return meta_util.NameWithSuffix(p.Name, fmt.Sprintf("%s-cert", string(alias)))
}

// GetCertSecretName returns the secret name for a certificate alias if any provide,
// otherwise returns default certificate secret name for the given alias.
func (p *Postgres) GetCertSecretName(alias PostgresCertificateAlias) string {
	if p.Spec.TLS != nil {
		name, ok := kmapi.GetCertificateSecretName(p.Spec.TLS.Certificates, string(alias))
		if ok {
			return name
		}
	}
	return p.CertificateName(alias)
}

// GetSharedBufferSizeForPostgres this func takes a input type int64 which is in bytes
// return the 25% of the input in Bytes, KiloBytes, MegaBytes, GigaBytes, or TeraBytes
func GetSharedBufferSizeForPostgres(resource *resource.Quantity) string {
	// no more than 25% of main memory (RAM)
	minSharedBuffer := int64(128 * 1024 * 1024)
	ret := minSharedBuffer
	if resource != nil {
		ret = (resource.Value() / 100) * 25
	}
	// the shared buffer value can't be less then this
	//128 MB  is the minimum
	if ret < minSharedBuffer {
		ret = minSharedBuffer
	}

	sharedBuffer := ConvertBytesInMB(ret)
	return sharedBuffer
}

func Round(val float64, roundOn float64, places int) (newVal float64) {
	var round float64
	pow := math.Pow(10, float64(places))
	digit := pow * val
	// this func take a float and return the int and fractional part separately
	// math.modf(100.4) will return int part = 100 and fractional part = 0.40000000000000000
	_, div := math.Modf(digit)
	if div >= roundOn {
		round = math.Ceil(digit)
	} else {
		round = math.Floor(digit)
	}
	newVal = round / pow
	return newVal
}

// ConvertBytesInMB this func takes a input type int64 which is in bytes
// return the input in Bytes, KiloBytes, MegaBytes, GigaBytes, or TeraBytes
func ConvertBytesInMB(value int64) string {
	var suffixes [5]string
	suffixes[0] = "B"
	suffixes[1] = "KB"
	suffixes[2] = "MB"
	suffixes[3] = "GB"
	suffixes[4] = "TB"

	// here base is the type we are going to represent the value in string
	// if base is 2 then we will represent the value in MB.
	// if base is 0 then represent the value in B.
	if value == 0 {
		return "0B"
	}
	base := math.Log(float64(value)) / math.Log(1024)
	getSize := Round(math.Pow(1024, base-math.Floor(base)), .5, 2)
	getSuffix := suffixes[int(math.Floor(base))]

	valueMB := strconv.FormatFloat(getSize, 'f', -1, 64) + string(getSuffix)
	return valueMB
}
<commit_msg>Update the default pg-coordinator params (#791)<commit_after>/*
Copyright AppsCode Inc. and Contributors

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 v1alpha2

import (
	"fmt"
	"math"
	"strconv"
	"time"

	"kubedb.dev/apimachinery/apis"
	catalog "kubedb.dev/apimachinery/apis/catalog/v1alpha1"
	"kubedb.dev/apimachinery/apis/kubedb"
	"kubedb.dev/apimachinery/crds"

	"gomodules.xyz/pointer"
	core "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	appslister "k8s.io/client-go/listers/apps/v1"
	kmapi "kmodules.xyz/client-go/api/v1"
	"kmodules.xyz/client-go/apiextensions"
	core_util "kmodules.xyz/client-go/core/v1"
	meta_util "kmodules.xyz/client-go/meta"
	appcat "kmodules.xyz/custom-resources/apis/appcatalog/v1alpha1"
	mona "kmodules.xyz/monitoring-agent-api/api/v1"
	ofst "kmodules.xyz/offshoot-api/api/v1"
)

func (_ Postgres) CustomResourceDefinition() *apiextensions.CustomResourceDefinition {
	return crds.MustCustomResourceDefinition(SchemeGroupVersion.WithResource(ResourcePluralPostgres))
}

var _ apis.ResourceInfo = &Postgres{}

func (p Postgres) OffshootName() string {
	return p.Name
}

func (p Postgres) OffshootSelectors() map[string]string {
	return map[string]string{
		meta_util.NameLabelKey:      p.ResourceFQN(),
		meta_util.InstanceLabelKey:  p.Name,
		meta_util.ManagedByLabelKey: kubedb.GroupName,
	}
}

func (p Postgres) OffshootLabels() map[string]string {
	out := p.OffshootSelectors()
	out[meta_util.ComponentLabelKey] = ComponentDatabase
	return meta_util.FilterKeys(kubedb.GroupName, out, p.Labels)
}

func (p Postgres) ResourceFQN() string {
	return fmt.Sprintf("%s.%s", ResourcePluralPostgres, kubedb.GroupName)
}

func (p Postgres) ResourceShortCode() string {
	return ResourceCodePostgres
}

func (p Postgres) ResourceKind() string {
	return ResourceKindPostgres
}

func (p Postgres) ResourceSingular() string {
	return ResourceSingularPostgres
}

func (p Postgres) ResourcePlural() string {
	return ResourcePluralPostgres
}

func (p Postgres) ServiceName() string {
	return p.OffshootName()
}

func (p Postgres) StandbyServiceName() string {
	return meta_util.NameWithPrefix(p.ServiceName(), "standby")
}

func (p Postgres) GoverningServiceName() string {
	return meta_util.NameWithSuffix(p.ServiceName(), "pods")
}

type postgresApp struct {
	*Postgres
}

func (r postgresApp) Name() string {
	return r.Postgres.Name
}

func (r postgresApp) Type() appcat.AppType {
	return appcat.AppType(fmt.Sprintf("%s/%s", kubedb.GroupName, ResourceSingularPostgres))
}

func (p Postgres) AppBindingMeta() appcat.AppBindingMeta {
	return &postgresApp{&p}
}

type postgresStatsService struct {
	*Postgres
}

func (p postgresStatsService) GetNamespace() string {
	return p.Postgres.GetNamespace()
}

func (p postgresStatsService) ServiceName() string {
	return p.OffshootName() + "-stats"
}

func (p postgresStatsService) ServiceMonitorName() string {
	return p.ServiceName()
}

func (p postgresStatsService) ServiceMonitorAdditionalLabels() map[string]string {
	return p.OffshootLabels()
}

func (p postgresStatsService) Path() string {
	return DefaultStatsPath
}

func (p postgresStatsService) Scheme() string {
	return ""
}

func (p Postgres) StatsService() mona.StatsAccessor {
	return &postgresStatsService{&p}
}

func (p Postgres) StatsServiceLabels() map[string]string {
	lbl := meta_util.FilterKeys(kubedb.GroupName, p.OffshootSelectors(), p.Labels)
	lbl[LabelRole] = RoleStats
	return lbl
}

func (p *Postgres) SetDefaults(postgresVersion *catalog.PostgresVersion, topology *core_util.Topology) {
	if p == nil {
		return
	}

	if p.Spec.StorageType == "" {
		p.Spec.StorageType = StorageTypeDurable
	}
	if p.Spec.TerminationPolicy == "" {
		p.Spec.TerminationPolicy = TerminationPolicyDelete
	}

	if p.Spec.LeaderElection == nil {
		p.Spec.LeaderElection = &PostgreLeaderElectionConfig{
			// The upper limit of election timeout is 50000ms (50s), which should only be used when deploying a
			// globally-distributed etcd cluster. A reasonable round-trip time for the continental United States is around 130-150ms,
			// and the time between US and Japan is around 350-400ms. If the network has uneven performance or regular packet
			// delays/loss then it is possible that a couple of retries may be necessary to successfully send a packet.
			// So 5s is a safe upper limit of global round-trip time. As the election timeout should be an order of magnitude
			// bigger than broadcast time, in the case of ~5s for a globally distributed cluster, then 50 seconds becomes
			// a reasonable maximum.
			Period: metav1.Duration{Duration: 300 * time.Millisecond},
			// the amount of HeartbeatTick can be missed before the failOver
			ElectionTick: 10,
			// this value should be one.
			HeartbeatTick: 1,
			//we have set this default to 33554432. if the difference between primary and replica is more then this,
			//the replica node is going to manually sync itself.
			MaximumLagBeforeFailover: 32 * 1024 * 1024,
		}
	}

	if p.Spec.PodTemplate.Spec.ServiceAccountName == "" {
		p.Spec.PodTemplate.Spec.ServiceAccountName = p.OffshootName()
	}

	if p.Spec.TLS != nil {
		if p.Spec.SSLMode == "" {
			p.Spec.SSLMode = PostgresSSLModeVerifyFull
		}
		if p.Spec.ClientAuthMode == "" {
			p.Spec.ClientAuthMode = ClientAuthModeMD5
		}
	} else {
		if p.Spec.SSLMode == "" {
			p.Spec.SSLMode = PostgresSSLModeDisable
		}
		if p.Spec.ClientAuthMode == "" {
			p.Spec.ClientAuthMode = ClientAuthModeMD5
		}
	}

	if p.Spec.PodTemplate.Spec.ContainerSecurityContext == nil {
		p.Spec.PodTemplate.Spec.ContainerSecurityContext = &core.SecurityContext{
			RunAsUser:  postgresVersion.Spec.SecurityContext.RunAsUser,
			RunAsGroup: postgresVersion.Spec.SecurityContext.RunAsUser,
			Privileged: pointer.BoolP(false),
			Capabilities: &core.Capabilities{
				Add: []core.Capability{"IPC_LOCK", "SYS_RESOURCE"},
			},
		}
	} else {
		if p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser == nil {
			p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser = postgresVersion.Spec.SecurityContext.RunAsUser
		}
		if p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup == nil {
			p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser
		}
	}

	if p.Spec.PodTemplate.Spec.SecurityContext == nil {
		p.Spec.PodTemplate.Spec.SecurityContext = &core.PodSecurityContext{
			RunAsUser:  p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser,
			RunAsGroup: p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup,
		}
	} else {
		if p.Spec.PodTemplate.Spec.SecurityContext.RunAsUser == nil {
			p.Spec.PodTemplate.Spec.SecurityContext.RunAsUser = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser
		}
		if p.Spec.PodTemplate.Spec.SecurityContext.RunAsGroup == nil {
			p.Spec.PodTemplate.Spec.SecurityContext.RunAsGroup = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup
		}
	}
	// Need to set FSGroup equal to  p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup.
	// So that /var/pv directory have the group permission for the RunAsGroup user GID.
	// Otherwise, We will get write permission denied.
	p.Spec.PodTemplate.Spec.SecurityContext.FSGroup = p.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup

	p.Spec.Monitor.SetDefaults()
	p.SetTLSDefaults()
	SetDefaultResourceLimits(&p.Spec.PodTemplate.Spec.Resources, DefaultResources)
	p.setDefaultAffinity(&p.Spec.PodTemplate, p.OffshootSelectors(), topology)
}

// setDefaultAffinity
func (p *Postgres) setDefaultAffinity(podTemplate *ofst.PodTemplateSpec, labels map[string]string, topology *core_util.Topology) {
	if podTemplate == nil {
		return
	} else if podTemplate.Spec.Affinity != nil {
		// Update topologyKey fields according to Kubernetes version
		topology.ConvertAffinity(podTemplate.Spec.Affinity)
		return
	}

	podTemplate.Spec.Affinity = &core.Affinity{
		PodAntiAffinity: &core.PodAntiAffinity{
			PreferredDuringSchedulingIgnoredDuringExecution: []core.WeightedPodAffinityTerm{
				// Prefer to not schedule multiple pods on the same node
				{
					Weight: 100,
					PodAffinityTerm: core.PodAffinityTerm{
						Namespaces: []string{p.Namespace},
						LabelSelector: &metav1.LabelSelector{
							MatchLabels: labels,
						},
						TopologyKey: core.LabelHostname,
					},
				},
				// Prefer to not schedule multiple pods on the node with same zone
				{
					Weight: 50,
					PodAffinityTerm: core.PodAffinityTerm{
						Namespaces: []string{p.Namespace},
						LabelSelector: &metav1.LabelSelector{
							MatchLabels: labels,
						},
						TopologyKey: topology.LabelZone,
					},
				},
			},
		},
	}
}

func (p *Postgres) SetTLSDefaults() {
	if p.Spec.TLS == nil || p.Spec.TLS.IssuerRef == nil {
		return
	}
	p.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(p.Spec.TLS.Certificates, string(PostgresServerCert), p.CertificateName(PostgresServerCert))
	p.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(p.Spec.TLS.Certificates, string(PostgresClientCert), p.CertificateName(PostgresClientCert))
	p.Spec.TLS.Certificates = kmapi.SetMissingSecretNameForCertificate(p.Spec.TLS.Certificates, string(PostgresMetricsExporterCert), p.CertificateName(PostgresMetricsExporterCert))
}

func (p *PostgresSpec) GetPersistentSecrets() []string {
	if p == nil {
		return nil
	}

	var secrets []string
	if p.AuthSecret != nil {
		secrets = append(secrets, p.AuthSecret.Name)
	}
	return secrets
}

func (p *Postgres) ReplicasAreReady(lister appslister.StatefulSetLister) (bool, string, error) {
	// Desire number of statefulSets
	expectedItems := 1
	return checkReplicas(lister.StatefulSets(p.Namespace), labels.SelectorFromSet(p.OffshootLabels()), expectedItems)
}

// CertificateName returns the default certificate name and/or certificate secret name for a certificate alias
func (p *Postgres) CertificateName(alias PostgresCertificateAlias) string {
	return meta_util.NameWithSuffix(p.Name, fmt.Sprintf("%s-cert", string(alias)))
}

// GetCertSecretName returns the secret name for a certificate alias if any provide,
// otherwise returns default certificate secret name for the given alias.
func (p *Postgres) GetCertSecretName(alias PostgresCertificateAlias) string {
	if p.Spec.TLS != nil {
		name, ok := kmapi.GetCertificateSecretName(p.Spec.TLS.Certificates, string(alias))
		if ok {
			return name
		}
	}
	return p.CertificateName(alias)
}

// GetSharedBufferSizeForPostgres this func takes a input type int64 which is in bytes
// return the 25% of the input in Bytes, KiloBytes, MegaBytes, GigaBytes, or TeraBytes
func GetSharedBufferSizeForPostgres(resource *resource.Quantity) string {
	// no more than 25% of main memory (RAM)
	minSharedBuffer := int64(128 * 1024 * 1024)
	ret := minSharedBuffer
	if resource != nil {
		ret = (resource.Value() / 100) * 25
	}
	// the shared buffer value can't be less then this
	//128 MB  is the minimum
	if ret < minSharedBuffer {
		ret = minSharedBuffer
	}

	sharedBuffer := ConvertBytesInMB(ret)
	return sharedBuffer
}

func Round(val float64, roundOn float64, places int) (newVal float64) {
	var round float64
	pow := math.Pow(10, float64(places))
	digit := pow * val
	// this func take a float and return the int and fractional part separately
	// math.modf(100.4) will return int part = 100 and fractional part = 0.40000000000000000
	_, div := math.Modf(digit)
	if div >= roundOn {
		round = math.Ceil(digit)
	} else {
		round = math.Floor(digit)
	}
	newVal = round / pow
	return newVal
}

// ConvertBytesInMB this func takes a input type int64 which is in bytes
// return the input in Bytes, KiloBytes, MegaBytes, GigaBytes, or TeraBytes
func ConvertBytesInMB(value int64) string {
	var suffixes [5]string
	suffixes[0] = "B"
	suffixes[1] = "KB"
	suffixes[2] = "MB"
	suffixes[3] = "GB"
	suffixes[4] = "TB"

	// here base is the type we are going to represent the value in string
	// if base is 2 then we will represent the value in MB.
	// if base is 0 then represent the value in B.
	if value == 0 {
		return "0B"
	}
	base := math.Log(float64(value)) / math.Log(1024)
	getSize := Round(math.Pow(1024, base-math.Floor(base)), .5, 2)
	getSuffix := suffixes[int(math.Floor(base))]

	valueMB := strconv.FormatFloat(getSize, 'f', -1, 64) + string(getSuffix)
	return valueMB
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
)

type textdata struct {
	rawdata []string
	data    []string
}

func (t *textdata) input(f io.Reader) {
	scanner := bufio.NewScanner(f)

	if t.data == nil {
		t.rawdata = make([]string, 0)
	}

	for scanner.Scan() {
		someline := scanner.Text()
		t.rawdata = append(t.rawdata, someline)
	}
}

func (t *textdata) tf(term string, norm bool) float64 {
	return 0.0
}

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func parse(lines []string) <-chan string {
	out := make(chan string, 8*100)

	go func() {
		for _, line := range lines {
			if len(line) > 0 {
				out <- line
			}
		}

		close(out)
	}()

	return out
}

func parselower(in <-chan string) <-chan string {
	out := make(chan string, cap(in))

	go func() {
		for line := range in {
			out <- strings.ToLower(line)
		}
		close(out)
	}()

	return out
}

func parsesplit(in <-chan string) <-chan string {
	out := make(chan string, cap(in))

	go func() {
		for line := range in {
			grams := strings.Split(line, " ")
			var prev string
			for _, gram := range grams {
				if len(gram) > 0 {
					out <- (prev + gram)
				}
				prev = gram
			}
		}
		close(out)
	}()

	return out
}

func resulter(c map[string]int, in <-chan string) {
	for gram := range in {
		c[gram] += 1
	}
}

func main() {
	t := new(textdata)

	t.input(os.Stdin)

	counts := make(map[string]int)

	parser := parse(t.rawdata)
	parselower := parselower(parser)
	parsespliter := parsesplit(parselower)
	resulter(counts, parsespliter)

	fmt.Println(counts)
}
<commit_msg>teaking with lexd<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
)

type textdata struct {
	rawdata []string
	data    []string
}

func (t *textdata) input(f io.Reader) {
	scanner := bufio.NewScanner(f)

	if t.data == nil {
		t.rawdata = make([]string, 0)
	}

	for scanner.Scan() {
		someline := scanner.Text()
		t.rawdata = append(t.rawdata, someline)
	}
}

func (t *textdata) tf(term string, norm bool) float64 {
	return 0.0
}

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func parse(lines []string) <-chan string {
	out := make(chan string, 8*100)

	go func() {
		for _, line := range lines {
			if len(line) > 0 {
				out <- line
			}
		}

		close(out)
	}()

	return out
}

func parselower(in <-chan string) <-chan string {
	out := make(chan string, cap(in))

	go func() {
		for line := range in {
			out <- strings.ToLower(line)
		}
		close(out)
	}()

	return out
}

func parsesplit(in <-chan string) <-chan string {
	out := make(chan string, cap(in))

	go func() {
		for line := range in {
			grams := strings.Split(line, " ")
			var prev string
			for _, gram := range grams {
				if len(gram) > 0 {
					out <- (prev + gram)
				}
				prev = gram
			}
		}
		close(out)
	}()

	return out
}

func resulter(c map[string]int, in <-chan string) int {
	var total int

	for gram := range in {
		total += 1
		c[gram] += 1
	}

	return total
}

func lexd(total, unique int) int {
	return int(float64(unique) / float64(total) * 100)
}

func main() {
	t := new(textdata)

	t.input(os.Stdin)

	counts := make(map[string]int)

	parser := parse(t.rawdata)
	parselower := parselower(parser)
	parsespliter := parsesplit(parselower)
	total := resulter(counts, parsespliter)

	fmt.Println(lexd(total, len(counts)))
}
<|endoftext|>