<commit_before>package libcoap

/*
#cgo LDFLAGS: -lcoap-3-openssl
#include <coap3/coap.h>
#include "callback.h"
*/
import "C"
import "errors"
import "unsafe"
import "strings"
import log "github.com/sirupsen/logrus"
import cache "github.com/patrickmn/go-cache"

// across invocations, sessions are not 'eq'
type MethodHandler func(*Context, *Resource, *Session, *Pdu, *[]byte, *string, *Pdu)

type EventHandler func(*Session, Event)

type EndPoint struct {
    ptr *C.coap_endpoint_t
}

type Event int
const (
    EventSessionDisconnected Event = C.COAP_EVENT_DTLS_CLOSED
    EventSessionConnected    Event = C.COAP_EVENT_DTLS_CONNECTED
    EventSessionRenegotiate  Event = C.COAP_EVENT_DTLS_RENEGOTIATE
    EventSessionError        Event = C.COAP_EVENT_DTLS_ERROR
)

func (context *Context) ContextSetPSK(identity string, key []byte) {
    cid := C.CString(identity)
    defer C.free(unsafe.Pointer(cid))

    C.coap_context_set_psk(context.ptr,
                           cid,
                           (*C.uint8_t)(&key[0]),
                           C.size_t(len(key)))
}

//export export_method_handler
func export_method_handler(rsrc  *C.coap_resource_t,
                           sess  *C.coap_session_t,
                           req   *C.coap_pdu_t,
                           query *C.coap_string_t,
                           resp  *C.coap_pdu_t) {
    ctx := C.coap_session_get_context(sess)
    if ctx == nil {
        return
    }
    context, ok := contexts[ctx]
    if !ok {
        return
    }
    resource, ok := resources[rsrc]
    if !ok {
        return
    }
    blockSize := resource.GetBlockSize()
    isQBlock2 := resource.IsQBlock2()

    // Handle observe :
    // In case of observation response (or notification), original 'request' from libcoap is NULL
    // In order to handle request with handleGet(), it is necessary to re-create equest
    // First, initialize request from response to re-use some data.
    is_observe := false
    if resource.IsNotification() {
        is_observe = true
        resource.SetIsNotification(false)
    }
    tok := C.coap_get_token_from_request_pdu(req)

    session, ok := sessions[sess]
    if !ok {
		return
    }

    request, err := req.toGo()
    if err != nil {
        return
    }

    // Handle observe:
    // Set request.uri-path from resource.uri-path (so that it can by-pass uri-path check inside PrefixFilter)
    var uri []string
    uri_path := resource.UriPath()
    hb_uri_path := request.PathString()
    if strings.Contains(hb_uri_path, "/hb") {
        uri_path = hb_uri_path
    }
    if is_observe {
        uriFilterList := GetUriFilterByKey(uri_path)
        for _, uriFilter := range uriFilterList {
            uriQuery := uriFilter
            uriFilterSplit := strings.Split(uriFilter, "?")
            if len(uriFilterSplit) > 1 {
                uriQuery = uriFilterSplit[0]
            }
            resourceTmp := context.GetResourceByQuery(&uriQuery)
            if resourceTmp != nil && resource.IsObserved() {
                if !strings.Contains(uri_path, "/mid") && !strings.Contains(uri_path, "/tmid") {
                    resourceTmp.SetIsObserved(false)
                }
                resource = resourceTmp
                uri_path = uriFilter
                break
            }
        }
        request.Code = RequestGet
        request.Options = make([]Option, 0)
        tmpUri := strings.Split(uri_path, "?")
        // Set uri-query and uri-path for handle observe
        if len(tmpUri) > 1 {
            uri = strings.Split(tmpUri[0], "/")
            queries := strings.Split(tmpUri[1], "&")
            uri = append(uri, queries...)
        } else {
            uri = strings.Split(uri_path, "/")
        }
        request.SetPath(uri)
        // If request is observe and resource contains block 2 option, set block 2 for request
        if blockSize != nil {
            block := &Block{}
            block.NUM = 0
            block.M   = 0
            block.SZX = *blockSize
            if isQBlock2 {
                request.SetOption(OptionQBlock2, uint32(block.ToInt()))
            } else {
                request.SetOption(OptionBlock2, uint32(block.ToInt()))
            }
            request.fillC(req)
        }
        session.SetIsNotification(true)
        log.WithField("Request:", request).Debug("Re-create request for handling obervation\n")
    }

    id := ""
    resourceOneUriPaths := strings.Split(uri_path, "/mid=")
    if len (resourceOneUriPaths) <= 1 {
        resourceOneUriPaths = strings.Split(uri_path, "/tmid=")
    }
    if len(resourceOneUriPaths) > 1 {
        id = resourceOneUriPaths[1]
    }
    token := tok.toBytes()
    queryString := query.toString()
    if !is_observe && queryString != nil {
        queryStr := "?" + *queryString
        id += queryStr
    }

    handler, ok := resource.handlers[request.Code]
    if ok {
        itemKey := uri_path
        response := Pdu{}
        res, isFound := caches.Get(itemKey)

        // If data does not exist in cache, add data to cache. Else get data from cache for response body
        if !isFound {
            SetBlockOptionFirstRequest(request)
            handler(context, resource, session, request, token, queryString, &response)
        } else {
            response = res.(Pdu)
            response.MessageID = request.MessageID
            response.Token = request.Token
        }
        if is_observe {
            response.SetPath(uri)
            resource.IncreaseObserveNumber()
            response.SetOption(OptionObserve, uint32(resource.GetObserveNumber()))
        } else {
            response.SetPath(strings.Split(uri_path, "/"))
        }
        response.fillC(resp)
        if request.Code == RequestGet && response.Code == ResponseContent {
            // handle max-age option
            maxAge, err := response.GetOptionIntegerValue(OptionMaxage)
            if err != nil || maxAge < 0 {
                maxAge = -1
            }
            response.RemoveOption(OptionMaxage)
            qBlock2, _ := request.GetOptionIntegerValue(OptionQBlock2)
            if qBlock2 >= 0 {
                C.coap_add_data_large_response(resource.ptr, session.ptr, req, resp, query, C.COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, C.int(0),
                                            C.uint64_t(0), C.size_t(len(response.Data)), (*C.uint8_t)(unsafe.Pointer(&response.Data[0])), nil, nil)
            } else {
                C.coap_add_data_blocked_response(req, resp, C.uint16_t(C.COAP_MEDIATYPE_APPLICATION_DOTS_CBOR), C.int(maxAge),
                                            C.size_t(len(response.Data)), (*C.uint8_t)(unsafe.Pointer(&response.Data[0])))
            }
            resPdu,_ := resp.toGo()
            HandleCache(resPdu, response, resource, context, itemKey)
        }
    }
}

// Create Event type from coap_event_t
func newEvent (ev C.coap_event_t) Event {
    switch ev {
    case C.COAP_EVENT_DTLS_CLOSED:      return EventSessionDisconnected
    case C.COAP_EVENT_DTLS_CONNECTED:   return EventSessionConnected
    case C.COAP_EVENT_DTLS_RENEGOTIATE: return EventSessionRenegotiate
    case C.COAP_EVENT_DTLS_ERROR:       return EventSessionError
    default: return -1
    }
}

//export export_event_handler
func export_event_handler(sess *C.coap_session_t, event C.coap_event_t) {
    ctx := C.coap_session_get_context(sess)
    if ctx == nil {
        return
    }
    context, ok := contexts[ctx]
	if !ok {
		return
    }

    session, ok := sessions[sess]
    if !ok {
        session = &Session{ sess, &SessionConfig{false, false, false, false, false, false, false, 0, 0 } }
    }

    // Run event handler when session is connected or disconnected
	if context.eventHandler != nil {
		context.eventHandler(session, newEvent(event))
	}
}

func (resource *Resource) RegisterHandler(method Code, handler MethodHandler) {
    resource.handlers[method] = handler
    C.coap_register_handler(resource.ptr, C.coap_request_t(method), C.coap_method_handler_t(C.method_handler))
}

// Register event handler to libcoap
func (context *Context) RegisterEventHandler(handler EventHandler) {
	context.eventHandler = handler
	C.coap_register_event_handler(context.ptr, C.coap_event_handler_t(C.event_handler))
}

func (context *Context) NewEndpoint(address Address, proto Proto) *EndPoint {
    ptr := C.coap_new_endpoint(context.ptr, &address.value, C.coap_proto_t(proto))
    if ptr == nil {
        return nil
    } else {
        return &EndPoint{ ptr }
    }
}

func (session *Session) DtlsGetPeerCommonName() (_ string, err error) {
    buf := make([]byte, 1024)
    n := C.coap_dtls_get_peer_common_name(session.ptr, (*C.char)(unsafe.Pointer(&buf[0])), 1024)
    if n < 0 {
        err = errors.New("could not get peer common name")
        return
    }
    return string(buf[:n]), nil
}

/*
 * Set block option with Num = 0 for first request
 */
func SetBlockOptionFirstRequest(request *Pdu) {
    blockValue,_ := request.GetOptionIntegerValue(OptionBlock2)
    block := IntToBlock(blockValue)
    if block != nil {
        block.NUM = 0
        request.SetOption(OptionBlock2, uint32(block.ToInt()))
    }
}

/*
 * Handle delete item if block is last block
 * Handle add item if item does not exist in cache
 */
func HandleCache(resp *Pdu, response Pdu, resource *Resource, context *Context, keyItem string) error {
    blockValue,_ := resp.GetOptionIntegerValue(OptionBlock2)
    block := IntToBlock(int(blockValue))
    // Delete block in cache when block is last block
    // Set isBlockwiseInProgress = false as one of conditions to remove resource if it expired
    if block != nil && block.NUM > 0 && block.M == LAST_BLOCK {
        log.Debugf("Delete item cache with key = %+v", keyItem)
        caches.Delete(keyItem)
        resource.isBlockwiseInProgress = false
    }

    // Add item with key if it does not exists
    // Set isBlockwiseInProgress = true to not remove resource in case it expired because block-wise transfer is in progress
    if block != nil && block.NUM == 0 && block.M == MORE_BLOCK {
        log.Debug("Create item cache with key = ", keyItem)
        caches.Set(keyItem, response, cache.DefaultExpiration)
        resource.isBlockwiseInProgress = true
    }
    return nil
}<commit_msg>Issue #358: Fix maxAge in response data<commit_after>package libcoap

/*
#cgo LDFLAGS: -lcoap-3-openssl
#include <coap3/coap.h>
#include "callback.h"
*/
import "C"
import "errors"
import "unsafe"
import "strings"
import log "github.com/sirupsen/logrus"
import cache "github.com/patrickmn/go-cache"

// across invocations, sessions are not 'eq'
type MethodHandler func(*Context, *Resource, *Session, *Pdu, *[]byte, *string, *Pdu)

type EventHandler func(*Session, Event)

type EndPoint struct {
    ptr *C.coap_endpoint_t
}

type Event int
const (
    EventSessionDisconnected Event = C.COAP_EVENT_DTLS_CLOSED
    EventSessionConnected    Event = C.COAP_EVENT_DTLS_CONNECTED
    EventSessionRenegotiate  Event = C.COAP_EVENT_DTLS_RENEGOTIATE
    EventSessionError        Event = C.COAP_EVENT_DTLS_ERROR
)

func (context *Context) ContextSetPSK(identity string, key []byte) {
    cid := C.CString(identity)
    defer C.free(unsafe.Pointer(cid))

    C.coap_context_set_psk(context.ptr,
                           cid,
                           (*C.uint8_t)(&key[0]),
                           C.size_t(len(key)))
}

//export export_method_handler
func export_method_handler(rsrc  *C.coap_resource_t,
                           sess  *C.coap_session_t,
                           req   *C.coap_pdu_t,
                           query *C.coap_string_t,
                           resp  *C.coap_pdu_t) {
    ctx := C.coap_session_get_context(sess)
    if ctx == nil {
        return
    }
    context, ok := contexts[ctx]
    if !ok {
        return
    }
    resource, ok := resources[rsrc]
    if !ok {
        return
    }
    blockSize := resource.GetBlockSize()
    isQBlock2 := resource.IsQBlock2()

    // Handle observe :
    // In case of observation response (or notification), original 'request' from libcoap is NULL
    // In order to handle request with handleGet(), it is necessary to re-create equest
    // First, initialize request from response to re-use some data.
    is_observe := false
    if resource.IsNotification() {
        is_observe = true
        resource.SetIsNotification(false)
    }
    tok := C.coap_get_token_from_request_pdu(req)

    session, ok := sessions[sess]
    if !ok {
		return
    }

    request, err := req.toGo()
    if err != nil {
        return
    }

    // Handle observe:
    // Set request.uri-path from resource.uri-path (so that it can by-pass uri-path check inside PrefixFilter)
    var uri []string
    uri_path := resource.UriPath()
    hb_uri_path := request.PathString()
    if strings.Contains(hb_uri_path, "/hb") {
        uri_path = hb_uri_path
    }
    if is_observe {
        uriFilterList := GetUriFilterByKey(uri_path)
        for _, uriFilter := range uriFilterList {
            uriQuery := uriFilter
            uriFilterSplit := strings.Split(uriFilter, "?")
            if len(uriFilterSplit) > 1 {
                uriQuery = uriFilterSplit[0]
            }
            resourceTmp := context.GetResourceByQuery(&uriQuery)
            if resourceTmp != nil && resource.IsObserved() {
                if !strings.Contains(uri_path, "/mid") && !strings.Contains(uri_path, "/tmid") {
                    resourceTmp.SetIsObserved(false)
                }
                resource = resourceTmp
                uri_path = uriFilter
                break
            }
        }
        request.Code = RequestGet
        request.Options = make([]Option, 0)
        tmpUri := strings.Split(uri_path, "?")
        // Set uri-query and uri-path for handle observe
        if len(tmpUri) > 1 {
            uri = strings.Split(tmpUri[0], "/")
            queries := strings.Split(tmpUri[1], "&")
            uri = append(uri, queries...)
        } else {
            uri = strings.Split(uri_path, "/")
        }
        request.SetPath(uri)
        // If request is observe and resource contains block 2 option, set block 2 for request
        if blockSize != nil {
            block := &Block{}
            block.NUM = 0
            block.M   = 0
            block.SZX = *blockSize
            if isQBlock2 {
                request.SetOption(OptionQBlock2, uint32(block.ToInt()))
            } else {
                request.SetOption(OptionBlock2, uint32(block.ToInt()))
            }
            request.fillC(req)
        }
        session.SetIsNotification(true)
        log.WithField("Request:", request).Debug("Re-create request for handling obervation\n")
    }

    id := ""
    resourceOneUriPaths := strings.Split(uri_path, "/mid=")
    if len (resourceOneUriPaths) <= 1 {
        resourceOneUriPaths = strings.Split(uri_path, "/tmid=")
    }
    if len(resourceOneUriPaths) > 1 {
        id = resourceOneUriPaths[1]
    }
    token := tok.toBytes()
    queryString := query.toString()
    if !is_observe && queryString != nil {
        queryStr := "?" + *queryString
        id += queryStr
    }

    handler, ok := resource.handlers[request.Code]
    if ok {
        itemKey := uri_path
        response := Pdu{}
        res, isFound := caches.Get(itemKey)

        // If data does not exist in cache, add data to cache. Else get data from cache for response body
        if !isFound {
            SetBlockOptionFirstRequest(request)
            handler(context, resource, session, request, token, queryString, &response)
        } else {
            response = res.(Pdu)
            response.MessageID = request.MessageID
            response.Token = request.Token
        }
        if is_observe {
            response.SetPath(uri)
            resource.IncreaseObserveNumber()
            response.SetOption(OptionObserve, uint32(resource.GetObserveNumber()))
        } else {
            response.SetPath(strings.Split(uri_path, "/"))
        }
        response.fillC(resp)
        if request.Code == RequestGet && response.Code == ResponseContent {
            // handle max-age option
            maxAge, err := response.GetOptionIntegerValue(OptionMaxage)
            if err != nil || maxAge < 0 {
                maxAge = -1
            }
            response.RemoveOption(OptionMaxage)
            qBlock2, _ := request.GetOptionIntegerValue(OptionQBlock2)
            if qBlock2 >= 0 {
                C.coap_add_data_large_response(resource.ptr, session.ptr, req, resp, query, C.COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, C.int(maxAge),
                                            C.uint64_t(0), C.size_t(len(response.Data)), (*C.uint8_t)(unsafe.Pointer(&response.Data[0])), nil, nil)
            } else {
                C.coap_add_data_blocked_response(req, resp, C.uint16_t(C.COAP_MEDIATYPE_APPLICATION_DOTS_CBOR), C.int(maxAge),
                                            C.size_t(len(response.Data)), (*C.uint8_t)(unsafe.Pointer(&response.Data[0])))
            }
            resPdu,_ := resp.toGo()
            HandleCache(resPdu, response, resource, context, itemKey)
        }
    }
}

// Create Event type from coap_event_t
func newEvent (ev C.coap_event_t) Event {
    switch ev {
    case C.COAP_EVENT_DTLS_CLOSED:      return EventSessionDisconnected
    case C.COAP_EVENT_DTLS_CONNECTED:   return EventSessionConnected
    case C.COAP_EVENT_DTLS_RENEGOTIATE: return EventSessionRenegotiate
    case C.COAP_EVENT_DTLS_ERROR:       return EventSessionError
    default: return -1
    }
}

//export export_event_handler
func export_event_handler(sess *C.coap_session_t, event C.coap_event_t) {
    ctx := C.coap_session_get_context(sess)
    if ctx == nil {
        return
    }
    context, ok := contexts[ctx]
	if !ok {
		return
    }

    session, ok := sessions[sess]
    if !ok {
        session = &Session{ sess, &SessionConfig{false, false, false, false, false, false, false, 0, 0 } }
    }

    // Run event handler when session is connected or disconnected
	if context.eventHandler != nil {
		context.eventHandler(session, newEvent(event))
	}
}

func (resource *Resource) RegisterHandler(method Code, handler MethodHandler) {
    resource.handlers[method] = handler
    C.coap_register_handler(resource.ptr, C.coap_request_t(method), C.coap_method_handler_t(C.method_handler))
}

// Register event handler to libcoap
func (context *Context) RegisterEventHandler(handler EventHandler) {
	context.eventHandler = handler
	C.coap_register_event_handler(context.ptr, C.coap_event_handler_t(C.event_handler))
}

func (context *Context) NewEndpoint(address Address, proto Proto) *EndPoint {
    ptr := C.coap_new_endpoint(context.ptr, &address.value, C.coap_proto_t(proto))
    if ptr == nil {
        return nil
    } else {
        return &EndPoint{ ptr }
    }
}

func (session *Session) DtlsGetPeerCommonName() (_ string, err error) {
    buf := make([]byte, 1024)
    n := C.coap_dtls_get_peer_common_name(session.ptr, (*C.char)(unsafe.Pointer(&buf[0])), 1024)
    if n < 0 {
        err = errors.New("could not get peer common name")
        return
    }
    return string(buf[:n]), nil
}

/*
 * Set block option with Num = 0 for first request
 */
func SetBlockOptionFirstRequest(request *Pdu) {
    blockValue,_ := request.GetOptionIntegerValue(OptionBlock2)
    block := IntToBlock(blockValue)
    if block != nil {
        block.NUM = 0
        request.SetOption(OptionBlock2, uint32(block.ToInt()))
    }
}

/*
 * Handle delete item if block is last block
 * Handle add item if item does not exist in cache
 */
func HandleCache(resp *Pdu, response Pdu, resource *Resource, context *Context, keyItem string) error {
    blockValue,_ := resp.GetOptionIntegerValue(OptionBlock2)
    block := IntToBlock(int(blockValue))
    // Delete block in cache when block is last block
    // Set isBlockwiseInProgress = false as one of conditions to remove resource if it expired
    if block != nil && block.NUM > 0 && block.M == LAST_BLOCK {
        log.Debugf("Delete item cache with key = %+v", keyItem)
        caches.Delete(keyItem)
        resource.isBlockwiseInProgress = false
    }

    // Add item with key if it does not exists
    // Set isBlockwiseInProgress = true to not remove resource in case it expired because block-wise transfer is in progress
    if block != nil && block.NUM == 0 && block.M == MORE_BLOCK {
        log.Debug("Create item cache with key = ", keyItem)
        caches.Set(keyItem, response, cache.DefaultExpiration)
        resource.isBlockwiseInProgress = true
    }
    return nil
}<|endoftext|>


<commit_before>// Package passwordhash implements safe password hashing and comparison.
//
// Passwords are derived using PBKDF2 function with 5000 iterations (by default),
// with 32-byte salt and 64-byte output.
package passwordhash

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/subtle"
	"fmt"
	"github.com/dchest/pbkdf2"
)

// PasswordHash represents storage for password hash and salt.
type PasswordHash struct {
	Iterations int
	Salt       []byte
	Hash       []byte
}

const (
	// Default number of iterations for PBKDF2.
	DefaultIterations = 5000
	// Default salt length.
	SaltLen = 32
)

// getSalt returns a new random salt.
func getSalt() []byte {
	salt := make([]byte, SaltLen)
	if _, err := rand.Reader.Read(salt); err != nil {
		panic("can't read from random source: " + err.String())
	}
	return salt
}

// New returns a new password hash derived from the provided password,
// a random salt, and the default number of iterations.
func New(password string) *PasswordHash {
	return NewWithSaltIterations(password, getSalt(), DefaultIterations)
}

// NewWithIterations returns a new password hash derived from the provided
// password, number of iterations, and a random salt.
func NewWithIterations(password string, iterations int) *PasswordHash {
	return NewWithSaltIterations(password, getSalt(), iterations)
}

// NewWithSaltIterations creates a new password hash from the provided password, salt,
// and the number of iterations.
func NewWithSaltIterations(password string, salt []byte, iterations int) *PasswordHash {
	return &PasswordHash{iterations, salt,
		pbkdf2.PBKDF2([]byte(password), salt, iterations, sha256.New, 64)}
}

// EqualToPassword returns true if the password hash was derived from the provided password.
// This function uses constant time comparison.
func (ph *PasswordHash) EqualToPassword(password string) bool {
	provided := NewWithSaltIterations(password, ph.Salt, ph.Iterations)
	return subtle.ConstantTimeCompare(ph.Hash, provided.Hash) == 1
}

// String returns a string representation of the password hash.
func (ph *PasswordHash) String() string {
	return fmt.Sprintf("&PasswordHash{Iterations: %d, Salt: %x, Hash: %x}",
		ph.Iterations, ph.Salt, ph.Hash)
}
<commit_msg>Document use of SHA256.<commit_after>// Package passwordhash implements safe password hashing and comparison.
//
// Passwords are derived using PBKDF2-SHA256 function with 5000 iterations (by default),
// with 32-byte salt and 64-byte output.
package passwordhash

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/subtle"
	"fmt"
	"github.com/dchest/pbkdf2"
)

// PasswordHash represents storage for password hash and salt.
type PasswordHash struct {
	Iterations int
	Salt       []byte
	Hash       []byte
}

const (
	// Default number of iterations for PBKDF2.
	DefaultIterations = 5000
	// Default salt length.
	SaltLen = 32
)

// getSalt returns a new random salt.
func getSalt() []byte {
	salt := make([]byte, SaltLen)
	if _, err := rand.Reader.Read(salt); err != nil {
		panic("can't read from random source: " + err.String())
	}
	return salt
}

// New returns a new password hash derived from the provided password,
// a random salt, and the default number of iterations.
func New(password string) *PasswordHash {
	return NewWithSaltIterations(password, getSalt(), DefaultIterations)
}

// NewWithIterations returns a new password hash derived from the provided
// password, number of iterations, and a random salt.
func NewWithIterations(password string, iterations int) *PasswordHash {
	return NewWithSaltIterations(password, getSalt(), iterations)
}

// NewWithSaltIterations creates a new password hash from the provided password, salt,
// and the number of iterations.
func NewWithSaltIterations(password string, salt []byte, iterations int) *PasswordHash {
	return &PasswordHash{iterations, salt,
		pbkdf2.PBKDF2([]byte(password), salt, iterations, sha256.New, 64)}
}

// EqualToPassword returns true if the password hash was derived from the provided password.
// This function uses constant time comparison.
func (ph *PasswordHash) EqualToPassword(password string) bool {
	provided := NewWithSaltIterations(password, ph.Salt, ph.Iterations)
	return subtle.ConstantTimeCompare(ph.Hash, provided.Hash) == 1
}

// String returns a string representation of the password hash.
func (ph *PasswordHash) String() string {
	return fmt.Sprintf("&PasswordHash{Iterations: %d, Salt: %x, Hash: %x}",
		ph.Iterations, ph.Salt, ph.Hash)
}
<|endoftext|>


<commit_before>package oauth

import (
	"http"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

type Mocks struct {
	httpClient     *MockHttpClient
	clock          *MockClock
	nonceGenerator *MockNonceGenerator
	signer         *MockSigner
}

func newMocks(t *testing.T) *Mocks {
	return &Mocks{
		httpClient:     NewMockHttpClient(t),
		clock:          &MockClock{Time: 1},
		nonceGenerator: &MockNonceGenerator{Nonce: 2},
		signer:         &MockSigner{},
	}
}

func (m *Mocks) install(c *Consumer) {
	c.httpClient = m.httpClient
	c.clock = m.clock
	c.nonceGenerator = m.nonceGenerator
	c.signer = m.signer
}

func TestSuccessfulTokenRequest(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/requesttoken",
		map[string]string{
			"oauth_callback":         http.URLEscape("http://www.mrjon.es/callback"),
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_version":          "1.0",
		},
		"oauth_token=TOKEN&oauth_token_secret=SECRET")

	token, url, err := c.GetRequestTokenAndUrl()
	if err != nil {
		t.Fatal(err)
	}

	assertEq(t, "TOKEN", token.Token)
	assertEq(t, "SECRET", token.Secret)
	assertEq(t, "consumersecret&", m.signer.UsedKey)
	assertEq(t, "http://www.mrjon.es/authorizetoken?oauth_token=TOKEN", url)
}

func TestSuccessfulTokenAuthorization(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/accesstoken",
		map[string]string{
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_token":            "RTOKEN",
			"oauth_verifier":         "VERIFICATION_CODE",
			"oauth_version":          "1.0",
		},
		"oauth_token=ATOKEN&oauth_token_secret=ATOKEN_SECRET")

  rtoken := &RequestToken{Token: "RTOKEN", Secret: "RSECRET"}
	atoken, err := c.AuthorizeToken(rtoken, "VERIFICATION_CODE")
	if err != nil {
		t.Fatal(err)
	}

	assertEq(t, "ATOKEN", atoken.Token)
	assertEq(t, "ATOKEN_SECRET", atoken.Secret)
	assertEq(t, "consumersecret&RSECRET", m.signer.UsedKey)
}

func TestSuccessfulAuthorizedGet(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/someurl?key=val",
		map[string]string{
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_token":            "TOKEN",
			"oauth_version":          "1.0",
		},
		"BODY:SUCCESS")

  token := &AccessToken{Token: "TOKEN", Secret: "SECRET"}

	resp, err := c.Get(
		"http://www.mrjon.es/someurl", map[string]string{"key": "val"}, token)

	if err != nil {
		t.Fatal(err)
	}

	assertEq(t, "consumersecret&SECRET", m.signer.UsedKey)

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assertEq(t, "BODY:SUCCESS", string(body))
}

func Test404OnTokenRequest(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ReturnStatusCode(404, "Not Found")

	_, _, err := c.GetRequestTokenAndUrl()
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func Test404OnAuthorizationRequest(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ReturnStatusCode(404, "Not Found")

  rtoken := &RequestToken{Token: "RTOKEN", Secret: "RSECRET"}
	_, err := c.AuthorizeToken(rtoken, "VERIFICATION_CODE")
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func Test404OnGet(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ReturnStatusCode(404, "Not Found")

  atoken := &AccessToken{Token: "ATOKEN", Secret: "ASECRET"}
	_, err := c.Get("URL", map[string]string{}, atoken)
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func basicConsumer() *Consumer {
	return &Consumer{
		ConsumerKey:       "consumerkey",
		ConsumerSecret:    "consumersecret",
		RequestTokenUrl:   "http://www.mrjon.es/requesttoken",
		AuthorizeTokenUrl: "http://www.mrjon.es/authorizetoken",
		AccessTokenUrl:    "http://www.mrjon.es/accesstoken",
		CallbackUrl:       "http://www.mrjon.es/callback",
	}
}

func assertEq(t *testing.T, expected interface{}, actual interface{}) {
	assertEqM(t, expected, actual, "")
}

func assertEqM(t *testing.T, expected interface{}, actual interface{}, msg string) {
	if expected != actual {
		t.Fatalf("Assertion error.\n\tExpected: '%s'\n\tActual:   '%s'\n\tMessage:  '%s'",
			expected, actual, msg)
	}
}

type MockHttpClient struct {
	url          string
	oAuthChecker *OAuthChecker
	responseBody string
	statusCode   int

	t *testing.T
}

func NewMockHttpClient(t *testing.T) *MockHttpClient {
	return &MockHttpClient{t: t, statusCode: 200}
}

func (mock *MockHttpClient) Do(req *http.Request) (*http.Response, os.Error) {
	if mock.url != "" && req.URL.String() != mock.url {
		mock.t.Fatalf("URLs did not match.\nExpected: '%s'\nActual: '%s'",
			mock.url, req.URL.String())
	}
	if mock.oAuthChecker != nil {
		if req.Header == nil {
			mock.t.Fatal("Missing 'Authorization' header.")
		}
		mock.oAuthChecker.CheckHeader(req.Header.Get("Authorization"))
	}

	return &http.Response{
		StatusCode: mock.statusCode,
		Body:       NewMockBody(mock.responseBody),
	},
		nil
}

func (mock *MockHttpClient) ExpectGet(
	  expectedUrl string, expectedOAuthPairs map[string]string, responseBody string) {
	mock.url = expectedUrl
	mock.oAuthChecker = NewOAuthChecker(mock.t, expectedOAuthPairs)
	mock.responseBody = responseBody
}

func (mock *MockHttpClient) ReturnStatusCode(statusCode int, body string) {
	mock.statusCode = statusCode
	mock.responseBody = body
}

type OAuthChecker struct {
	headerPairs map[string]string
	t           *testing.T
}

func NewOAuthChecker(t *testing.T, headerPairs map[string]string) *OAuthChecker {
	return &OAuthChecker{
		headerPairs: headerPairs,
		t:           t,
	}
}

func (o *OAuthChecker) CheckHeader(header string) {
	assertEqM(o.t, "OAuth ", header[0:6], "OAuth Header did not begin correctly.")
	paramsStr := header[6:]
	params := strings.Split(paramsStr, "\n    ", -1)
	paramMap := make(map[string]string)
	for _, param := range params {
		keyvalue := strings.Split(param, "=", -1)
		// line looks like: key="value", strip off the quotes
		// TODO(mrjones): this is pretty hacky
		value := keyvalue[1]
		if strings.HasSuffix(value, ",") {
			value = value[0 : len(value)-1]
		}
		value = value[1 : len(value)-1]
		paramMap[keyvalue[0]] = value
	}
	for key, value := range o.headerPairs {
		assertEqM(o.t, value, paramMap[key], "For OAuth parameter "+key)
	}
}

type MockBody struct {
	reader io.Reader
}

func NewMockBody(body string) *MockBody {
	return &MockBody{
		reader: strings.NewReader(body),
	}
}

func (*MockBody) Close() os.Error {
	return nil
}

func (mock *MockBody) Read(p []byte) (n int, err os.Error) {
	return mock.reader.Read(p)
}

type MockClock struct {
	Time int64
}

func (m *MockClock) Seconds() int64 {
	return m.Time
}

type MockNonceGenerator struct {
	Nonce int64
}

func (m *MockNonceGenerator) Int63() int64 {
	return m.Nonce
}

type MockSigner struct {
	UsedKey      string
	SignedString string
}

func (m *MockSigner) Sign(message string, key string) string {
	m.UsedKey = key
	m.SignedString = message
	return "MOCK_SIGNATURE"
}
<commit_msg>more tests<commit_after>package oauth

import (
	"http"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

type Mocks struct {
	httpClient     *MockHttpClient
	clock          *MockClock
	nonceGenerator *MockNonceGenerator
	signer         *MockSigner
}

func newMocks(t *testing.T) *Mocks {
	return &Mocks{
		httpClient:     NewMockHttpClient(t),
		clock:          &MockClock{Time: 1},
		nonceGenerator: &MockNonceGenerator{Nonce: 2},
		signer:         &MockSigner{},
	}
}

func (m *Mocks) install(c *Consumer) {
	c.httpClient = m.httpClient
	c.clock = m.clock
	c.nonceGenerator = m.nonceGenerator
	c.signer = m.signer
}

func TestSuccessfulTokenRequest(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/requesttoken",
		map[string]string{
			"oauth_callback":         http.URLEscape("http://www.mrjon.es/callback"),
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_version":          "1.0",
		},
		"oauth_token=TOKEN&oauth_token_secret=SECRET")

	token, url, err := c.GetRequestTokenAndUrl()
	if err != nil {
		t.Fatal(err)
	}

	assertEq(t, "TOKEN", token.Token)
	assertEq(t, "SECRET", token.Secret)
	assertEq(t, "consumersecret&", m.signer.UsedKey)
	assertEq(t, "http://www.mrjon.es/authorizetoken?oauth_token=TOKEN", url)
}

func TestSuccessfulTokenAuthorization(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/accesstoken",
		map[string]string{
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_token":            "RTOKEN",
			"oauth_verifier":         "VERIFICATION_CODE",
			"oauth_version":          "1.0",
		},
		"oauth_token=ATOKEN&oauth_token_secret=ATOKEN_SECRET")

  rtoken := &RequestToken{Token: "RTOKEN", Secret: "RSECRET"}
	atoken, err := c.AuthorizeToken(rtoken, "VERIFICATION_CODE")
	if err != nil {
		t.Fatal(err)
	}

	assertEq(t, "ATOKEN", atoken.Token)
	assertEq(t, "ATOKEN_SECRET", atoken.Secret)
	assertEq(t, "consumersecret&RSECRET", m.signer.UsedKey)
}

func TestSuccessfulAuthorizedGet(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/someurl?key=val",
		map[string]string{
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_token":            "TOKEN",
			"oauth_version":          "1.0",
		},
		"BODY:SUCCESS")

  token := &AccessToken{Token: "TOKEN", Secret: "SECRET"}

	resp, err := c.Get(
		"http://www.mrjon.es/someurl", map[string]string{"key": "val"}, token)

	if err != nil {
		t.Fatal(err)
	}

	assertEq(t, "consumersecret&SECRET", m.signer.UsedKey)

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assertEq(t, "BODY:SUCCESS", string(body))
}

func Test404OnTokenRequest(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ReturnStatusCode(404, "Not Found")

	_, _, err := c.GetRequestTokenAndUrl()
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func Test404OnAuthorizationRequest(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ReturnStatusCode(404, "Not Found")

  rtoken := &RequestToken{Token: "RTOKEN", Secret: "RSECRET"}
	_, err := c.AuthorizeToken(rtoken, "VERIFICATION_CODE")
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func Test404OnGet(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ReturnStatusCode(404, "Not Found")

  atoken := &AccessToken{Token: "ATOKEN", Secret: "ASECRET"}
	_, err := c.Get("URL", map[string]string{}, atoken)
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func TestMissingRequestTokenSecret(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/requesttoken",
		map[string]string{
			"oauth_callback":         http.URLEscape("http://www.mrjon.es/callback"),
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_version":          "1.0",
		},
		"oauth_token=TOKEN") // Missing token_secret

	_, _, err := c.GetRequestTokenAndUrl()
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func TestMissingRequestToken(t *testing.T) {
	c := basicConsumer()
	m := newMocks(t)
	m.install(c)

	m.httpClient.ExpectGet(
		"http://www.mrjon.es/requesttoken",
		map[string]string{
			"oauth_callback":         http.URLEscape("http://www.mrjon.es/callback"),
			"oauth_consumer_key":     "consumerkey",
			"oauth_nonce":            "2",
			"oauth_signature":        "MOCK_SIGNATURE",
			"oauth_signature_method": "HMAC-SHA1",
			"oauth_timestamp":        "1",
			"oauth_version":          "1.0",
		},
		"oauth_token_secret=SECRET") // Missing token

	_, _, err := c.GetRequestTokenAndUrl()
	if err == nil {
		t.Fatal("Should have raised an error")
	}
}

func basicConsumer() *Consumer {
	return &Consumer{
		ConsumerKey:       "consumerkey",
		ConsumerSecret:    "consumersecret",
		RequestTokenUrl:   "http://www.mrjon.es/requesttoken",
		AuthorizeTokenUrl: "http://www.mrjon.es/authorizetoken",
		AccessTokenUrl:    "http://www.mrjon.es/accesstoken",
		CallbackUrl:       "http://www.mrjon.es/callback",
	}
}

func assertEq(t *testing.T, expected interface{}, actual interface{}) {
	assertEqM(t, expected, actual, "")
}

func assertEqM(t *testing.T, expected interface{}, actual interface{}, msg string) {
	if expected != actual {
		t.Fatalf("Assertion error.\n\tExpected: '%s'\n\tActual:   '%s'\n\tMessage:  '%s'",
			expected, actual, msg)
	}
}

type MockHttpClient struct {
	url          string
	oAuthChecker *OAuthChecker
	responseBody string
	statusCode   int

	t *testing.T
}

func NewMockHttpClient(t *testing.T) *MockHttpClient {
	return &MockHttpClient{t: t, statusCode: 200}
}

func (mock *MockHttpClient) Do(req *http.Request) (*http.Response, os.Error) {
	if mock.url != "" && req.URL.String() != mock.url {
		mock.t.Fatalf("URLs did not match.\nExpected: '%s'\nActual: '%s'",
			mock.url, req.URL.String())
	}
	if mock.oAuthChecker != nil {
		if req.Header == nil {
			mock.t.Fatal("Missing 'Authorization' header.")
		}
		mock.oAuthChecker.CheckHeader(req.Header.Get("Authorization"))
	}

	return &http.Response{
		StatusCode: mock.statusCode,
		Body:       NewMockBody(mock.responseBody),
	},
		nil
}

func (mock *MockHttpClient) ExpectGet(
	  expectedUrl string, expectedOAuthPairs map[string]string, responseBody string) {
	mock.url = expectedUrl
	mock.oAuthChecker = NewOAuthChecker(mock.t, expectedOAuthPairs)
	mock.responseBody = responseBody
}

func (mock *MockHttpClient) ReturnStatusCode(statusCode int, body string) {
	mock.statusCode = statusCode
	mock.responseBody = body
}

type OAuthChecker struct {
	headerPairs map[string]string
	t           *testing.T
}

func NewOAuthChecker(t *testing.T, headerPairs map[string]string) *OAuthChecker {
	return &OAuthChecker{
		headerPairs: headerPairs,
		t:           t,
	}
}

func (o *OAuthChecker) CheckHeader(header string) {
	assertEqM(o.t, "OAuth ", header[0:6], "OAuth Header did not begin correctly.")
	paramsStr := header[6:]
	params := strings.Split(paramsStr, "\n    ", -1)
	paramMap := make(map[string]string)
	for _, param := range params {
		keyvalue := strings.Split(param, "=", -1)
		// line looks like: key="value", strip off the quotes
		// TODO(mrjones): this is pretty hacky
		value := keyvalue[1]
		if strings.HasSuffix(value, ",") {
			value = value[0 : len(value)-1]
		}
		value = value[1 : len(value)-1]
		paramMap[keyvalue[0]] = value
	}
	for key, value := range o.headerPairs {
		assertEqM(o.t, value, paramMap[key], "For OAuth parameter "+key)
	}
}

type MockBody struct {
	reader io.Reader
}

func NewMockBody(body string) *MockBody {
	return &MockBody{
		reader: strings.NewReader(body),
	}
}

func (*MockBody) Close() os.Error {
	return nil
}

func (mock *MockBody) Read(p []byte) (n int, err os.Error) {
	return mock.reader.Read(p)
}

type MockClock struct {
	Time int64
}

func (m *MockClock) Seconds() int64 {
	return m.Time
}

type MockNonceGenerator struct {
	Nonce int64
}

func (m *MockNonceGenerator) Int63() int64 {
	return m.Nonce
}

type MockSigner struct {
	UsedKey      string
	SignedString string
}

func (m *MockSigner) Sign(message string, key string) string {
	m.UsedKey = key
	m.SignedString = message
	return "MOCK_SIGNATURE"
}
<|endoftext|>


<commit_before>package slinga

import (
	"github.com/golang/glog"
	yaml "gopkg.in/yaml.v2"
	"k8s.io/helm/pkg/helm"
	"strings"
)

// HelmCodeExecutor is an executor that uses Helm for deployment of apps on kubernetes
type HelmCodeExecutor struct {
	Code *Code
}

func HelmName(str string) string {
	r := strings.NewReplacer("#", "-", "_", "-")
	return r.Replace(str)
}

const (
	//tillerHost = "tiller-deploy.kube-system.svc.cluster.local:44134"
	tillerHost = "kapp-demo-1:40666"
)

func newHelmClient() *helm.Client {
	return helm.NewClient(helm.Host(tillerHost))
}

func findHelmRelease(helmClient *helm.Client, name string) (bool, error) {
	resp, err := helmClient.ListReleases()
	if err != nil {
		return false, nil
	}

	for _, rel := range resp.Releases {
		if rel.Name == name {
			return true, nil
		}
	}

	return false, nil
}

// Install for HelmCodeExecutor runs "helm install" for the corresponding helm chart
func (executor HelmCodeExecutor) Install(key string, codeMetadata map[string]string, codeParams interface{}) error {
	releaseName := strings.ToLower(HelmName(key))

	chartName := codeMetadata["chartName"]

	helmClient := newHelmClient()

	// TODO check err separately
	if exists, err := findHelmRelease(helmClient, releaseName); exists && err == nil {
		// TODO log that it's already installed
		// TODO update release just in case
		return nil
	}

	chartPath := GetAptomiPolicyDir() + "/charts/" + chartName + ".tgz"

	vals, err := yaml.Marshal(codeParams)
	if err != nil {
		return err
	}

	glog.Infof("Installing new Helm release '%s' of '%s' (path: %s) with params:\n%s", releaseName, chartName, chartPath, string(vals))

	// TODO is it good to reuse name?
	_ /*resp*/, err = helmClient.InstallRelease(chartPath, "aptomi", helm.ReleaseName(releaseName), helm.ValueOverrides(vals), helm.InstallReuseName(true))
	if err != nil {
		return err
	}
	return nil
}

// Update for HelmCodeExecutor runs "helm update" for the corresponding helm chart
func (executor HelmCodeExecutor) Update(key string, codeMetadata map[string]string, codeParams interface{}) error {
	// TODO: implement update method
	return nil
}

// Destroy for HelmCodeExecutor runs "helm delete" for the corresponding helm chart
func (executor HelmCodeExecutor) Destroy(key string) error {
	releaseName := strings.ToLower(HelmName(key))

	helmClient := newHelmClient()

	glog.Infof("Deleting Helm release '%s'", releaseName)

	if _, err := helmClient.DeleteRelease(releaseName, helm.DeletePurge(true)); err != nil {
		return err
	}

	return nil
}
<commit_msg>Support Helm upgrade<commit_after>package slinga

import (
	"github.com/golang/glog"
	yaml "gopkg.in/yaml.v2"
	"k8s.io/helm/pkg/helm"
	"strings"
)

// HelmCodeExecutor is an executor that uses Helm for deployment of apps on kubernetes
type HelmCodeExecutor struct {
	Code *Code
}

func HelmName(str string) string {
	r := strings.NewReplacer("#", "-", "_", "-")
	return r.Replace(str)
}

const (
	//tillerHost = "tiller-deploy.kube-system.svc.cluster.local:44134"
	tillerHost = "kapp-demo-1:40666"
)

func newHelmClient() *helm.Client {
	return helm.NewClient(helm.Host(tillerHost))
}

func findHelmRelease(helmClient *helm.Client, name string) (bool, error) {
	resp, err := helmClient.ListReleases()
	if err != nil {
		return false, nil
	}

	for _, rel := range resp.Releases {
		if rel.Name == name {
			return true, nil
		}
	}

	return false, nil
}

//func preparePar

// Install for HelmCodeExecutor runs "helm install" for the corresponding helm chart
func (executor HelmCodeExecutor) Install(key string, codeMetadata map[string]string, codeParams interface{}) error {
	releaseName := strings.ToLower(HelmName(key))

	chartName := codeMetadata["chartName"]

	helmClient := newHelmClient()

	// TODO check err separately
	if exists, err := findHelmRelease(helmClient, releaseName); exists && err == nil {
		// TODO log that it's already installed
		// TODO update release just in case
		return nil
	}

	chartPath := GetAptomiPolicyDir() + "/charts/" + chartName + ".tgz"

	vals, err := yaml.Marshal(codeParams)
	if err != nil {
		return err
	}

	glog.Infof("Installing new Helm release '%s' of '%s' (path: %s) with params:\n%s", releaseName, chartName, chartPath, string(vals))

	// TODO is it good to reuse name?
	_ /*resp*/, err = helmClient.InstallRelease(chartPath, "aptomi", helm.ReleaseName(releaseName), helm.ValueOverrides(vals), helm.InstallReuseName(true))
	if err != nil {
		return err
	}
	return nil
}

// Update for HelmCodeExecutor runs "helm update" for the corresponding helm chart
func (executor HelmCodeExecutor) Update(key string, codeMetadata map[string]string, codeParams interface{}) error {
	// TODO merge with Install
	releaseName := strings.ToLower(HelmName(key))

	chartName := codeMetadata["chartName"]

	helmClient := newHelmClient()

	// TODO check err separately
	if exists, err := findHelmRelease(helmClient, releaseName); exists && err == nil {
		// TODO log that it's already installed
		// TODO update release just in case
		return nil
	}

	chartPath := GetAptomiPolicyDir() + "/charts/" + chartName + ".tgz"

	vals, err := yaml.Marshal(codeParams)
	if err != nil {
		return err
	}

	glog.Infof("Upgrading Helm release '%s' of '%s' (path: %s) with params:\n%s", releaseName, chartName, chartPath, string(vals))

	// TODO is it good to reuse name?
	_ /*resp*/, err = helmClient.UpdateRelease(releaseName, chartPath, helm.UpdateValueOverrides(vals))
	if err != nil {
		return err
	}

	return nil
}

// Destroy for HelmCodeExecutor runs "helm delete" for the corresponding helm chart
func (executor HelmCodeExecutor) Destroy(key string) error {
	releaseName := strings.ToLower(HelmName(key))

	helmClient := newHelmClient()

	glog.Infof("Deleting Helm release '%s'", releaseName)

	if _, err := helmClient.DeleteRelease(releaseName, helm.DeletePurge(true)); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package handshake

import (
	"bytes"
)

type dtlsRecord struct {
	raw            []byte
	contentType    uint8
	version        uint16
	epoch          uint16
	sequenceNumber uint64 // uint48
	length         uint16
	dtlsBody       []byte
}

func (m *dtlsRecord) marshal() []byte {
	if m.raw != nil {
		return m.raw
	}

	m.length = uint16(len(m.dtlsBody))

	buf := make([]byte, 13+m.length)

	buf[0] = m.contentType
	buf[1] = uint8(m.version >> 8)
	buf[2] = uint8(m.version)
	buf[3] = uint8(m.epoch >> 8)
	buf[4] = uint8(m.epoch)
	buf[5] = uint8(m.sequenceNumber >> 40)
	buf[6] = uint8(m.sequenceNumber >> 32)
	buf[7] = uint8(m.sequenceNumber >> 24)
	buf[8] = uint8(m.sequenceNumber >> 16)
	buf[9] = uint8(m.sequenceNumber >> 8)
	buf[10] = uint8(m.sequenceNumber)
	buf[11] = uint8(m.length >> 8)
	buf[12] = uint8(m.length)

	copy(buf[13:], m.dtlsBody)

	m.raw = buf

	return buf
}

func (m *dtlsRecord) unmarshal(data []byte) bool {
	if len(data) < 13 {
		return false
	}
	m.raw = data
	m.contentType = uint8(data[0])
	m.version = uint16(data[1])<<8 | uint16(data[2])
	m.epoch = uint16(data[3])<<8 | uint16(data[4])
	m.sequenceNumber = uint64(data[5])<<40 | uint64(data[6])<<32 | uint64(data[7])<<24 | uint64(data[8])<<16 | uint64(data[9])<<8 | uint64(data[10])
	m.length = uint16(data[11])<<8 | uint16(data[12])

	copy(m.dtlsBody, data[12:])

	return true
}

func (m *dtlsRecord) Equal(i interface{}) bool {
	m1, ok := i.(*dtlsRecord)
	if !ok {
		return false
	}

	return bytes.Equal(m.raw, m1.raw) &&
		m.contentType == m1.contentType &&
		m.version == m1.version &&
		m.epoch == m1.epoch &&
		m.sequenceNumber == m1.sequenceNumber &&
		m.length == m1.length &&
		bytes.Equal(m.dtlsBody, m1.dtlsBody)
}
<commit_msg>Added comments from RFC.<commit_after>package handshake

import (
	"bytes"
)

/*
   epoch: A counter value that is incremented on every cipher state change;
   initially zero and incremented each time a ChangeCipherSpec message is sent.

   sequenceNumber: explicit sequence number; Sequence numbers are maintained
   separately for each epoch, with each sequence_number initially being 0
   for each epoch.
*/

type dtlsRecord struct {
	raw            []byte
	contentType    uint8
	version        uint16
	epoch          uint16
	sequenceNumber uint64 // uint48
	length         uint16
	dtlsBody       []byte
}

func (m *dtlsRecord) marshal() []byte {
	if m.raw != nil {
		return m.raw
	}

	m.length = uint16(len(m.dtlsBody))

	buf := make([]byte, 13+m.length)

	buf[0] = m.contentType
	buf[1] = uint8(m.version >> 8)
	buf[2] = uint8(m.version)
	buf[3] = uint8(m.epoch >> 8)
	buf[4] = uint8(m.epoch)
	buf[5] = uint8(m.sequenceNumber >> 40)
	buf[6] = uint8(m.sequenceNumber >> 32)
	buf[7] = uint8(m.sequenceNumber >> 24)
	buf[8] = uint8(m.sequenceNumber >> 16)
	buf[9] = uint8(m.sequenceNumber >> 8)
	buf[10] = uint8(m.sequenceNumber)
	buf[11] = uint8(m.length >> 8)
	buf[12] = uint8(m.length)

	copy(buf[13:], m.dtlsBody)

	m.raw = buf

	return buf
}

func (m *dtlsRecord) unmarshal(data []byte) bool {
	if len(data) < 13 {
		return false
	}
	m.raw = data
	m.contentType = uint8(data[0])
	m.version = uint16(data[1])<<8 | uint16(data[2])
	m.epoch = uint16(data[3])<<8 | uint16(data[4])
	m.sequenceNumber = uint64(data[5])<<40 | uint64(data[6])<<32 | uint64(data[7])<<24 | uint64(data[8])<<16 | uint64(data[9])<<8 | uint64(data[10])
	m.length = uint16(data[11])<<8 | uint16(data[12])

	copy(m.dtlsBody, data[12:])

	return true
}

func (m *dtlsRecord) Equal(i interface{}) bool {
	m1, ok := i.(*dtlsRecord)
	if !ok {
		return false
	}

	return bytes.Equal(m.raw, m1.raw) &&
		m.contentType == m1.contentType &&
		m.version == m1.version &&
		m.epoch == m1.epoch &&
		m.sequenceNumber == m1.sequenceNumber &&
		m.length == m1.length &&
		bytes.Equal(m.dtlsBody, m1.dtlsBody)
}
<|endoftext|>


<commit_before>package model

import (
	"time"
)

type User struct {
	Id              uint      `gorm:"column:user_id;primary_key"`
	Username        string    `gorm:"column:username"`
	Password        string    `gorm:"column:password"`
	Email           string    `gorm:"column:email"`
	Status          int       `gorm:"column:status"`
	CreatedAt       time.Time `gorm:"column:created_at"`
	UpdatedAt       time.Time `gorm:"column:updated_at"`
	Token           string    `gorm:"column:api_token"`
	TokenExpiration time.Time `gorm:"column:api_token_expiry"`
	Language        string    `gorm:"column:language"`

	// TODO: move this to PublicUser
	LikingCount     int       `json:"likingCount" gorm:"-"`
	LikedCount      int       `json:"likedCount" gorm:"-"`
	Likings         []User    `gorm:"foreignkey:userId;associationforeignkey:follower_id;many2many:users_followers;"`
	Liked           []User    `gorm:"foreignkey:follower_id;associationforeignkey:userId;many2many:users_followers;"`

	Md5             string     `json:"md5" gorm:"-"`
	Torrents        []Torrents `gorm:"ForeignKey:UploaderId"`
}

type PublicUser struct {
	User      *User
}

// UsersFollowers is a relation table to relate users each other.
type UsersFollowers struct {
	UserID     uint `gorm:"column:user_id"`
	FollowerID uint `gorm:"column:following"`
}

func (c UsersFollowers) TableName() string {
	return "user_follows"
}
<commit_msg>Maybe fix gravatar<commit_after>package model

import (
	"time"
)

type User struct {
	Id              uint      `gorm:"column:user_id;primary_key"`
	Username        string    `gorm:"column:username"`
	Password        string    `gorm:"column:password"`
	Email           string    `gorm:"column:email"`
	Status          int       `gorm:"column:status"`
	CreatedAt       time.Time `gorm:"column:created_at"`
	UpdatedAt       time.Time `gorm:"column:updated_at"`
	Token           string    `gorm:"column:api_token"`
	TokenExpiration time.Time `gorm:"column:api_token_expiry"`
	Language        string    `gorm:"column:language"`

	// TODO: move this to PublicUser
	LikingCount     int       `json:"likingCount" gorm:"-"`
	LikedCount      int       `json:"likedCount" gorm:"-"`
	Likings         []User    `gorm:"foreignkey:userId;associationforeignkey:follower_id;many2many:users_followers;"`
	Liked           []User    `gorm:"foreignkey:follower_id;associationforeignkey:userId;many2many:users_followers;"`

	Md5             string     `json:"md5"`
	Torrents        []Torrents `gorm:"ForeignKey:UploaderId"`
}

type PublicUser struct {
	User      *User
}

// UsersFollowers is a relation table to relate users each other.
type UsersFollowers struct {
	UserID     uint `gorm:"column:user_id"`
	FollowerID uint `gorm:"column:following"`
}

func (c UsersFollowers) TableName() string {
	return "user_follows"
}
<|endoftext|>


<commit_before><commit_msg>Support GOARCH constraints for the `syscall` package overlays.<commit_after><|endoftext|>


<commit_before>// +build freebsd linux darwin

/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package util

import (
	"io/ioutil"
	"net"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestParseEndpoint(t *testing.T) {
	tests := []struct {
		endpoint         string
		expectError      bool
		expectedProtocol string
		expectedAddr     string
	}{
		{
			endpoint:         "unix:///tmp/s1.sock",
			expectedProtocol: "unix",
			expectedAddr:     "/tmp/s1.sock",
		},
		{
			endpoint:         "tcp://localhost:15880",
			expectedProtocol: "tcp",
			expectedAddr:     "localhost:15880",
		},
		{
			endpoint:         "npipe://./pipe/mypipe",
			expectedProtocol: "npipe",
			expectError:      true,
		},
		{
			endpoint:         "tcp1://abc",
			expectedProtocol: "tcp1",
			expectError:      true,
		},
		{
			endpoint:    "a b c",
			expectError: true,
		},
	}

	for _, test := range tests {
		protocol, addr, err := parseEndpoint(test.endpoint)
		assert.Equal(t, test.expectedProtocol, protocol)
		if test.expectError {
			assert.NotNil(t, err, "Expect error during parsing %q", test.endpoint)
			continue
		}
		assert.Nil(t, err, "Expect no error during parsing %q", test.endpoint)
		assert.Equal(t, test.expectedAddr, addr)
	}

}

func TestIsUnixDomainSocket(t *testing.T) {
	tests := []struct {
		label          string
		listenOnSocket bool
		expectSocket   bool
		expectError    bool
		invalidFile    bool
	}{
		{
			label:          "Domain Socket file",
			listenOnSocket: true,
			expectSocket:   true,
			expectError:    false,
		},
		{
			label:       "Non Existent file",
			invalidFile: true,
			expectError: true,
		},
		{
			label:          "Regular file",
			listenOnSocket: false,
			expectSocket:   false,
			expectError:    false,
		},
	}
	for _, test := range tests {
		f, err := ioutil.TempFile("", "test-domain-socket")
		require.NoErrorf(t, err, "Failed to create file for test purposes: %v while setting up: %s", err, test.label)
		addr := f.Name()
		f.Close()
		var ln *net.UnixListener
		if test.listenOnSocket {
			os.Remove(addr)
			ta, err := net.ResolveUnixAddr("unix", addr)
			require.NoErrorf(t, err, "Failed to ResolveUnixAddr: %v while setting up: %s", err, test.label)
			ln, err = net.ListenUnix("unix", ta)
			require.NoErrorf(t, err, "Failed to ListenUnix: %v while setting up: %s", err, test.label)
		}
		fileToTest := addr
		if test.invalidFile {
			fileToTest = fileToTest + ".invalid"
		}
		result, err := IsUnixDomainSocket(fileToTest)
		if test.listenOnSocket {
			// this takes care of removing the file associated with the domain socket
			ln.Close()
		} else {
			// explicitly remove regular file
			os.Remove(addr)
		}
		if test.expectError {
			assert.NotNil(t, err, "Unexpected nil error from IsUnixDomainSocket for %s", test.label)
		} else {
			assert.Nil(t, err, "Unexpected error invoking IsUnixDomainSocket for %s", test.label)
		}
		assert.Equal(t, result, test.expectSocket, "Unexpected result from IsUnixDomainSocket: %v for %s", result, test.label)
	}
}
<commit_msg>add GetAddressAndDialer unit test<commit_after>// +build freebsd linux darwin

/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package util

import (
	"io/ioutil"
	"net"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestParseEndpoint(t *testing.T) {
	tests := []struct {
		endpoint         string
		expectError      bool
		expectedProtocol string
		expectedAddr     string
	}{
		{
			endpoint:         "unix:///tmp/s1.sock",
			expectedProtocol: "unix",
			expectedAddr:     "/tmp/s1.sock",
		},
		{
			endpoint:         "tcp://localhost:15880",
			expectedProtocol: "tcp",
			expectedAddr:     "localhost:15880",
		},
		{
			endpoint:         "npipe://./pipe/mypipe",
			expectedProtocol: "npipe",
			expectError:      true,
		},
		{
			endpoint:         "tcp1://abc",
			expectedProtocol: "tcp1",
			expectError:      true,
		},
		{
			endpoint:    "a b c",
			expectError: true,
		},
	}

	for _, test := range tests {
		protocol, addr, err := parseEndpoint(test.endpoint)
		assert.Equal(t, test.expectedProtocol, protocol)
		if test.expectError {
			assert.NotNil(t, err, "Expect error during parsing %q", test.endpoint)
			continue
		}
		assert.Nil(t, err, "Expect no error during parsing %q", test.endpoint)
		assert.Equal(t, test.expectedAddr, addr)
	}

}

func TestIsUnixDomainSocket(t *testing.T) {
	tests := []struct {
		label          string
		listenOnSocket bool
		expectSocket   bool
		expectError    bool
		invalidFile    bool
	}{
		{
			label:          "Domain Socket file",
			listenOnSocket: true,
			expectSocket:   true,
			expectError:    false,
		},
		{
			label:       "Non Existent file",
			invalidFile: true,
			expectError: true,
		},
		{
			label:          "Regular file",
			listenOnSocket: false,
			expectSocket:   false,
			expectError:    false,
		},
	}
	for _, test := range tests {
		f, err := ioutil.TempFile("", "test-domain-socket")
		require.NoErrorf(t, err, "Failed to create file for test purposes: %v while setting up: %s", err, test.label)
		addr := f.Name()
		f.Close()
		var ln *net.UnixListener
		if test.listenOnSocket {
			os.Remove(addr)
			ta, err := net.ResolveUnixAddr("unix", addr)
			require.NoErrorf(t, err, "Failed to ResolveUnixAddr: %v while setting up: %s", err, test.label)
			ln, err = net.ListenUnix("unix", ta)
			require.NoErrorf(t, err, "Failed to ListenUnix: %v while setting up: %s", err, test.label)
		}
		fileToTest := addr
		if test.invalidFile {
			fileToTest = fileToTest + ".invalid"
		}
		result, err := IsUnixDomainSocket(fileToTest)
		if test.listenOnSocket {
			// this takes care of removing the file associated with the domain socket
			ln.Close()
		} else {
			// explicitly remove regular file
			os.Remove(addr)
		}
		if test.expectError {
			assert.NotNil(t, err, "Unexpected nil error from IsUnixDomainSocket for %s", test.label)
		} else {
			assert.Nil(t, err, "Unexpected error invoking IsUnixDomainSocket for %s", test.label)
		}
		assert.Equal(t, result, test.expectSocket, "Unexpected result from IsUnixDomainSocket: %v for %s", result, test.label)
	}
}

func TestGetAddressAndDialer(t *testing.T) {
	tests := []struct {
		endpoint     string
		expectError  bool
		expectedAddr string
	}{
		{
			endpoint:     "unix:///tmp/s1.sock",
			expectError:  false,
			expectedAddr: "/tmp/s1.sock",
		},
		{
			endpoint:     "unix:///tmp/f6.sock",
			expectError:  false,
			expectedAddr: "/tmp/f6.sock",
		},
		{
			endpoint:    "tco:/localhost:9090",
			expectError: true,
		},
		{
			// The misspelling is intentional to make it error
			endpoint:    "htta://free-test.com",
			expectError: true,
		},
	}
	for _, test := range tests {
		// just test addr and err
		addr, _, err := GetAddressAndDialer(test.endpoint)
		if test.expectError {
			assert.NotNil(t, err, "expected error during parsing %s", test.endpoint)
			continue
		}
		assert.Nil(t, err, "expected no error during parsing %s", test.endpoint)
		assert.Equal(t, test.expectedAddr, addr)
	}
}
<|endoftext|>


<commit_before>package wrangler

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"sync"

	istiov1alpha3api "github.com/knative/pkg/apis/istio/v1alpha3"
	prommonitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
	fleetv1alpha1api "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
	"github.com/rancher/lasso/pkg/controller"
	"github.com/rancher/lasso/pkg/dynamic"
	catalogv1 "github.com/rancher/rancher/pkg/apis/catalog.cattle.io/v1"
	clusterv3api "github.com/rancher/rancher/pkg/apis/cluster.cattle.io/v3"
	managementv3api "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
	projectv3api "github.com/rancher/rancher/pkg/apis/project.cattle.io/v3"
	provisioningv1api "github.com/rancher/rancher/pkg/apis/provisioning.cattle.io/v1"
	rkev1api "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
	"github.com/rancher/rancher/pkg/catalogv2/content"
	"github.com/rancher/rancher/pkg/catalogv2/helmop"
	"github.com/rancher/rancher/pkg/catalogv2/system"
	"github.com/rancher/rancher/pkg/generated/controllers/catalog.cattle.io"
	catalogcontrollers "github.com/rancher/rancher/pkg/generated/controllers/catalog.cattle.io/v1"
	capi "github.com/rancher/rancher/pkg/generated/controllers/cluster.x-k8s.io"
	capicontrollers "github.com/rancher/rancher/pkg/generated/controllers/cluster.x-k8s.io/v1alpha4"
	"github.com/rancher/rancher/pkg/generated/controllers/fleet.cattle.io"
	fleetv1alpha1 "github.com/rancher/rancher/pkg/generated/controllers/fleet.cattle.io/v1alpha1"
	"github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io"
	managementv3 "github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/generated/controllers/project.cattle.io"
	projectv3 "github.com/rancher/rancher/pkg/generated/controllers/project.cattle.io/v3"
	"github.com/rancher/rancher/pkg/generated/controllers/provisioning.cattle.io"
	provisioningv1 "github.com/rancher/rancher/pkg/generated/controllers/provisioning.cattle.io/v1"
	"github.com/rancher/rancher/pkg/generated/controllers/rke.cattle.io"
	rkecontrollers "github.com/rancher/rancher/pkg/generated/controllers/rke.cattle.io/v1"
	"github.com/rancher/rancher/pkg/peermanager"
	"github.com/rancher/rancher/pkg/tunnelserver"
	"github.com/rancher/remotedialer"
	"github.com/rancher/steve/pkg/accesscontrol"
	"github.com/rancher/steve/pkg/client"
	"github.com/rancher/steve/pkg/server"
	"github.com/rancher/wrangler/pkg/apply"
	admissionreg "github.com/rancher/wrangler/pkg/generated/controllers/admissionregistration.k8s.io"
	admissionregcontrollers "github.com/rancher/wrangler/pkg/generated/controllers/admissionregistration.k8s.io/v1"
	"github.com/rancher/wrangler/pkg/generated/controllers/apps"
	appsv1 "github.com/rancher/wrangler/pkg/generated/controllers/apps/v1"
	"github.com/rancher/wrangler/pkg/generated/controllers/batch"
	batchv1 "github.com/rancher/wrangler/pkg/generated/controllers/batch/v1"
	"github.com/rancher/wrangler/pkg/generic"
	"github.com/rancher/wrangler/pkg/leader"
	"github.com/rancher/wrangler/pkg/schemes"
	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/client-go/discovery"
	"k8s.io/client-go/discovery/cached/memory"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/restmapper"
	"k8s.io/client-go/tools/clientcmd"
	apiregistrationv12 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
	capiv1alpha4api "sigs.k8s.io/cluster-api/api/v1alpha4"
)

var (
	localSchemeBuilder = runtime.SchemeBuilder{
		provisioningv1api.AddToScheme,
		capiv1alpha4api.AddToScheme,
		fleetv1alpha1api.AddToScheme,
		managementv3api.AddToScheme,
		projectv3api.AddToScheme,
		clusterv3api.AddToScheme,
		rkev1api.AddToScheme,
		scheme.AddToScheme,
		apiextensionsv1beta1.AddToScheme,
		apiregistrationv12.AddToScheme,
		prommonitoringv1.AddToScheme,
		istiov1alpha3api.AddToScheme,
		catalogv1.AddToScheme,
	}
	AddToScheme = localSchemeBuilder.AddToScheme
	Scheme      = runtime.NewScheme()
)

func init() {
	utilruntime.Must(AddToScheme(Scheme))
	utilruntime.Must(schemes.AddToScheme(Scheme))
}

type Context struct {
	*server.Controllers

	Apply               apply.Apply
	Dynamic             *dynamic.Controller
	CAPI                capicontrollers.Interface
	RKE                 rkecontrollers.Interface
	Mgmt                managementv3.Interface
	Apps                appsv1.Interface
	Admission           admissionregcontrollers.Interface
	Batch               batchv1.Interface
	Fleet               fleetv1alpha1.Interface
	Project             projectv3.Interface
	Catalog             catalogcontrollers.Interface
	ControllerFactory   controller.SharedControllerFactory
	MultiClusterManager MultiClusterManager
	TunnelServer        *remotedialer.Server
	TunnelAuthorizer    *tunnelserver.Authorizers
	PeerManager         peermanager.PeerManager
	Provisioning        provisioningv1.Interface

	ASL                     accesscontrol.AccessSetLookup
	ClientConfig            clientcmd.ClientConfig
	CachedDiscovery         discovery.CachedDiscoveryInterface
	RESTMapper              meta.RESTMapper
	SharedControllerFactory controller.SharedControllerFactory
	leadership              *leader.Manager
	controllerLock          sync.Mutex

	RESTClientGetter      genericclioptions.RESTClientGetter
	CatalogContentManager *content.Manager
	HelmOperations        *helmop.Operations
	SystemChartsManager   *system.Manager
}

type MultiClusterManager interface {
	ClusterDialer(clusterID string) func(ctx context.Context, network, address string) (net.Conn, error)
	Start(ctx context.Context) error
	Wait(ctx context.Context)
	Middleware(next http.Handler) http.Handler
	K8sClient(clusterName string) (kubernetes.Interface, error)
}

func (w *Context) OnLeader(f func(ctx context.Context) error) {
	w.leadership.OnLeader(f)
}

func (w *Context) StartWithTransaction(ctx context.Context, f func(context.Context) error) (err error) {
	defer func() {
		if err == nil {
			err = w.Start(ctx)
		}
	}()

	w.controllerLock.Lock()
	defer w.controllerLock.Unlock()

	transaction := controller.NewHandlerTransaction(ctx)
	if err := f(transaction); err != nil {
		transaction.Rollback()
		return err
	}
	transaction.Commit()
	return nil
}

func (w *Context) Start(ctx context.Context) error {
	w.controllerLock.Lock()
	defer w.controllerLock.Unlock()

	if err := w.Dynamic.Register(ctx, w.SharedControllerFactory); err != nil {
		return err
	}

	if err := w.ControllerFactory.Start(ctx, 5); err != nil {
		return err
	}
	w.leadership.Start(ctx)
	return nil
}

func NewContext(ctx context.Context, clientConfig clientcmd.ClientConfig, restConfig *rest.Config) (*Context, error) {
	controllerFactory, err := controller.NewSharedControllerFactoryFromConfig(restConfig, Scheme)
	if err != nil {
		return nil, err
	}

	opts := &generic.FactoryOptions{
		SharedControllerFactory: controllerFactory,
	}

	steveControllers, err := server.NewController(restConfig, opts)
	if err != nil {
		return nil, err
	}

	cache := memory.NewMemCacheClient(steveControllers.K8s.Discovery())
	restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cache)

	apply, err := apply.NewForConfig(restConfig)
	if err != nil {
		return nil, err
	}

	mgmt, err := management.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	apps, err := apps.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	adminReg, err := admissionreg.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	project, err := project.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	capi, err := capi.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	rke, err := rke.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	fleet, err := fleet.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	provisioning, err := provisioning.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	helm, err := catalog.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	batch, err := batch.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	asl := accesscontrol.NewAccessStore(ctx, true, steveControllers.RBAC)

	cg, err := client.NewFactory(restConfig, false)
	if err != nil {
		return nil, err
	}

	content := content.NewManager(
		steveControllers.K8s.Discovery(),
		steveControllers.Core.ConfigMap().Cache(),
		steveControllers.Core.Secret().Cache(),
		helm.Catalog().V1().ClusterRepo().Cache())

	helmop := helmop.NewOperations(cg,
		helm.Catalog().V1(),
		content,
		steveControllers.Core.Pod())

	restClientGetter := &SimpleRESTClientGetter{
		ClientConfig:    clientConfig,
		RESTConfig:      restConfig,
		CachedDiscovery: cache,
		RESTMapper:      restMapper,
	}

	systemCharts, err := system.NewManager(ctx, restClientGetter, content, helmop, steveControllers.Core.Pod())
	if err != nil {
		return nil, err
	}

	tunnelAuth := &tunnelserver.Authorizers{}
	tunnelServer := remotedialer.New(tunnelAuth.Authorize, remotedialer.DefaultErrorWriter)
	peerManager, err := tunnelserver.NewPeerManager(ctx, steveControllers.Core.Endpoints(), tunnelServer)
	if err != nil {
		return nil, err
	}

	leadership := leader.NewManager("", "cattle-controllers", steveControllers.K8s)
	leadership.OnLeader(func(ctx context.Context) error {
		if peerManager != nil {
			peerManager.Leader()
		}
		return nil
	})

	return &Context{
		Controllers:             steveControllers,
		Apply:                   apply,
		SharedControllerFactory: controllerFactory,
		Dynamic:                 dynamic.New(steveControllers.K8s.Discovery()),
		CAPI:                    capi.Cluster().V1alpha4(),
		RKE:                     rke.Rke().V1(),
		Mgmt:                    mgmt.Management().V3(),
		Apps:                    apps.Apps().V1(),
		Admission:               adminReg.Admissionregistration().V1(),
		Project:                 project.Project().V3(),
		Fleet:                   fleet.Fleet().V1alpha1(),
		Provisioning:            provisioning.Provisioning().V1(),
		Catalog:                 helm.Catalog().V1(),
		Batch:                   batch.Batch().V1(),
		ControllerFactory:       controllerFactory,
		ASL:                     asl,
		ClientConfig:            clientConfig,
		MultiClusterManager:     noopMCM{},
		CachedDiscovery:         cache,
		RESTMapper:              restMapper,
		leadership:              leadership,
		RESTClientGetter:        restClientGetter,
		CatalogContentManager:   content,
		HelmOperations:          helmop,
		SystemChartsManager:     systemCharts,
		TunnelAuthorizer:        tunnelAuth,
		TunnelServer:            tunnelServer,
	}, nil
}

type noopMCM struct {
}

func (n noopMCM) ClusterDialer(clusterID string) func(ctx context.Context, network string, address string) (net.Conn, error) {
	return func(ctx context.Context, network string, address string) (net.Conn, error) {
		return nil, fmt.Errorf("no cluster manager")
	}
}

func (n noopMCM) Wait(ctx context.Context) {
}

func (n noopMCM) Start(ctx context.Context) error {
	return nil
}

func (n noopMCM) Middleware(next http.Handler) http.Handler {
	return next
}

func (n noopMCM) K8sClient(clusterName string) (kubernetes.Interface, error) {
	return nil, nil
}

type SimpleRESTClientGetter struct {
	ClientConfig    clientcmd.ClientConfig
	RESTConfig      *rest.Config
	CachedDiscovery discovery.CachedDiscoveryInterface
	RESTMapper      meta.RESTMapper
}

func (s *SimpleRESTClientGetter) ToRawKubeConfigLoader() clientcmd.ClientConfig {
	return s.ClientConfig
}

func (s *SimpleRESTClientGetter) ToRESTConfig() (*rest.Config, error) {
	return s.RESTConfig, nil
}

func (s *SimpleRESTClientGetter) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
	return s.CachedDiscovery, nil
}

func (s *SimpleRESTClientGetter) ToRESTMapper() (meta.RESTMapper, error) {
	return s.RESTMapper, nil
}
<commit_msg>Bump management controller workers to 50<commit_after>package wrangler

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"sync"

	istiov1alpha3api "github.com/knative/pkg/apis/istio/v1alpha3"
	prommonitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
	fleetv1alpha1api "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
	"github.com/rancher/lasso/pkg/controller"
	"github.com/rancher/lasso/pkg/dynamic"
	catalogv1 "github.com/rancher/rancher/pkg/apis/catalog.cattle.io/v1"
	clusterv3api "github.com/rancher/rancher/pkg/apis/cluster.cattle.io/v3"
	managementv3api "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
	projectv3api "github.com/rancher/rancher/pkg/apis/project.cattle.io/v3"
	provisioningv1api "github.com/rancher/rancher/pkg/apis/provisioning.cattle.io/v1"
	rkev1api "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
	"github.com/rancher/rancher/pkg/catalogv2/content"
	"github.com/rancher/rancher/pkg/catalogv2/helmop"
	"github.com/rancher/rancher/pkg/catalogv2/system"
	"github.com/rancher/rancher/pkg/generated/controllers/catalog.cattle.io"
	catalogcontrollers "github.com/rancher/rancher/pkg/generated/controllers/catalog.cattle.io/v1"
	capi "github.com/rancher/rancher/pkg/generated/controllers/cluster.x-k8s.io"
	capicontrollers "github.com/rancher/rancher/pkg/generated/controllers/cluster.x-k8s.io/v1alpha4"
	"github.com/rancher/rancher/pkg/generated/controllers/fleet.cattle.io"
	fleetv1alpha1 "github.com/rancher/rancher/pkg/generated/controllers/fleet.cattle.io/v1alpha1"
	"github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io"
	managementv3 "github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/generated/controllers/project.cattle.io"
	projectv3 "github.com/rancher/rancher/pkg/generated/controllers/project.cattle.io/v3"
	"github.com/rancher/rancher/pkg/generated/controllers/provisioning.cattle.io"
	provisioningv1 "github.com/rancher/rancher/pkg/generated/controllers/provisioning.cattle.io/v1"
	"github.com/rancher/rancher/pkg/generated/controllers/rke.cattle.io"
	rkecontrollers "github.com/rancher/rancher/pkg/generated/controllers/rke.cattle.io/v1"
	"github.com/rancher/rancher/pkg/peermanager"
	"github.com/rancher/rancher/pkg/tunnelserver"
	"github.com/rancher/remotedialer"
	"github.com/rancher/steve/pkg/accesscontrol"
	"github.com/rancher/steve/pkg/client"
	"github.com/rancher/steve/pkg/server"
	"github.com/rancher/wrangler/pkg/apply"
	admissionreg "github.com/rancher/wrangler/pkg/generated/controllers/admissionregistration.k8s.io"
	admissionregcontrollers "github.com/rancher/wrangler/pkg/generated/controllers/admissionregistration.k8s.io/v1"
	"github.com/rancher/wrangler/pkg/generated/controllers/apps"
	appsv1 "github.com/rancher/wrangler/pkg/generated/controllers/apps/v1"
	"github.com/rancher/wrangler/pkg/generated/controllers/batch"
	batchv1 "github.com/rancher/wrangler/pkg/generated/controllers/batch/v1"
	"github.com/rancher/wrangler/pkg/generic"
	"github.com/rancher/wrangler/pkg/leader"
	"github.com/rancher/wrangler/pkg/schemes"
	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/client-go/discovery"
	"k8s.io/client-go/discovery/cached/memory"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/restmapper"
	"k8s.io/client-go/tools/clientcmd"
	apiregistrationv12 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
	capiv1alpha4api "sigs.k8s.io/cluster-api/api/v1alpha4"
)

var (
	localSchemeBuilder = runtime.SchemeBuilder{
		provisioningv1api.AddToScheme,
		capiv1alpha4api.AddToScheme,
		fleetv1alpha1api.AddToScheme,
		managementv3api.AddToScheme,
		projectv3api.AddToScheme,
		clusterv3api.AddToScheme,
		rkev1api.AddToScheme,
		scheme.AddToScheme,
		apiextensionsv1beta1.AddToScheme,
		apiregistrationv12.AddToScheme,
		prommonitoringv1.AddToScheme,
		istiov1alpha3api.AddToScheme,
		catalogv1.AddToScheme,
	}
	AddToScheme = localSchemeBuilder.AddToScheme
	Scheme      = runtime.NewScheme()
)

func init() {
	utilruntime.Must(AddToScheme(Scheme))
	utilruntime.Must(schemes.AddToScheme(Scheme))
}

type Context struct {
	*server.Controllers

	Apply               apply.Apply
	Dynamic             *dynamic.Controller
	CAPI                capicontrollers.Interface
	RKE                 rkecontrollers.Interface
	Mgmt                managementv3.Interface
	Apps                appsv1.Interface
	Admission           admissionregcontrollers.Interface
	Batch               batchv1.Interface
	Fleet               fleetv1alpha1.Interface
	Project             projectv3.Interface
	Catalog             catalogcontrollers.Interface
	ControllerFactory   controller.SharedControllerFactory
	MultiClusterManager MultiClusterManager
	TunnelServer        *remotedialer.Server
	TunnelAuthorizer    *tunnelserver.Authorizers
	PeerManager         peermanager.PeerManager
	Provisioning        provisioningv1.Interface

	ASL                     accesscontrol.AccessSetLookup
	ClientConfig            clientcmd.ClientConfig
	CachedDiscovery         discovery.CachedDiscoveryInterface
	RESTMapper              meta.RESTMapper
	SharedControllerFactory controller.SharedControllerFactory
	leadership              *leader.Manager
	controllerLock          sync.Mutex

	RESTClientGetter      genericclioptions.RESTClientGetter
	CatalogContentManager *content.Manager
	HelmOperations        *helmop.Operations
	SystemChartsManager   *system.Manager
}

type MultiClusterManager interface {
	ClusterDialer(clusterID string) func(ctx context.Context, network, address string) (net.Conn, error)
	Start(ctx context.Context) error
	Wait(ctx context.Context)
	Middleware(next http.Handler) http.Handler
	K8sClient(clusterName string) (kubernetes.Interface, error)
}

func (w *Context) OnLeader(f func(ctx context.Context) error) {
	w.leadership.OnLeader(f)
}

func (w *Context) StartWithTransaction(ctx context.Context, f func(context.Context) error) (err error) {
	defer func() {
		if err == nil {
			err = w.Start(ctx)
		}
	}()

	w.controllerLock.Lock()
	defer w.controllerLock.Unlock()

	transaction := controller.NewHandlerTransaction(ctx)
	if err := f(transaction); err != nil {
		transaction.Rollback()
		return err
	}
	transaction.Commit()
	return nil
}

func (w *Context) Start(ctx context.Context) error {
	w.controllerLock.Lock()
	defer w.controllerLock.Unlock()

	if err := w.Dynamic.Register(ctx, w.SharedControllerFactory); err != nil {
		return err
	}

	if err := w.ControllerFactory.Start(ctx, 50); err != nil {
		return err
	}
	w.leadership.Start(ctx)
	return nil
}

func NewContext(ctx context.Context, clientConfig clientcmd.ClientConfig, restConfig *rest.Config) (*Context, error) {
	controllerFactory, err := controller.NewSharedControllerFactoryFromConfig(restConfig, Scheme)
	if err != nil {
		return nil, err
	}

	opts := &generic.FactoryOptions{
		SharedControllerFactory: controllerFactory,
	}

	steveControllers, err := server.NewController(restConfig, opts)
	if err != nil {
		return nil, err
	}

	cache := memory.NewMemCacheClient(steveControllers.K8s.Discovery())
	restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cache)

	apply, err := apply.NewForConfig(restConfig)
	if err != nil {
		return nil, err
	}

	mgmt, err := management.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	apps, err := apps.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	adminReg, err := admissionreg.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	project, err := project.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	capi, err := capi.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	rke, err := rke.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	fleet, err := fleet.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	provisioning, err := provisioning.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	helm, err := catalog.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	batch, err := batch.NewFactoryFromConfigWithOptions(restConfig, opts)
	if err != nil {
		return nil, err
	}

	asl := accesscontrol.NewAccessStore(ctx, true, steveControllers.RBAC)

	cg, err := client.NewFactory(restConfig, false)
	if err != nil {
		return nil, err
	}

	content := content.NewManager(
		steveControllers.K8s.Discovery(),
		steveControllers.Core.ConfigMap().Cache(),
		steveControllers.Core.Secret().Cache(),
		helm.Catalog().V1().ClusterRepo().Cache())

	helmop := helmop.NewOperations(cg,
		helm.Catalog().V1(),
		content,
		steveControllers.Core.Pod())

	restClientGetter := &SimpleRESTClientGetter{
		ClientConfig:    clientConfig,
		RESTConfig:      restConfig,
		CachedDiscovery: cache,
		RESTMapper:      restMapper,
	}

	systemCharts, err := system.NewManager(ctx, restClientGetter, content, helmop, steveControllers.Core.Pod())
	if err != nil {
		return nil, err
	}

	tunnelAuth := &tunnelserver.Authorizers{}
	tunnelServer := remotedialer.New(tunnelAuth.Authorize, remotedialer.DefaultErrorWriter)
	peerManager, err := tunnelserver.NewPeerManager(ctx, steveControllers.Core.Endpoints(), tunnelServer)
	if err != nil {
		return nil, err
	}

	leadership := leader.NewManager("", "cattle-controllers", steveControllers.K8s)
	leadership.OnLeader(func(ctx context.Context) error {
		if peerManager != nil {
			peerManager.Leader()
		}
		return nil
	})

	return &Context{
		Controllers:             steveControllers,
		Apply:                   apply,
		SharedControllerFactory: controllerFactory,
		Dynamic:                 dynamic.New(steveControllers.K8s.Discovery()),
		CAPI:                    capi.Cluster().V1alpha4(),
		RKE:                     rke.Rke().V1(),
		Mgmt:                    mgmt.Management().V3(),
		Apps:                    apps.Apps().V1(),
		Admission:               adminReg.Admissionregistration().V1(),
		Project:                 project.Project().V3(),
		Fleet:                   fleet.Fleet().V1alpha1(),
		Provisioning:            provisioning.Provisioning().V1(),
		Catalog:                 helm.Catalog().V1(),
		Batch:                   batch.Batch().V1(),
		ControllerFactory:       controllerFactory,
		ASL:                     asl,
		ClientConfig:            clientConfig,
		MultiClusterManager:     noopMCM{},
		CachedDiscovery:         cache,
		RESTMapper:              restMapper,
		leadership:              leadership,
		RESTClientGetter:        restClientGetter,
		CatalogContentManager:   content,
		HelmOperations:          helmop,
		SystemChartsManager:     systemCharts,
		TunnelAuthorizer:        tunnelAuth,
		TunnelServer:            tunnelServer,
	}, nil
}

type noopMCM struct {
}

func (n noopMCM) ClusterDialer(clusterID string) func(ctx context.Context, network string, address string) (net.Conn, error) {
	return func(ctx context.Context, network string, address string) (net.Conn, error) {
		return nil, fmt.Errorf("no cluster manager")
	}
}

func (n noopMCM) Wait(ctx context.Context) {
}

func (n noopMCM) Start(ctx context.Context) error {
	return nil
}

func (n noopMCM) Middleware(next http.Handler) http.Handler {
	return next
}

func (n noopMCM) K8sClient(clusterName string) (kubernetes.Interface, error) {
	return nil, nil
}

type SimpleRESTClientGetter struct {
	ClientConfig    clientcmd.ClientConfig
	RESTConfig      *rest.Config
	CachedDiscovery discovery.CachedDiscoveryInterface
	RESTMapper      meta.RESTMapper
}

func (s *SimpleRESTClientGetter) ToRawKubeConfigLoader() clientcmd.ClientConfig {
	return s.ClientConfig
}

func (s *SimpleRESTClientGetter) ToRESTConfig() (*rest.Config, error) {
	return s.RESTConfig, nil
}

func (s *SimpleRESTClientGetter) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
	return s.CachedDiscovery, nil
}

func (s *SimpleRESTClientGetter) ToRESTMapper() (meta.RESTMapper, error) {
	return s.RESTMapper, nil
}
<|endoftext|>