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

package utils

import (
	"bufio"
	"io"
	"regexp"
	"strings"

	"github.com/irfansharif/cfilter"
)

const (
	// IPv4RE is a regular expression that will match an IPv4 address.
	IPv4RE = "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"

	// SUBRE is a regular expression that will match on all subdomains once the domain is appended.
	SUBRE = "(([a-zA-Z0-9]{1}|[_a-zA-Z0-9]{1}[_a-zA-Z0-9-]{0,61}[a-zA-Z0-9]{1})[.]{1})+"

	tldList = "https://raw.githubusercontent.com/OWASP/Amass/develop/wordlists/tldlist.txt"
)

var (
	// KnownValidTLDs is a list of valid top-level domains that is maintained by the IANA.
	KnownValidTLDs []string
)

func getTLDList() []string {
	page, err := RequestWebPage(tldList, nil, nil, "", "")
	if err != nil {
		return nil
	}
	return getWordList(strings.NewReader(page))
}

func getWordList(reader io.Reader) []string {
	var words []string

	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		// Get the next word in the list
		w := strings.TrimSpace(scanner.Text())
		if err := scanner.Err(); err == nil && w != "" && !strings.Contains(w, "-") {
			words = append(words, w)
		}
	}
	return words
}

type filterRequest struct {
	String string
	Result chan bool
}

// StringFilter implements an object that performs filtering of strings
// to ensure that only unique items get through the filter.
type StringFilter struct {
	filter   *cfilter.CFilter
	requests chan filterRequest
	quit     chan struct{}
}

// NewStringFilter returns an initialized StringFilter.
func NewStringFilter() *StringFilter {
	sf := &StringFilter{
		filter:   cfilter.New(),
		requests: make(chan filterRequest),
		quit:     make(chan struct{}),
	}
	go sf.processRequests()
	return sf
}

// Duplicate checks if the name provided has been seen before by this filter.
func (sf *StringFilter) Duplicate(s string) bool {
	result := make(chan bool)

	sf.requests <- filterRequest{String: s, Result: result}
	return <-result
}

func (sf *StringFilter) processRequests() {
	for {
		select {
		case <-sf.quit:
			return
		case r := <-sf.requests:
			if sf.filter.Lookup([]byte(r.String)) {
				r.Result <- true
			} else {
				sf.filter.Insert([]byte(r.String))
				r.Result <- false
			}
		}
	}
}

// SubdomainRegex returns a Regexp object initialized to match
// subdomain names that end with the domain provided by the parameter.
func SubdomainRegex(domain string) *regexp.Regexp {
	// Change all the periods into literal periods for the regex
	d := strings.Replace(domain, ".", "[.]", -1)

	return regexp.MustCompile(SUBRE + d)
}

// AnySubdomainRegex returns a Regexp object initialized to match any DNS subdomain name.
func AnySubdomainRegex() *regexp.Regexp {
	return regexp.MustCompile(SUBRE + "[a-zA-Z]{0,61}")
}

// NewUniqueElements removes elements that have duplicates in the original or new elements.
func NewUniqueElements(orig []string, add ...string) []string {
	var n []string

	for _, av := range add {
		found := false
		s := strings.ToLower(av)

		// Check the original slice for duplicates
		for _, ov := range orig {
			if s == strings.ToLower(ov) {
				found = true
				break
			}
		}
		// Check that we didn't already add it in
		if !found {
			for _, nv := range n {
				if s == nv {
					found = true
					break
				}
			}
		}
		// If no duplicates were found, add the entry in
		if !found {
			n = append(n, s)
		}
	}
	return n
}

// UniqueAppend behaves like the Go append, but does not add duplicate elements.
func UniqueAppend(orig []string, add ...string) []string {
	return append(orig, NewUniqueElements(orig, add...)...)
}

// CopyString return a new string variable with the same value as the parameter.
func CopyString(src string) string {
	str := make([]byte, len(src))

	copy(str, src)
	return string(str)
}

// RemoveAsteriskLabel returns the provided DNS name with all asterisk labels removed.
func RemoveAsteriskLabel(s string) string {
	var index int

	labels := strings.Split(s, ".")
	for i := len(labels) - 1; i >= 0; i-- {
		if strings.TrimSpace(labels[i]) == "*" {
			break
		}
		index = i
	}
	if index == len(labels)-1 {
		return ""
	}
	return strings.Join(labels[index:], ".")
}
<commit_msg>added the ReverseString function to utils<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package utils

import (
	"bufio"
	"io"
	"regexp"
	"strings"

	"github.com/irfansharif/cfilter"
)

const (
	// IPv4RE is a regular expression that will match an IPv4 address.
	IPv4RE = "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"

	// SUBRE is a regular expression that will match on all subdomains once the domain is appended.
	SUBRE = "(([a-zA-Z0-9]{1}|[_a-zA-Z0-9]{1}[_a-zA-Z0-9-]{0,61}[a-zA-Z0-9]{1})[.]{1})+"

	tldList = "https://raw.githubusercontent.com/OWASP/Amass/develop/wordlists/tldlist.txt"
)

var (
	// KnownValidTLDs is a list of valid top-level domains that is maintained by the IANA.
	KnownValidTLDs []string
)

func getTLDList() []string {
	page, err := RequestWebPage(tldList, nil, nil, "", "")
	if err != nil {
		return nil
	}
	return getWordList(strings.NewReader(page))
}

func getWordList(reader io.Reader) []string {
	var words []string

	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		// Get the next word in the list
		w := strings.TrimSpace(scanner.Text())
		if err := scanner.Err(); err == nil && w != "" && !strings.Contains(w, "-") {
			words = append(words, w)
		}
	}
	return words
}

type filterRequest struct {
	String string
	Result chan bool
}

// StringFilter implements an object that performs filtering of strings
// to ensure that only unique items get through the filter.
type StringFilter struct {
	filter   *cfilter.CFilter
	requests chan filterRequest
	quit     chan struct{}
}

// NewStringFilter returns an initialized StringFilter.
func NewStringFilter() *StringFilter {
	sf := &StringFilter{
		filter:   cfilter.New(),
		requests: make(chan filterRequest),
		quit:     make(chan struct{}),
	}
	go sf.processRequests()
	return sf
}

// Duplicate checks if the name provided has been seen before by this filter.
func (sf *StringFilter) Duplicate(s string) bool {
	result := make(chan bool)

	sf.requests <- filterRequest{String: s, Result: result}
	return <-result
}

func (sf *StringFilter) processRequests() {
	for {
		select {
		case <-sf.quit:
			return
		case r := <-sf.requests:
			if sf.filter.Lookup([]byte(r.String)) {
				r.Result <- true
			} else {
				sf.filter.Insert([]byte(r.String))
				r.Result <- false
			}
		}
	}
}

// SubdomainRegex returns a Regexp object initialized to match
// subdomain names that end with the domain provided by the parameter.
func SubdomainRegex(domain string) *regexp.Regexp {
	// Change all the periods into literal periods for the regex
	d := strings.Replace(domain, ".", "[.]", -1)

	return regexp.MustCompile(SUBRE + d)
}

// AnySubdomainRegex returns a Regexp object initialized to match any DNS subdomain name.
func AnySubdomainRegex() *regexp.Regexp {
	return regexp.MustCompile(SUBRE + "[a-zA-Z]{0,61}")
}

// NewUniqueElements removes elements that have duplicates in the original or new elements.
func NewUniqueElements(orig []string, add ...string) []string {
	var n []string

	for _, av := range add {
		found := false
		s := strings.ToLower(av)

		// Check the original slice for duplicates
		for _, ov := range orig {
			if s == strings.ToLower(ov) {
				found = true
				break
			}
		}
		// Check that we didn't already add it in
		if !found {
			for _, nv := range n {
				if s == nv {
					found = true
					break
				}
			}
		}
		// If no duplicates were found, add the entry in
		if !found {
			n = append(n, s)
		}
	}
	return n
}

// UniqueAppend behaves like the Go append, but does not add duplicate elements.
func UniqueAppend(orig []string, add ...string) []string {
	return append(orig, NewUniqueElements(orig, add...)...)
}

// CopyString return a new string variable with the same value as the parameter.
func CopyString(src string) string {
	str := make([]byte, len(src))

	copy(str, src)
	return string(str)
}

// RemoveAsteriskLabel returns the provided DNS name with all asterisk labels removed.
func RemoveAsteriskLabel(s string) string {
	var index int

	labels := strings.Split(s, ".")
	for i := len(labels) - 1; i >= 0; i-- {
		if strings.TrimSpace(labels[i]) == "*" {
			break
		}
		index = i
	}
	if index == len(labels)-1 {
		return ""
	}
	return strings.Join(labels[index:], ".")
}

// ReverseString returns the characters of the argument string in reverse order.
func ReverseString(s string) string {
	chrs := []rune(s)

	end := len(chrs) / 2
	for i, j := 0, len(chrs)-1; i < end; i, j = i+1, j-1 {
		chrs[i], chrs[j] = chrs[j], chrs[i]
	}
	return string(chrs)
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Tekton 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 tektonconfig

import (
	"context"
	"os"
	"time"

	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
	"github.com/tektoncd/operator/pkg/client/clientset/versioned"
	"github.com/tektoncd/operator/pkg/reconciler/common"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"knative.dev/pkg/logging"
)

const (
	// RetryInterval specifies the time between two polls.
	RetryInterval = 10 * time.Second

	// RetryTimeout specifies the timeout for the function PollImmediate to
	// reach a certain status.
	RetryTimeout = 5 * time.Minute

	// DefaultCRName specifies the default targetnamespaceto be used
	// in autocreated TektonConfig instance
	DefaultCRName = "config"
)

type tektonConfig struct {
	operatorClientSet versioned.Interface
	kubeClientSet     kubernetes.Interface
	namespace         string
}

func newTektonConfig(operatorClientSet versioned.Interface, kubeClientSet kubernetes.Interface) tektonConfig {

	return tektonConfig{
		operatorClientSet: operatorClientSet,
		kubeClientSet:     kubeClientSet,
		namespace:         os.Getenv("DEFAULT_TARGET_NAMESPACE"),
	}
}

// try to ensure an instance of TektonConfig exists
// if there is an error log error,and continue (an instance of TektonConfig will
// then need to be created by the user to get Tekton Pipelines components installed
func (tc tektonConfig) ensureInstance(ctx context.Context) {
	logger := logging.FromContext(ctx)
	logger.Debug("ensuring tektonconfig instance")

	waitErr := wait.PollImmediate(RetryInterval, RetryTimeout, func() (bool, error) {
		//note: the code in this block will be retired until
		// an error is returned, or
		// 'true' is returned, or
		// timeout
		instance, err := tc.operatorClientSet.
			OperatorV1alpha1().
			TektonConfigs().Get(context.TODO(), DefaultCRName, metav1.GetOptions{})
		if err == nil {
			if !instance.GetDeletionTimestamp().IsZero() {
				// log deleting timestamp error and retry
				logger.Errorf("deletionTimestamp is set on existing Tektonconfig instance, Name: %w", instance.GetName())
				return false, nil
			}
			return true, nil
		}
		if !apierrs.IsNotFound(err) {
			//log error and retry
			logger.Errorf("error getting Tektonconfig, Name: ", instance.GetName())
			return false, nil
		}
		err = tc.createInstance(ctx)
		if err != nil {
			//log error and retry
			logger.Errorf("error creating Tektonconfig instance, Name: ", instance.GetName())
			return false, nil
		}
		// even if there is no error after create,
		// loop again to ensure the create is successful with a 'get; api call
		return false, nil
	})
	if waitErr != nil {
		// log error and continue
		logger.Error("error ensuring instance of tektonconfig, check retry logs above for more details, %w", waitErr)
		logger.Infof("an instance of TektonConfig need to be created by the user to get Pipelines components installed")
	}
}

func (tc tektonConfig) createInstance(ctx context.Context) error {
	tcCR := &v1alpha1.TektonConfig{
		ObjectMeta: metav1.ObjectMeta{
			Name: common.ConfigResourceName,
		},
		Spec: v1alpha1.TektonConfigSpec{
			Profile: common.ProfileAll,
			CommonSpec: v1alpha1.CommonSpec{
				TargetNamespace: tc.namespace,
			},
		},
	}
	tcCR.SetDefaults(ctx)
	_, err := tc.operatorClientSet.OperatorV1alpha1().
		TektonConfigs().Create(ctx, tcCR, metav1.CreateOptions{})
	return err
}
<commit_msg>Removes deletion timestamp check in Autocreation of TektonConfig<commit_after>/*
Copyright 2021 The Tekton 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 tektonconfig

import (
	"context"
	"os"
	"time"

	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
	"github.com/tektoncd/operator/pkg/client/clientset/versioned"
	"github.com/tektoncd/operator/pkg/reconciler/common"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"knative.dev/pkg/logging"
)

const (
	// RetryInterval specifies the time between two polls.
	RetryInterval = 10 * time.Second

	// RetryTimeout specifies the timeout for the function PollImmediate to
	// reach a certain status.
	RetryTimeout = 5 * time.Minute

	// DefaultCRName specifies the default targetnamespaceto be used
	// in autocreated TektonConfig instance
	DefaultCRName = "config"
)

type tektonConfig struct {
	operatorClientSet versioned.Interface
	kubeClientSet     kubernetes.Interface
	namespace         string
}

func newTektonConfig(operatorClientSet versioned.Interface, kubeClientSet kubernetes.Interface) tektonConfig {

	return tektonConfig{
		operatorClientSet: operatorClientSet,
		kubeClientSet:     kubeClientSet,
		namespace:         os.Getenv("DEFAULT_TARGET_NAMESPACE"),
	}
}

// try to ensure an instance of TektonConfig exists
// if there is an error log error,and continue (an instance of TektonConfig will
// then need to be created by the user to get Tekton Pipelines components installed
func (tc tektonConfig) ensureInstance(ctx context.Context) {
	logger := logging.FromContext(ctx)
	logger.Debug("ensuring tektonconfig instance")

	waitErr := wait.PollImmediate(RetryInterval, RetryTimeout, func() (bool, error) {
		//note: the code in this block will be retired until
		// an error is returned, or
		// 'true' is returned, or
		// timeout
		instance, err := tc.operatorClientSet.
			OperatorV1alpha1().
			TektonConfigs().Get(context.TODO(), DefaultCRName, metav1.GetOptions{})
		if err == nil {
			return true, nil
		}
		if !apierrs.IsNotFound(err) {
			//log error and retry
			logger.Errorf("error getting Tektonconfig, Name: ", instance.GetName())
			return false, nil
		}
		err = tc.createInstance(ctx)
		if err != nil {
			//log error and retry
			logger.Errorf("error creating Tektonconfig instance, Name: ", instance.GetName())
			return false, nil
		}
		// even if there is no error after create,
		// loop again to ensure the create is successful with a 'get; api call
		return false, nil
	})
	if waitErr != nil {
		// log error and continue
		logger.Error("error ensuring instance of tektonconfig, check retry logs above for more details, %w", waitErr)
		logger.Infof("an instance of TektonConfig need to be created by the user to get Pipelines components installed")
	}
}

func (tc tektonConfig) createInstance(ctx context.Context) error {
	tcCR := &v1alpha1.TektonConfig{
		ObjectMeta: metav1.ObjectMeta{
			Name: common.ConfigResourceName,
		},
		Spec: v1alpha1.TektonConfigSpec{
			Profile: common.ProfileAll,
			CommonSpec: v1alpha1.CommonSpec{
				TargetNamespace: tc.namespace,
			},
		},
	}
	tcCR.SetDefaults(ctx)
	_, err := tc.operatorClientSet.OperatorV1alpha1().
		TektonConfigs().Create(ctx, tcCR, metav1.CreateOptions{})
	return err
}
<|endoftext|>


<commit_before>/*
Copyright 2016 Skippbox, Ltd.
Copyright 2017 André Cruz

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 handlers

import (
	"fmt"
	"strings"

	"log"

	"github.com/spf13/viper"

	"github.com/nlopes/slack"

	"github.com/edevil/kubewatch/pkg/event"
)

var slackColors = map[string]string{
	"Normal":  "good",
	"Warning": "warning",
	"Danger":  "danger",
}

var slackErrMsg = `
%s

You need to set both slack token and channel for slack notify
in your configuration file.

`

// Slack handler implements handler.Handler interface,
// Notify event to slack channel
type Slack struct {
	Token   string
	Channel string
}

// Init prepares slack configuration
func (s *Slack) Init(c *viper.Viper) error {
	s.Token = c.GetString("token")
	s.Channel = c.GetString("channel")

	if s.Token == "" || s.Channel == "" {
		return fmt.Errorf(slackErrMsg, "Missing slack token or channel")
	}

	return nil
}

// ObjectCreated - implementation of Handler interface
func (s *Slack) ObjectCreated(obj interface{}) {
	notifySlack(s, obj, "created", "")
}

// ObjectDeleted - implementation of Handler interface
func (s *Slack) ObjectDeleted(obj interface{}) {
	notifySlack(s, obj, "deleted", "")
}

// ObjectUpdated - implementation of Handler interface
func (s *Slack) ObjectUpdated(oldObj, newObj interface{}, changes []string) {
	notifySlack(s, newObj, "updated", strings.Join(changes, ", "))
}

func notifySlack(s *Slack, obj interface{}, action string, extra string) {
	e := event.New(obj, action)
	api := slack.New(s.Token)
	params := slack.PostMessageParameters{}
	attachment := prepareSlackAttachment(e)

	params.Attachments = []slack.Attachment{attachment}
	params.AsUser = true
	channelID, timestamp, err := api.PostMessage(s.Channel, extra, params)
	if err != nil {
		log.Printf("%s\n", err)
		return
	}

	log.Printf("Message successfully sent to channel %s at %s", channelID, timestamp)
}

func prepareSlackAttachment(e event.Event) slack.Attachment {
	msg := fmt.Sprintf(
		"A %s in namespace %s has been %s: %s",
		e.Kind,
		e.Namespace,
		e.Reason,
		e.Name,
	)

	attachment := slack.Attachment{
		Fields: []slack.AttachmentField{
			slack.AttachmentField{
				Title: "kubewatch",
				Value: msg,
			},
		},
	}

	if color, ok := slackColors[e.Status]; ok {
		attachment.Color = color
	}

	attachment.MarkdownIn = []string{"fields"}

	return attachment
}

func init() {
	HandlerMap["slack"] = &Slack{}
}
<commit_msg>Try to improve pasting of large text<commit_after>/*
Copyright 2016 Skippbox, Ltd.
Copyright 2017 André Cruz

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 handlers

import (
	"fmt"
	"strings"

	"log"

	"github.com/spf13/viper"

	"github.com/nlopes/slack"

	"github.com/edevil/kubewatch/pkg/event"
)

var slackColors = map[string]string{
	"Normal":  "good",
	"Warning": "warning",
	"Danger":  "danger",
}

var slackErrMsg = `
%s

You need to set both slack token and channel for slack notify
in your configuration file.

`

// Slack handler implements handler.Handler interface,
// Notify event to slack channel
type Slack struct {
	Token   string
	Channel string
}

// Init prepares slack configuration
func (s *Slack) Init(c *viper.Viper) error {
	s.Token = c.GetString("token")
	s.Channel = c.GetString("channel")

	if s.Token == "" || s.Channel == "" {
		return fmt.Errorf(slackErrMsg, "Missing slack token or channel")
	}

	return nil
}

// ObjectCreated - implementation of Handler interface
func (s *Slack) ObjectCreated(obj interface{}) {
	notifySlack(s, obj, "created", "")
}

// ObjectDeleted - implementation of Handler interface
func (s *Slack) ObjectDeleted(obj interface{}) {
	notifySlack(s, obj, "deleted", "")
}

// ObjectUpdated - implementation of Handler interface
func (s *Slack) ObjectUpdated(oldObj, newObj interface{}, changes []string) {
	var extra string
	if len(changes) > 0 {
		extra = "{{{" + strings.Join(changes, ", ") + "}}}"
	}
	notifySlack(s, newObj, "updated", extra)
}

func notifySlack(s *Slack, obj interface{}, action string, extra string) {
	e := event.New(obj, action)
	api := slack.New(s.Token)
	params := slack.PostMessageParameters{}
	attachment := prepareSlackAttachment(e)

	params.Attachments = []slack.Attachment{attachment}
	params.AsUser = true
	channelID, timestamp, err := api.PostMessage(s.Channel, extra, params)
	if err != nil {
		log.Printf("%s\n", err)
		return
	}

	log.Printf("Message successfully sent to channel %s at %s", channelID, timestamp)
}

func prepareSlackAttachment(e event.Event) slack.Attachment {
	msg := fmt.Sprintf(
		"A %s in namespace %s has been %s: %s",
		e.Kind,
		e.Namespace,
		e.Reason,
		e.Name,
	)

	attachment := slack.Attachment{
		Fields: []slack.AttachmentField{
			slack.AttachmentField{
				Title: "kubewatch",
				Value: msg,
			},
		},
	}

	if color, ok := slackColors[e.Status]; ok {
		attachment.Color = color
	}

	attachment.MarkdownIn = []string{"fields"}

	return attachment
}

func init() {
	HandlerMap["slack"] = &Slack{}
}
<|endoftext|>


<commit_before>package helm

import (
	"fmt"
	"github.com/Aptomi/aptomi/pkg/slinga/event"
	"github.com/Aptomi/aptomi/pkg/slinga/lang"
	"github.com/Aptomi/aptomi/pkg/slinga/util"
	"gopkg.in/yaml.v2"
	"k8s.io/helm/pkg/helm"
	"k8s.io/kubernetes/pkg/api"
	k8serrors "k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/labels"
	"strings"
)

var helmCodeTypes = []string{"helm", "aptomi/code/kubernetes-helm"}

// GetSupportedCodeTypes returns all code types for which this plugin is registered to
func (p *Plugin) GetSupportedCodeTypes() []string {
	return helmCodeTypes
}

// Create creates component instance in the cloud by deploying a helm chart
func (p *Plugin) Create(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) error {
	return p.createOrUpdate(cluster, deployName, params, eventLog, true)
}

// Update updates component instance in the cloud by updating parameters of a helm chart
func (p *Plugin) Update(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) error {
	return p.createOrUpdate(cluster, deployName, params, eventLog, true)
}

func (p *Plugin) createOrUpdate(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log, create bool) error {
	cache, err := p.getCache(cluster, eventLog)
	if err != nil {
		return err
	}

	releaseName := helmReleaseName(deployName)
	chartName, err := helmChartName(params)
	if err != nil {
		return err
	}

	helmClient := cache.newHelmClient(cluster)

	chartPath, err := getValidChartPath(chartName)
	if err != nil {
		return err
	}

	helmParams, err := yaml.Marshal(params)
	if err != nil {
		return err
	}

	if create {
		exists, errRelease := findHelmRelease(helmClient, releaseName)
		if errRelease != nil {
			return fmt.Errorf("Error while looking for Helm release %s: %s", releaseName, errRelease)
		}

		if exists {
			// If a release already exists, let's just go ahead and update it
			eventLog.WithFields(event.Fields{}).Infof("Release '%s' already exists. Updating it", releaseName)
		}

		eventLog.WithFields(event.Fields{
			"release": releaseName,
			"chart":   chartName,
			"path":    chartPath,
			"params":  string(helmParams),
		}).Infof("Installing Helm release '%s', chart '%s'", releaseName, chartName)

		_, err = helmClient.InstallRelease(chartPath, cluster.Config.Namespace, helm.ReleaseName(releaseName), helm.ValueOverrides(helmParams), helm.InstallReuseName(true))
	} else {
		eventLog.WithFields(event.Fields{
			"release": releaseName,
			"chart":   chartName,
			"path":    chartPath,
			"params":  string(helmParams),
		}).Infof("Updating Helm release '%s', chart '%s'", releaseName, chartName)

		_, err = helmClient.UpdateRelease(releaseName, chartPath, helm.UpdateValueOverrides(helmParams))
	}

	return err
}

// Destroy for Plugin runs "helm delete" for the corresponding helm chart
func (p *Plugin) Destroy(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) error {
	cache, err := p.getCache(cluster, eventLog)
	if err != nil {
		return err
	}

	releaseName := helmReleaseName(deployName)

	helmClient := cache.newHelmClient(cluster)

	eventLog.WithFields(event.Fields{
		"release": releaseName,
	}).Infof("Deleting Helm release '%s'", releaseName)

	_, err = helmClient.DeleteRelease(releaseName, helm.DeletePurge(true))
	return err
}

// Endpoints returns map from port type to url for all services of the current chart
func (p *Plugin) Endpoints(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) (map[string]string, error) {
	cache, err := p.getCache(cluster, eventLog)
	if err != nil {
		return nil, err
	}

	_, client, err := cache.newKubeClient(cluster, eventLog)
	if err != nil {
		return nil, err
	}

	coreClient := client.Core()

	releaseName := helmReleaseName(deployName)
	chartName, err := helmChartName(params)
	if err != nil {
		return nil, err
	}

	selector := labels.Set{"release": releaseName, "chart": chartName}.AsSelector()
	options := api.ListOptions{LabelSelector: selector}

	endpoints := make(map[string]string)

	// Check all corresponding services
	services, err := coreClient.Services(cluster.Config.Namespace).List(options)
	if err != nil {
		return nil, err
	}

	kubeHost, err := cache.getKubeExternalAddress(cluster, eventLog)
	if err != nil {
		return nil, err
	}

	for _, service := range services.Items {
		if service.Spec.Type == "NodePort" {
			for _, port := range service.Spec.Ports {
				sURL := fmt.Sprintf("%s:%d", kubeHost, port.NodePort)

				// todo(slukjanov): could we somehow detect real schema? I think no :(
				if util.StringContainsAny(port.Name, "https") {
					sURL = "https://" + sURL
				} else if util.StringContainsAny(port.Name, "ui", "rest", "http", "grafana") {
					sURL = "http://" + sURL
				}

				endpoints[port.Name] = sURL
			}
		}
	}

	// Find Istio Ingress service (how ingress itself exposed)
	service, err := coreClient.Services(cluster.Config.Namespace).Get("istio-ingress")
	if err != nil {
		// return if there is no Istio deployed
		if k8serrors.IsNotFound(err) {
			return endpoints, nil
		}
		return nil, err
	}

	istioIngress := "<unresolved>"
	if service.Spec.Type == "NodePort" {
		for _, port := range service.Spec.Ports {
			if port.Name == "http" {
				istioIngress = fmt.Sprintf("%s:%d", kubeHost, port.NodePort)
			}
		}
	}

	// Check all corresponding istio ingresses
	ingresses, err := client.Extensions().Ingresses(cluster.Config.Namespace).List(options)
	if err != nil {
		return nil, err
	}

	// todo(slukjanov): support more then one ingress / rule / path
	for _, ingress := range ingresses.Items {
		if class, ok := ingress.Annotations["kubernetes.io/ingress.class"]; !ok || class != "istio" {
			continue
		}
		for _, rule := range ingress.Spec.Rules {
			for _, path := range rule.HTTP.Paths {
				pathStr := strings.Trim(path.Path, ".*")

				if rule.Host == "" {
					endpoints["ingress"] = "http://" + istioIngress + pathStr
				} else {
					endpoints["ingress"] = "http://" + rule.Host + pathStr
				}
			}
		}
	}

	return endpoints, nil
}
<commit_msg>Fix helm plugin logic in case of create action on existing release<commit_after>package helm

import (
	"fmt"
	"github.com/Aptomi/aptomi/pkg/slinga/event"
	"github.com/Aptomi/aptomi/pkg/slinga/lang"
	"github.com/Aptomi/aptomi/pkg/slinga/util"
	"gopkg.in/yaml.v2"
	"k8s.io/helm/pkg/helm"
	"k8s.io/kubernetes/pkg/api"
	k8serrors "k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/labels"
	"strings"
)

var helmCodeTypes = []string{"helm", "aptomi/code/kubernetes-helm"}

// GetSupportedCodeTypes returns all code types for which this plugin is registered to
func (p *Plugin) GetSupportedCodeTypes() []string {
	return helmCodeTypes
}

// Create creates component instance in the cloud by deploying a helm chart
func (p *Plugin) Create(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) error {
	return p.createOrUpdate(cluster, deployName, params, eventLog, true)
}

// Update updates component instance in the cloud by updating parameters of a helm chart
func (p *Plugin) Update(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) error {
	return p.createOrUpdate(cluster, deployName, params, eventLog, true)
}

func (p *Plugin) createOrUpdate(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log, create bool) error {
	cache, err := p.getCache(cluster, eventLog)
	if err != nil {
		return err
	}

	releaseName := helmReleaseName(deployName)
	chartName, err := helmChartName(params)
	if err != nil {
		return err
	}

	helmClient := cache.newHelmClient(cluster)

	chartPath, err := getValidChartPath(chartName)
	if err != nil {
		return err
	}

	helmParams, err := yaml.Marshal(params)
	if err != nil {
		return err
	}

	if create {
		exists, errRelease := findHelmRelease(helmClient, releaseName)
		if errRelease != nil {
			return fmt.Errorf("Error while looking for Helm release %s: %s", releaseName, errRelease)
		}

		if exists {
			// If a release already exists, let's just go ahead and update it
			eventLog.WithFields(event.Fields{}).Infof("Release '%s' already exists. Updating it", releaseName)
		} else {
			eventLog.WithFields(event.Fields{
				"release": releaseName,
				"chart":   chartName,
				"path":    chartPath,
				"params":  string(helmParams),
			}).Infof("Installing Helm release '%s', chart '%s', cluster: '%s'", releaseName, chartName, cluster.Name)

			_, err = helmClient.InstallRelease(chartPath, cluster.Config.Namespace, helm.ReleaseName(releaseName), helm.ValueOverrides(helmParams), helm.InstallReuseName(true))

			return err
		}
	}

	eventLog.WithFields(event.Fields{
		"release": releaseName,
		"chart":   chartName,
		"path":    chartPath,
		"params":  string(helmParams),
	}).Infof("Updating Helm release '%s', chart '%s', cluster: '%s'", releaseName, chartName, cluster.Name)

	_, err = helmClient.UpdateRelease(releaseName, chartPath, helm.UpdateValueOverrides(helmParams))

	return err
}

// Destroy for Plugin runs "helm delete" for the corresponding helm chart
func (p *Plugin) Destroy(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) error {
	cache, err := p.getCache(cluster, eventLog)
	if err != nil {
		return err
	}

	releaseName := helmReleaseName(deployName)

	helmClient := cache.newHelmClient(cluster)

	eventLog.WithFields(event.Fields{
		"release": releaseName,
	}).Infof("Deleting Helm release '%s'", releaseName)

	_, err = helmClient.DeleteRelease(releaseName, helm.DeletePurge(true))
	return err
}

// Endpoints returns map from port type to url for all services of the current chart
func (p *Plugin) Endpoints(cluster *lang.Cluster, deployName string, params util.NestedParameterMap, eventLog *event.Log) (map[string]string, error) {
	cache, err := p.getCache(cluster, eventLog)
	if err != nil {
		return nil, err
	}

	_, client, err := cache.newKubeClient(cluster, eventLog)
	if err != nil {
		return nil, err
	}

	coreClient := client.Core()

	releaseName := helmReleaseName(deployName)
	chartName, err := helmChartName(params)
	if err != nil {
		return nil, err
	}

	selector := labels.Set{"release": releaseName, "chart": chartName}.AsSelector()
	options := api.ListOptions{LabelSelector: selector}

	endpoints := make(map[string]string)

	// Check all corresponding services
	services, err := coreClient.Services(cluster.Config.Namespace).List(options)
	if err != nil {
		return nil, err
	}

	kubeHost, err := cache.getKubeExternalAddress(cluster, eventLog)
	if err != nil {
		return nil, err
	}

	for _, service := range services.Items {
		if service.Spec.Type == "NodePort" {
			for _, port := range service.Spec.Ports {
				sURL := fmt.Sprintf("%s:%d", kubeHost, port.NodePort)

				// todo(slukjanov): could we somehow detect real schema? I think no :(
				if util.StringContainsAny(port.Name, "https") {
					sURL = "https://" + sURL
				} else if util.StringContainsAny(port.Name, "ui", "rest", "http", "grafana") {
					sURL = "http://" + sURL
				}

				endpoints[port.Name] = sURL
			}
		}
	}

	// Find Istio Ingress service (how ingress itself exposed)
	service, err := coreClient.Services(cluster.Config.Namespace).Get("istio-ingress")
	if err != nil {
		// return if there is no Istio deployed
		if k8serrors.IsNotFound(err) {
			return endpoints, nil
		}
		return nil, err
	}

	istioIngress := "<unresolved>"
	if service.Spec.Type == "NodePort" {
		for _, port := range service.Spec.Ports {
			if port.Name == "http" {
				istioIngress = fmt.Sprintf("%s:%d", kubeHost, port.NodePort)
			}
		}
	}

	// Check all corresponding istio ingresses
	ingresses, err := client.Extensions().Ingresses(cluster.Config.Namespace).List(options)
	if err != nil {
		return nil, err
	}

	// todo(slukjanov): support more then one ingress / rule / path
	for _, ingress := range ingresses.Items {
		if class, ok := ingress.Annotations["kubernetes.io/ingress.class"]; !ok || class != "istio" {
			continue
		}
		for _, rule := range ingress.Spec.Rules {
			for _, path := range rule.HTTP.Paths {
				pathStr := strings.Trim(path.Path, ".*")

				if rule.Host == "" {
					endpoints["ingress"] = "http://" + istioIngress + pathStr
				} else {
					endpoints["ingress"] = "http://" + rule.Host + pathStr
				}
			}
		}
	}

	return endpoints, nil
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package service

import (
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/hyperledger/fabric/protos/ledger/rwset"

	"github.com/hyperledger/fabric/core/deliverservice"
	"github.com/hyperledger/fabric/core/deliverservice/blocksprovider"
	"github.com/hyperledger/fabric/core/ledger"
	"github.com/hyperledger/fabric/core/transientstore"
	"github.com/hyperledger/fabric/gossip/api"
	"github.com/hyperledger/fabric/gossip/election"
	"github.com/hyperledger/fabric/gossip/state"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
)

type transientStoreMock struct {
}

func (*transientStoreMock) PurgeByHeight(maxBlockNumToRetain uint64) error {
	return nil
}

func (*transientStoreMock) Persist(txid string, blockHeight uint64, privateSimulationResults *rwset.TxPvtReadWriteSet) error {
	panic("implement me")
}

func (*transientStoreMock) GetTxPvtRWSetByTxid(txid string, filter ledger.PvtNsCollFilter) (transientstore.RWSetScanner, error) {
	panic("implement me")
}

func (*transientStoreMock) PurgeByTxids(txids []string) error {
	panic("implement me")
}

type embeddingDeliveryService struct {
	deliverclient.DeliverService
	startSignal sync.WaitGroup
	stopSignal  sync.WaitGroup
}

func newEmbeddingDeliveryService(ds deliverclient.DeliverService) *embeddingDeliveryService {
	eds := &embeddingDeliveryService{
		DeliverService: ds,
	}
	eds.startSignal.Add(1)
	eds.stopSignal.Add(1)
	return eds
}

func (eds *embeddingDeliveryService) waitForDeliveryServiceActivation() {
	eds.startSignal.Wait()
}

func (eds *embeddingDeliveryService) waitForDeliveryServiceTermination() {
	eds.stopSignal.Wait()
}

func (eds *embeddingDeliveryService) StartDeliverForChannel(chainID string, ledgerInfo blocksprovider.LedgerInfo, finalizer func()) error {
	eds.startSignal.Done()
	return eds.DeliverService.StartDeliverForChannel(chainID, ledgerInfo, finalizer)
}

func (eds *embeddingDeliveryService) StopDeliverForChannel(chainID string) error {
	eds.stopSignal.Done()
	return eds.DeliverService.StopDeliverForChannel(chainID)
}

func (eds *embeddingDeliveryService) Stop() {
	eds.DeliverService.Stop()
}

type embeddingDeliveryServiceFactory struct {
	DeliveryServiceFactory
}

func (edsf *embeddingDeliveryServiceFactory) Service(g GossipService, endpoints []string, mcs api.MessageCryptoService) (deliverclient.DeliverService, error) {
	ds, _ := edsf.DeliveryServiceFactory.Service(g, endpoints, mcs)
	return newEmbeddingDeliveryService(ds), nil
}

func TestLeaderYield(t *testing.T) {
	t.Skip()
	// Scenario: Spawn 2 peers and wait for the first one to be the leader
	// There isn't any orderer present so the leader peer won't be able to
	// connect to the orderer, and should relinquish its leadership after a while.
	// Make sure the other peer declares itself as the leader soon after.
	viper.Set("peer.deliveryclient.reconnectTotalTimeThreshold", time.Second*5)
	viper.Set("peer.gossip.useLeaderElection", true)
	viper.Set("peer.gossip.orgLeader", false)
	n := 2
	portPrefix := 30000
	gossips := startPeers(t, n, portPrefix)
	defer stopPeers(gossips)
	channelName := "channelA"
	peerIndexes := []int{0, 1}
	// Add peers to the channel
	addPeersToChannel(t, n, portPrefix, channelName, gossips, peerIndexes)
	// Prime the membership view of the peers
	waitForFullMembership(t, gossips, n, time.Second*30, time.Second*2)
	mcs := &naiveCryptoService{}
	// Helper function that creates a gossipService instance
	newGossipService := func(i int) *gossipServiceImpl {
		peerIdentity := api.PeerIdentityType(fmt.Sprintf("localhost:%d", portPrefix+i))
		gs := &gossipServiceImpl{
			mcs:             mcs,
			gossipSvc:       gossips[i],
			chains:          make(map[string]state.GossipStateProvider),
			leaderElection:  make(map[string]election.LeaderElectionService),
			deliveryFactory: &embeddingDeliveryServiceFactory{&deliveryFactoryImpl{}},
			peerIdentity:    peerIdentity,
			secAdv:          &secAdvMock{},
		}
		gossipServiceInstance = gs
		gs.InitializeChannel(channelName, []string{"localhost:7050"}, Support{
			Committer: &mockLedgerInfo{1},
			Store:     &transientStoreMock{},
		})
		return gs
	}

	p0 := newGossipService(0)
	p1 := newGossipService(1)

	// Returns index of the leader or -1 if no leader elected
	getLeader := func() int {
		p0.lock.RLock()
		p1.lock.RLock()
		defer p0.lock.RUnlock()
		defer p1.lock.RUnlock()

		if p0.leaderElection[channelName].IsLeader() {
			// Ensure p1 isn't a leader at the same time
			assert.False(t, p1.leaderElection[channelName].IsLeader())
			return 0
		}
		if p1.leaderElection[channelName].IsLeader() {
			return 1
		}
		return -1
	}

	ds0 := p0.deliveryService[channelName].(*embeddingDeliveryService)
	ds1 := p1.deliveryService[channelName].(*embeddingDeliveryService)

	// Wait for p0 to connect to the ordering service
	ds0.waitForDeliveryServiceActivation()
	t.Log("p0 started its delivery service")
	// Ensure it's a leader
	assert.Equal(t, 0, getLeader())
	// Wait for p0 to lose its leadership
	ds0.waitForDeliveryServiceTermination()
	t.Log("p0 stopped its delivery service")
	// Ensure there is no leader
	assert.Equal(t, -1, getLeader())
	// Wait for p1 to take over
	ds1.waitForDeliveryServiceActivation()
	t.Log("p1 started its delivery service")
	// Ensure it's a leader now
	assert.Equal(t, 1, getLeader())
	p0.chains[channelName].Stop()
	p1.chains[channelName].Stop()
	p0.deliveryService[channelName].Stop()
	p1.deliveryService[channelName].Stop()
}
<commit_msg>[FAB-5503] Reintroduce disabled test<commit_after>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package service

import (
	"sync"
	"testing"
	"time"

	"github.com/hyperledger/fabric/core/deliverservice"
	"github.com/hyperledger/fabric/core/deliverservice/blocksprovider"
	"github.com/hyperledger/fabric/core/ledger"
	"github.com/hyperledger/fabric/core/transientstore"
	"github.com/hyperledger/fabric/gossip/api"
	"github.com/hyperledger/fabric/gossip/util"
	"github.com/hyperledger/fabric/protos/ledger/rwset"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
)

type transientStoreMock struct {
}

func (*transientStoreMock) PurgeByHeight(maxBlockNumToRetain uint64) error {
	return nil
}

func (*transientStoreMock) Persist(txid string, blockHeight uint64, privateSimulationResults *rwset.TxPvtReadWriteSet) error {
	panic("implement me")
}

func (*transientStoreMock) GetTxPvtRWSetByTxid(txid string, filter ledger.PvtNsCollFilter) (transientstore.RWSetScanner, error) {
	panic("implement me")
}

func (*transientStoreMock) PurgeByTxids(txids []string) error {
	panic("implement me")
}

type embeddingDeliveryService struct {
	startOnce sync.Once
	stopOnce  sync.Once
	deliverclient.DeliverService
	startSignal sync.WaitGroup
	stopSignal  sync.WaitGroup
}

func newEmbeddingDeliveryService(ds deliverclient.DeliverService) *embeddingDeliveryService {
	eds := &embeddingDeliveryService{
		DeliverService: ds,
	}
	eds.startSignal.Add(1)
	eds.stopSignal.Add(1)
	return eds
}

func (eds *embeddingDeliveryService) waitForDeliveryServiceActivation() {
	eds.startSignal.Wait()
}

func (eds *embeddingDeliveryService) waitForDeliveryServiceTermination() {
	eds.stopSignal.Wait()
}

func (eds *embeddingDeliveryService) StartDeliverForChannel(chainID string, ledgerInfo blocksprovider.LedgerInfo, finalizer func()) error {
	eds.startOnce.Do(func() {
		eds.startSignal.Done()
	})
	return eds.DeliverService.StartDeliverForChannel(chainID, ledgerInfo, finalizer)
}

func (eds *embeddingDeliveryService) StopDeliverForChannel(chainID string) error {
	eds.stopOnce.Do(func() {
		eds.stopSignal.Done()
	})
	return eds.DeliverService.StopDeliverForChannel(chainID)
}

func (eds *embeddingDeliveryService) Stop() {
	eds.DeliverService.Stop()
}

type embeddingDeliveryServiceFactory struct {
	DeliveryServiceFactory
}

func (edsf *embeddingDeliveryServiceFactory) Service(g GossipService, endpoints []string, mcs api.MessageCryptoService) (deliverclient.DeliverService, error) {
	ds, _ := edsf.DeliveryServiceFactory.Service(g, endpoints, mcs)
	return newEmbeddingDeliveryService(ds), nil
}

func TestLeaderYield(t *testing.T) {
	// Scenario: Spawn 2 peers and wait for the first one to be the leader
	// There isn't any orderer present so the leader peer won't be able to
	// connect to the orderer, and should relinquish its leadership after a while.
	// Make sure the other peer declares itself as the leader soon after.
	takeOverMaxTimeout := time.Minute
	viper.Set("peer.gossip.election.leaderAliveThreshold", time.Second*5)
	viper.Set("peer.deliveryclient.reconnectTotalTimeThreshold", time.Second*5)
	viper.Set("peer.gossip.useLeaderElection", true)
	viper.Set("peer.gossip.orgLeader", false)
	n := 2
	portPrefix := 30000
	gossips := startPeers(t, n, portPrefix)
	defer stopPeers(gossips)
	channelName := "channelA"
	peerIndexes := []int{0, 1}
	// Add peers to the channel
	addPeersToChannel(t, n, portPrefix, channelName, gossips, peerIndexes)
	// Prime the membership view of the peers
	waitForFullMembership(t, gossips, n, time.Second*30, time.Second*2)
	// Helper function that creates a gossipService instance
	newGossipService := func(i int) *gossipServiceImpl {
		gs := gossips[i].(*gossipServiceImpl)
		gs.deliveryFactory = &embeddingDeliveryServiceFactory{&deliveryFactoryImpl{}}
		gossipServiceInstance = gs
		gs.InitializeChannel(channelName, []string{"localhost:7050"}, Support{
			Committer: &mockLedgerInfo{1},
			Store:     &transientStoreMock{},
		})
		return gs
	}

	p0 := newGossipService(0)
	p1 := newGossipService(1)

	// Returns index of the leader or -1 if no leader elected
	getLeader := func() int {
		p0.lock.RLock()
		p1.lock.RLock()
		defer p0.lock.RUnlock()
		defer p1.lock.RUnlock()

		if p0.leaderElection[channelName].IsLeader() {
			return 0
		}
		if p1.leaderElection[channelName].IsLeader() {
			return 1
		}
		return -1
	}

	ds0 := p0.deliveryService[channelName].(*embeddingDeliveryService)

	// Wait for p0 to connect to the ordering service
	ds0.waitForDeliveryServiceActivation()
	t.Log("p0 started its delivery service")
	// Ensure it's a leader
	assert.Equal(t, 0, getLeader())
	// Wait for p0 to lose its leadership
	ds0.waitForDeliveryServiceTermination()
	t.Log("p0 stopped its delivery service")
	// Ensure p0 is not a leader
	assert.NotEqual(t, 0, getLeader())
	// Wait for p1 to take over. It should take over before time reaches timeLimit
	timeLimit := time.Now().Add(takeOverMaxTimeout)
	for getLeader() != 1 && time.Now().Before(timeLimit) {
		time.Sleep(time.Second)
	}
	if time.Now().After(timeLimit) {
		util.PrintStackTrace()
		t.Fatalf("p1 hasn't taken over leadership within %v: %d", takeOverMaxTimeout, getLeader())
	}
	p0.chains[channelName].Stop()
	p1.chains[channelName].Stop()
	p0.deliveryService[channelName].Stop()
	p1.deliveryService[channelName].Stop()
}
<|endoftext|>


<commit_before><commit_msg>Increment https conversion<commit_after><|endoftext|>


<commit_before>package cluster

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

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

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kclientset "k8s.io/client-go/kubernetes"
	reale2e "k8s.io/kubernetes/test/e2e"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	"github.com/openshift/api/annotations"
	projectv1 "github.com/openshift/api/project/v1"
	"github.com/openshift/origin/test/extended/cluster/metrics"
	exutil "github.com/openshift/origin/test/extended/util"
)

const checkDeleteProjectInterval = 10 * time.Second
const checkDeleteProjectTimeout = 3 * time.Minute
const checkPodRunningTimeout = 5 * time.Minute

// TODO sjug: pass label via config
var podLabels = map[string]string{"purpose": "test"}
var rootDir string

var _ = g.Describe("[Feature:Performance][Serial][Slow] Load cluster", func() {
	defer g.GinkgoRecover()
	var (
		oc                = exutil.NewCLIWithoutNamespace("cl")
		masterVertFixture = exutil.FixturePath("testdata", "cluster", "master-vert.yaml")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "cakephp-mysql.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "dancer-mysql.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "django-postgresql.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "nodejs-mongodb.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "rails-postgresql.json")
	)

	var c kclientset.Interface
	g.BeforeEach(func() {
		var err error
		c = oc.AdminKubeClient()
		viperConfig := reale2e.GetViperConfig()
		if viperConfig == "" {
			e2e.Logf("Undefined config file, using built-in config %v\n", masterVertFixture)
			path := strings.Split(masterVertFixture, "/")
			rootDir = strings.Join(path[:len(path)-5], "/")
			err = ParseConfig(masterVertFixture, true)
		} else {
			if _, err := os.Stat(viperConfig); os.IsNotExist(err) {
				e2e.Failf("Config file not found: \"%v\"\n", err)
			}
			e2e.Logf("Using config \"%v\"\n", viperConfig)
			err = ParseConfig(viperConfig, false)
		}
		if err != nil {
			e2e.Failf("Error parsing config: %v\n", err)
		}
	})

	g.It("should load the cluster", func() {
		project := ConfigContext.ClusterLoader.Projects
		tuningSets := ConfigContext.ClusterLoader.TuningSets
		sync := ConfigContext.ClusterLoader.Sync
		if project == nil {
			e2e.Failf("Invalid config file.\nFile: %v", project)
		}

		var namespaces []string
		//totalPods := 0 // Keep track of how many pods for stepping
		// TODO sjug: add concurrency
		testStartTime := time.Now()
		for _, p := range project {
			// Find tuning if we have it
			tuning := GetTuningSet(tuningSets, p.Tuning)
			if tuning != nil {
				e2e.Logf("Our tuning set is: %v", tuning)
			}
			for j := 0; j < p.Number; j++ {
				var allArgs []string
				if p.NodeSelector != "" {
					allArgs = append(allArgs, "--node-selector")
					allArgs = append(allArgs, p.NodeSelector)
				}
				nsName := fmt.Sprintf("%s%d", p.Basename, j)
				allArgs = append(allArgs, nsName)

				projectExists, err := ProjectExists(oc, nsName)
				o.Expect(err).NotTo(o.HaveOccurred())
				if !projectExists {
					e2e.Logf("Project %s does not exist.", nsName)
				}

				switch p.IfExists {
				case IF_EXISTS_REUSE:
					e2e.Logf("Configuration requested reuse of project %v", nsName)
				case IF_EXISTS_DELETE:
					e2e.Logf("Configuration requested deletion of project %v", nsName)
					if projectExists {
						err = DeleteProject(oc, nsName, checkDeleteProjectInterval, checkDeleteProjectTimeout)
						o.Expect(err).NotTo(o.HaveOccurred())
					}
				default:
					e2e.Failf("Unsupported ifexists value '%v' for project %v", p.IfExists, project)
				}

				if p.IfExists == IF_EXISTS_REUSE && projectExists {
					// do nothing
				} else {
					// Create namespaces as defined in Cluster Loader config
					err = oc.Run("adm", "new-project").Args(allArgs...).Execute()
					o.Expect(err).NotTo(o.HaveOccurred())
					e2e.Logf("%d/%d : Created new namespace: %v", j+1, p.Number, nsName)
				}

				// label namespace nsName
				if p.Labels != nil {
					_, err = SetNamespaceLabels(c, nsName, p.Labels)
					o.Expect(err).NotTo(o.HaveOccurred())
				}
				namespaces = append(namespaces, nsName)

				// Create config maps
				if p.Configmaps != nil {
					// Configmaps defined, create them
					err := CreateConfigmaps(oc, c, nsName, p.Configmaps)
					o.Expect(err).NotTo(o.HaveOccurred())
				}

				// Create secrets
				if p.Secrets != nil {
					// Secrets defined, create them
					err := CreateSecrets(oc, c, nsName, p.Secrets)
					o.Expect(err).NotTo(o.HaveOccurred())
				}

				// Create templates as defined
				for _, template := range p.Templates {
					err := CreateTemplates(oc, c, nsName, reale2e.GetViperConfig(), template, tuning)
					o.Expect(err).NotTo(o.HaveOccurred())
				}

				// This is too familiar, create pods
				for _, pod := range p.Pods {
					var path string
					var err error
					if pod.File != "" {
						// Parse Pod file into struct
						path, err = mkPath(pod.File, reale2e.GetViperConfig())
						o.Expect(err).NotTo(o.HaveOccurred())
					}

					config, err := ParsePods(path)
					o.Expect(err).NotTo(o.HaveOccurred())

					// Check if environment variables are defined in CL config
					if pod.Parameters == nil {
						e2e.Logf("Pod environment variables will not be modified.")
					} else {
						// Override environment variables for Pod using ConfigMap
						configMapName := InjectConfigMap(c, nsName, pod.Parameters, config)
						// Cleanup ConfigMap at some point after the Pods are created
						defer func() {
							_ = c.CoreV1().ConfigMaps(nsName).Delete(configMapName, nil)
						}()
					}
					err = pod.CreatePods(c, nsName, podLabels, config.Spec, tuning)
					o.Expect(err).NotTo(o.HaveOccurred())
				}
			}
		}

		if sync.Running {
			timeout, err := time.ParseDuration(sync.Timeout)
			o.Expect(err).NotTo(o.HaveOccurred())
			for _, ns := range namespaces {
				err := SyncRunningPods(c, ns, sync.Selectors, timeout)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		}

		if sync.Server.Enabled {
			var podCount PodCount
			err := Server(&podCount, sync.Server.Port, false)
			o.Expect(err).NotTo(o.HaveOccurred())
		}

		if sync.Succeeded {
			timeout, err := time.ParseDuration(sync.Timeout)
			o.Expect(err).NotTo(o.HaveOccurred())
			for _, ns := range namespaces {
				err := SyncSucceededPods(c, ns, sync.Selectors, timeout)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		}

		// Wait for builds and deployments to complete
		for _, ns := range namespaces {
			rcList, err := oc.AdminKubeClient().CoreV1().ReplicationControllers(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing RCs: %v", err)
			}
			rcCount := len(rcList.Items)
			if rcCount > 0 {
				e2e.Logf("Waiting for %d RCs in namespace %s", rcCount, ns)
				for _, rc := range rcList.Items {
					e2e.Logf("Waiting for RC: %s", rc.Name)
					err := e2e.WaitForRCToStabilize(oc.AdminKubeClient(), ns, rc.Name, checkPodRunningTimeout)
					if err != nil {
						e2e.Failf("Error in waiting for RC to stabilize: %v", err)
					}
					err = WaitForRCReady(oc, ns, rc.Name, checkPodRunningTimeout)
					if err != nil {
						e2e.Failf("Error in waiting for RC to become ready: %v", err)
					}
				}
			}

			podList, err := oc.AdminKubeClient().CoreV1().Pods(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing pods: %v", err)
			}
			podCount := len(podList.Items)
			if podCount > 0 {
				e2e.Logf("Waiting for %d pods in namespace %s", podCount, ns)
				pods, err := exutil.WaitForPods(c.CoreV1().Pods(ns), exutil.ParseLabelsOrDie(mapToString(podLabels)), exutil.CheckPodIsRunning, podCount, checkPodRunningTimeout)
				if err != nil {
					e2e.Failf("Error in pod wait: %v", err)
				} else if len(pods) < podCount {
					e2e.Failf("Only got %v out of %v pods in %s (timeout)", len(pods), podCount, checkPodRunningTimeout)
				}
				e2e.Logf("All pods in namespace %s running", ns)
			}

			buildList, err := oc.AsAdmin().BuildClient().BuildV1().Builds(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing builds: %v", err)
			}
			e2e.Logf("Build List: %+v", buildList)
			if len(buildList.Items) > 0 {
				// Get first build name
				buildName := buildList.Items[0].Name
				e2e.Logf("Waiting for build: %q", buildName)
				err = exutil.WaitForABuild(oc.AsAdmin().BuildClient().BuildV1().Builds(ns), buildName, nil, nil, nil)
				if err != nil {
					exutil.DumpBuildLogs(buildName, oc)
				}
				o.Expect(err).NotTo(o.HaveOccurred())
				e2e.Logf("Build %q completed", buildName)

			}

			dcList, err := oc.AsAdmin().AppsClient().AppsV1().DeploymentConfigs(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing deployment configs: %v", err)
			}
			if len(dcList.Items) > 0 {
				// Get first deployment config name
				deploymentName := dcList.Items[0].Name
				e2e.Logf("Waiting for deployment: %q", deploymentName)
				err = exutil.WaitForDeploymentConfig(oc.AdminKubeClient(), oc.AsAdmin().AppsClient().AppsV1(), ns, deploymentName, 1, true, oc)
				o.Expect(err).NotTo(o.HaveOccurred())
				e2e.Logf("Deployment %q completed", deploymentName)
			}
		}

		// Calculate and log test duration
		m := []metrics.Metrics{metrics.NewTestDuration("cluster-loader-test", testStartTime, time.Since(testStartTime))}
		err := metrics.LogMetrics(m)
		o.Expect(err).NotTo(o.HaveOccurred())

		// If config context set to cleanup on completion
		if ConfigContext.ClusterLoader.Cleanup == true {
			for _, ns := range namespaces {
				e2e.Logf("Deleting project %s", ns)
				err := oc.AsAdmin().KubeClient().CoreV1().Namespaces().Delete(ns, nil)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		}
	})
})

func newProject(nsName string) *projectv1.Project {
	return &projectv1.Project{
		ObjectMeta: metav1.ObjectMeta{
			Name: nsName,
			Annotations: map[string]string{
				annotations.OpenShiftDisplayName: nsName,
				//"openshift.io/node-selector": "purpose=test",
			},
		},
	}
}

// mkPath returns fully qualfied file path as a string
func mkPath(filename, config string) (string, error) {
	// Use absolute path if provided in config
	if filepath.IsAbs(filename) {
		return filename, nil
	}
	// Handle an empty filename.
	if filename == "" {
		return "", fmt.Errorf("no template file defined!")
	}

	var searchPaths []string
	workingDir, err := os.Getwd()
	if err != nil {
		return "", err
	}
	configDir := filepath.Dir(config)

	searchPaths = append(searchPaths, filepath.Join(workingDir, filename))
	searchPaths = append(searchPaths, filepath.Join(configDir, filename))

	for _, v := range searchPaths {
		if _, err := os.Stat(v); err == nil {
			return v, nil
		}
	}

	return "", fmt.Errorf("unable to find pod/template file %s\n", filename)
}

// appendIntToString appends an integer i to string s
func appendIntToString(s string, i int) string {
	return s + strconv.Itoa(i)
}
<commit_msg>Wait for pods that have the correct label<commit_after>package cluster

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

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

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kclientset "k8s.io/client-go/kubernetes"
	reale2e "k8s.io/kubernetes/test/e2e"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	"github.com/openshift/api/annotations"
	projectv1 "github.com/openshift/api/project/v1"
	"github.com/openshift/origin/test/extended/cluster/metrics"
	exutil "github.com/openshift/origin/test/extended/util"
)

const checkDeleteProjectInterval = 10 * time.Second
const checkDeleteProjectTimeout = 3 * time.Minute
const checkPodRunningTimeout = 5 * time.Minute

// TODO sjug: pass label via config
var podLabelMap = map[string]string{"purpose": "test"}
var rootDir string

var _ = g.Describe("[Feature:Performance][Serial][Slow] Load cluster", func() {
	defer g.GinkgoRecover()
	var (
		oc                = exutil.NewCLIWithoutNamespace("cl")
		masterVertFixture = exutil.FixturePath("testdata", "cluster", "master-vert.yaml")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "cakephp-mysql.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "dancer-mysql.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "django-postgresql.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "nodejs-mongodb.json")
		_                 = exutil.FixturePath("testdata", "cluster", "quickstarts", "rails-postgresql.json")
	)

	var c kclientset.Interface
	g.BeforeEach(func() {
		var err error
		c = oc.AdminKubeClient()
		viperConfig := reale2e.GetViperConfig()
		if viperConfig == "" {
			e2e.Logf("Undefined config file, using built-in config %v\n", masterVertFixture)
			path := strings.Split(masterVertFixture, "/")
			rootDir = strings.Join(path[:len(path)-5], "/")
			err = ParseConfig(masterVertFixture, true)
		} else {
			if _, err := os.Stat(viperConfig); os.IsNotExist(err) {
				e2e.Failf("Config file not found: \"%v\"\n", err)
			}
			e2e.Logf("Using config \"%v\"\n", viperConfig)
			err = ParseConfig(viperConfig, false)
		}
		if err != nil {
			e2e.Failf("Error parsing config: %v\n", err)
		}
	})

	g.It("should load the cluster", func() {
		project := ConfigContext.ClusterLoader.Projects
		tuningSets := ConfigContext.ClusterLoader.TuningSets
		sync := ConfigContext.ClusterLoader.Sync
		if project == nil {
			e2e.Failf("Invalid config file.\nFile: %v", project)
		}

		var namespaces []string
		//totalPods := 0 // Keep track of how many pods for stepping
		// TODO sjug: add concurrency
		testStartTime := time.Now()
		for _, p := range project {
			// Find tuning if we have it
			tuning := GetTuningSet(tuningSets, p.Tuning)
			if tuning != nil {
				e2e.Logf("Our tuning set is: %v", tuning)
			}
			for j := 0; j < p.Number; j++ {
				var allArgs []string
				if p.NodeSelector != "" {
					allArgs = append(allArgs, "--node-selector")
					allArgs = append(allArgs, p.NodeSelector)
				}
				nsName := fmt.Sprintf("%s%d", p.Basename, j)
				allArgs = append(allArgs, nsName)

				projectExists, err := ProjectExists(oc, nsName)
				o.Expect(err).NotTo(o.HaveOccurred())
				if !projectExists {
					e2e.Logf("Project %s does not exist.", nsName)
				}

				switch p.IfExists {
				case IF_EXISTS_REUSE:
					e2e.Logf("Configuration requested reuse of project %v", nsName)
				case IF_EXISTS_DELETE:
					e2e.Logf("Configuration requested deletion of project %v", nsName)
					if projectExists {
						err = DeleteProject(oc, nsName, checkDeleteProjectInterval, checkDeleteProjectTimeout)
						o.Expect(err).NotTo(o.HaveOccurred())
					}
				default:
					e2e.Failf("Unsupported ifexists value '%v' for project %v", p.IfExists, project)
				}

				if p.IfExists == IF_EXISTS_REUSE && projectExists {
					// do nothing
				} else {
					// Create namespaces as defined in Cluster Loader config
					err = oc.Run("adm", "new-project").Args(allArgs...).Execute()
					o.Expect(err).NotTo(o.HaveOccurred())
					e2e.Logf("%d/%d : Created new namespace: %v", j+1, p.Number, nsName)
				}

				// label namespace nsName
				if p.Labels != nil {
					_, err = SetNamespaceLabels(c, nsName, p.Labels)
					o.Expect(err).NotTo(o.HaveOccurred())
				}
				namespaces = append(namespaces, nsName)

				// Create config maps
				if p.Configmaps != nil {
					// Configmaps defined, create them
					err := CreateConfigmaps(oc, c, nsName, p.Configmaps)
					o.Expect(err).NotTo(o.HaveOccurred())
				}

				// Create secrets
				if p.Secrets != nil {
					// Secrets defined, create them
					err := CreateSecrets(oc, c, nsName, p.Secrets)
					o.Expect(err).NotTo(o.HaveOccurred())
				}

				// Create templates as defined
				for _, template := range p.Templates {
					err := CreateTemplates(oc, c, nsName, reale2e.GetViperConfig(), template, tuning)
					o.Expect(err).NotTo(o.HaveOccurred())
				}

				// This is too familiar, create pods
				for _, pod := range p.Pods {
					var path string
					var err error
					if pod.File != "" {
						// Parse Pod file into struct
						path, err = mkPath(pod.File, reale2e.GetViperConfig())
						o.Expect(err).NotTo(o.HaveOccurred())
					}

					config, err := ParsePods(path)
					o.Expect(err).NotTo(o.HaveOccurred())

					// Check if environment variables are defined in CL config
					if pod.Parameters == nil {
						e2e.Logf("Pod environment variables will not be modified.")
					} else {
						// Override environment variables for Pod using ConfigMap
						configMapName := InjectConfigMap(c, nsName, pod.Parameters, config)
						// Cleanup ConfigMap at some point after the Pods are created
						defer func() {
							_ = c.CoreV1().ConfigMaps(nsName).Delete(configMapName, nil)
						}()
					}
					err = pod.CreatePods(c, nsName, podLabelMap, config.Spec, tuning)
					o.Expect(err).NotTo(o.HaveOccurred())
				}
			}
		}

		if sync.Running {
			timeout, err := time.ParseDuration(sync.Timeout)
			o.Expect(err).NotTo(o.HaveOccurred())
			for _, ns := range namespaces {
				err := SyncRunningPods(c, ns, sync.Selectors, timeout)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		}

		if sync.Server.Enabled {
			var podCount PodCount
			err := Server(&podCount, sync.Server.Port, false)
			o.Expect(err).NotTo(o.HaveOccurred())
		}

		if sync.Succeeded {
			timeout, err := time.ParseDuration(sync.Timeout)
			o.Expect(err).NotTo(o.HaveOccurred())
			for _, ns := range namespaces {
				err := SyncSucceededPods(c, ns, sync.Selectors, timeout)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		}

		// Wait for builds and deployments to complete
		for _, ns := range namespaces {
			rcList, err := oc.AdminKubeClient().CoreV1().ReplicationControllers(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing RCs: %v", err)
			}
			rcCount := len(rcList.Items)
			if rcCount > 0 {
				e2e.Logf("Waiting for %d RCs in namespace %s", rcCount, ns)
				for _, rc := range rcList.Items {
					e2e.Logf("Waiting for RC: %s", rc.Name)
					err := e2e.WaitForRCToStabilize(oc.AdminKubeClient(), ns, rc.Name, checkPodRunningTimeout)
					if err != nil {
						e2e.Failf("Error in waiting for RC to stabilize: %v", err)
					}
					err = WaitForRCReady(oc, ns, rc.Name, checkPodRunningTimeout)
					if err != nil {
						e2e.Failf("Error in waiting for RC to become ready: %v", err)
					}
				}
			}

			podLabels := exutil.ParseLabelsOrDie(mapToString(podLabelMap))
			podList, err := oc.AdminKubeClient().CoreV1().Pods(ns).List(metav1.ListOptions{LabelSelector: podLabels.String()})
			if err != nil {
				e2e.Failf("Error listing pods: %v", err)
			}
			podCount := len(podList.Items)
			if podCount > 0 {
				e2e.Logf("Waiting for %d pods in namespace %s", podCount, ns)
				pods, err := exutil.WaitForPods(c.CoreV1().Pods(ns), podLabels, exutil.CheckPodIsRunning, podCount, checkPodRunningTimeout)
				if err != nil {
					e2e.Failf("Error in pod wait: %v", err)
				} else if len(pods) < podCount {
					e2e.Failf("Only got %v out of %v pods in %s (timeout)", len(pods), podCount, checkPodRunningTimeout)
				}
				e2e.Logf("All pods in namespace %s running", ns)
			}

			buildList, err := oc.AsAdmin().BuildClient().BuildV1().Builds(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing builds: %v", err)
			}
			e2e.Logf("Build List: %+v", buildList)
			if len(buildList.Items) > 0 {
				// Get first build name
				buildName := buildList.Items[0].Name
				e2e.Logf("Waiting for build: %q", buildName)
				err = exutil.WaitForABuild(oc.AsAdmin().BuildClient().BuildV1().Builds(ns), buildName, nil, nil, nil)
				if err != nil {
					exutil.DumpBuildLogs(buildName, oc)
				}
				o.Expect(err).NotTo(o.HaveOccurred())
				e2e.Logf("Build %q completed", buildName)

			}

			dcList, err := oc.AsAdmin().AppsClient().AppsV1().DeploymentConfigs(ns).List(metav1.ListOptions{})
			if err != nil {
				e2e.Failf("Error listing deployment configs: %v", err)
			}
			if len(dcList.Items) > 0 {
				// Get first deployment config name
				deploymentName := dcList.Items[0].Name
				e2e.Logf("Waiting for deployment: %q", deploymentName)
				err = exutil.WaitForDeploymentConfig(oc.AdminKubeClient(), oc.AsAdmin().AppsClient().AppsV1(), ns, deploymentName, 1, true, oc)
				o.Expect(err).NotTo(o.HaveOccurred())
				e2e.Logf("Deployment %q completed", deploymentName)
			}
		}

		// Calculate and log test duration
		m := []metrics.Metrics{metrics.NewTestDuration("cluster-loader-test", testStartTime, time.Since(testStartTime))}
		err := metrics.LogMetrics(m)
		o.Expect(err).NotTo(o.HaveOccurred())

		// If config context set to cleanup on completion
		if ConfigContext.ClusterLoader.Cleanup == true {
			for _, ns := range namespaces {
				e2e.Logf("Deleting project %s", ns)
				err := oc.AsAdmin().KubeClient().CoreV1().Namespaces().Delete(ns, nil)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		}
	})
})

func newProject(nsName string) *projectv1.Project {
	return &projectv1.Project{
		ObjectMeta: metav1.ObjectMeta{
			Name: nsName,
			Annotations: map[string]string{
				annotations.OpenShiftDisplayName: nsName,
				//"openshift.io/node-selector": "purpose=test",
			},
		},
	}
}

// mkPath returns fully qualfied file path as a string
func mkPath(filename, config string) (string, error) {
	// Use absolute path if provided in config
	if filepath.IsAbs(filename) {
		return filename, nil
	}
	// Handle an empty filename.
	if filename == "" {
		return "", fmt.Errorf("no template file defined!")
	}

	var searchPaths []string
	workingDir, err := os.Getwd()
	if err != nil {
		return "", err
	}
	configDir := filepath.Dir(config)

	searchPaths = append(searchPaths, filepath.Join(workingDir, filename))
	searchPaths = append(searchPaths, filepath.Join(configDir, filename))

	for _, v := range searchPaths {
		if _, err := os.Stat(v); err == nil {
			return v, nil
		}
	}

	return "", fmt.Errorf("unable to find pod/template file %s\n", filename)
}

// appendIntToString appends an integer i to string s
func appendIntToString(s string, i int) string {
	return s + strconv.Itoa(i)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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 systemstatsmonitor

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

	"github.com/golang/glog"

	"k8s.io/node-problem-detector/pkg/problemdaemon"
	ssmtypes "k8s.io/node-problem-detector/pkg/systemstatsmonitor/types"
	"k8s.io/node-problem-detector/pkg/types"
	"k8s.io/node-problem-detector/pkg/util/tomb"
)

const SystemStatsMonitorName = "system-stats-monitor"

func init() {
	problemdaemon.Register(SystemStatsMonitorName, types.ProblemDaemonHandler{
		CreateProblemDaemonOrDie: NewSystemStatsMonitorOrDie,
		CmdOptionDescription:     "Set to config file paths."})
}

type systemStatsMonitor struct {
	configPath         string
	config             ssmtypes.SystemStatsConfig
	cpuCollector       *cpuCollector
	diskCollector      *diskCollector
	hostCollector      *hostCollector
	memoryCollector    *memoryCollector
	osFeatureCollector *osFeatureCollector
	tomb               *tomb.Tomb
}

// NewSystemStatsMonitorOrDie creates a system stats monitor.
func NewSystemStatsMonitorOrDie(configPath string) types.Monitor {
	ssm := systemStatsMonitor{
		configPath: configPath,
		tomb:       tomb.NewTomb(),
	}

	// Apply configurations.
	f, err := ioutil.ReadFile(configPath)
	if err != nil {
		glog.Fatalf("Failed to read configuration file %q: %v", configPath, err)
	}
	err = json.Unmarshal(f, &ssm.config)
	if err != nil {
		glog.Fatalf("Failed to unmarshal configuration file %q: %v", configPath, err)
	}

	err = ssm.config.ApplyConfiguration()
	if err != nil {
		glog.Fatalf("Failed to apply configuration for %q: %v", configPath, err)
	}

	glog.Infof("Error: %v", ssm.config)

	err = ssm.config.Validate()
	if err != nil {
		glog.Fatalf("Failed to validate %s configuration %+v: %v", ssm.configPath, ssm.config, err)
	}

	if len(ssm.config.CPUConfig.MetricsConfigs) > 0 {
		ssm.cpuCollector = NewCPUCollectorOrDie(&ssm.config.CPUConfig)
	}
	if len(ssm.config.DiskConfig.MetricsConfigs) > 0 {
		ssm.diskCollector = NewDiskCollectorOrDie(&ssm.config.DiskConfig)
	}
	if len(ssm.config.HostConfig.MetricsConfigs) > 0 {
		ssm.hostCollector = NewHostCollectorOrDie(&ssm.config.HostConfig)
	}
	if len(ssm.config.MemoryConfig.MetricsConfigs) > 0 {
		ssm.memoryCollector = NewMemoryCollectorOrDie(&ssm.config.MemoryConfig)
	}
	if len(ssm.config.OsFeatureConfig.MetricsConfigs) > 0 {
		ssm.osFeatureCollector = NewOsFeatureCollectorOrDie(&ssm.config.OsFeatureConfig)
	}
	return &ssm
}

func (ssm *systemStatsMonitor) Start() (<-chan *types.Status, error) {
	glog.Infof("Start system stats monitor %s", ssm.configPath)
	go ssm.monitorLoop()
	return nil, nil
}

func (ssm *systemStatsMonitor) monitorLoop() {
	defer ssm.tomb.Done()

	runTicker := time.NewTicker(ssm.config.InvokeInterval)
	defer runTicker.Stop()

	select {
	case <-ssm.tomb.Stopping():
		glog.Infof("System stats monitor stopped: %s", ssm.configPath)
		return
	default:
		ssm.cpuCollector.collect()
		ssm.diskCollector.collect()
		ssm.hostCollector.collect()
		ssm.memoryCollector.collect()
		ssm.osFeatureCollector.collect()
	}

	for {
		select {
		case <-runTicker.C:
			ssm.cpuCollector.collect()
			ssm.diskCollector.collect()
			ssm.hostCollector.collect()
			ssm.memoryCollector.collect()
			ssm.osFeatureCollector.collect()
		case <-ssm.tomb.Stopping():
			glog.Infof("System stats monitor stopped: %s", ssm.configPath)
			return
		}
	}
}

func (ssm *systemStatsMonitor) Stop() {
	glog.Infof("Stop system stats monitor %s", ssm.configPath)
	ssm.tomb.Stop()
}
<commit_msg>cleanup the log<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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 systemstatsmonitor

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

	"github.com/golang/glog"

	"k8s.io/node-problem-detector/pkg/problemdaemon"
	ssmtypes "k8s.io/node-problem-detector/pkg/systemstatsmonitor/types"
	"k8s.io/node-problem-detector/pkg/types"
	"k8s.io/node-problem-detector/pkg/util/tomb"
)

const SystemStatsMonitorName = "system-stats-monitor"

func init() {
	problemdaemon.Register(SystemStatsMonitorName, types.ProblemDaemonHandler{
		CreateProblemDaemonOrDie: NewSystemStatsMonitorOrDie,
		CmdOptionDescription:     "Set to config file paths."})
}

type systemStatsMonitor struct {
	configPath         string
	config             ssmtypes.SystemStatsConfig
	cpuCollector       *cpuCollector
	diskCollector      *diskCollector
	hostCollector      *hostCollector
	memoryCollector    *memoryCollector
	osFeatureCollector *osFeatureCollector
	tomb               *tomb.Tomb
}

// NewSystemStatsMonitorOrDie creates a system stats monitor.
func NewSystemStatsMonitorOrDie(configPath string) types.Monitor {
	ssm := systemStatsMonitor{
		configPath: configPath,
		tomb:       tomb.NewTomb(),
	}

	// Apply configurations.
	f, err := ioutil.ReadFile(configPath)
	if err != nil {
		glog.Fatalf("Failed to read configuration file %q: %v", configPath, err)
	}
	err = json.Unmarshal(f, &ssm.config)
	if err != nil {
		glog.Fatalf("Failed to unmarshal configuration file %q: %v", configPath, err)
	}

	err = ssm.config.ApplyConfiguration()
	if err != nil {
		glog.Fatalf("Failed to apply configuration for %q: %v", configPath, err)
	}

	err = ssm.config.Validate()
	if err != nil {
		glog.Fatalf("Failed to validate %s configuration %+v: %v", ssm.configPath, ssm.config, err)
	}

	if len(ssm.config.CPUConfig.MetricsConfigs) > 0 {
		ssm.cpuCollector = NewCPUCollectorOrDie(&ssm.config.CPUConfig)
	}
	if len(ssm.config.DiskConfig.MetricsConfigs) > 0 {
		ssm.diskCollector = NewDiskCollectorOrDie(&ssm.config.DiskConfig)
	}
	if len(ssm.config.HostConfig.MetricsConfigs) > 0 {
		ssm.hostCollector = NewHostCollectorOrDie(&ssm.config.HostConfig)
	}
	if len(ssm.config.MemoryConfig.MetricsConfigs) > 0 {
		ssm.memoryCollector = NewMemoryCollectorOrDie(&ssm.config.MemoryConfig)
	}
	if len(ssm.config.OsFeatureConfig.MetricsConfigs) > 0 {
		ssm.osFeatureCollector = NewOsFeatureCollectorOrDie(&ssm.config.OsFeatureConfig)
	}
	return &ssm
}

func (ssm *systemStatsMonitor) Start() (<-chan *types.Status, error) {
	glog.Infof("Start system stats monitor %s", ssm.configPath)
	go ssm.monitorLoop()
	return nil, nil
}

func (ssm *systemStatsMonitor) monitorLoop() {
	defer ssm.tomb.Done()

	runTicker := time.NewTicker(ssm.config.InvokeInterval)
	defer runTicker.Stop()

	select {
	case <-ssm.tomb.Stopping():
		glog.Infof("System stats monitor stopped: %s", ssm.configPath)
		return
	default:
		ssm.cpuCollector.collect()
		ssm.diskCollector.collect()
		ssm.hostCollector.collect()
		ssm.memoryCollector.collect()
		ssm.osFeatureCollector.collect()
	}

	for {
		select {
		case <-runTicker.C:
			ssm.cpuCollector.collect()
			ssm.diskCollector.collect()
			ssm.hostCollector.collect()
			ssm.memoryCollector.collect()
			ssm.osFeatureCollector.collect()
		case <-ssm.tomb.Stopping():
			glog.Infof("System stats monitor stopped: %s", ssm.configPath)
			return
		}
	}
}

func (ssm *systemStatsMonitor) Stop() {
	glog.Infof("Stop system stats monitor %s", ssm.configPath)
	ssm.tomb.Stop()
}
<|endoftext|>


<commit_before>package protocol

// Code generated (see typescript/README.md) DO NOT EDIT.

import (
	"context"
	"encoding/json"

	"golang.org/x/tools/internal/jsonrpc2"
	"golang.org/x/tools/internal/lsp/xlog"
)

type Client interface {
	ShowMessage(context.Context, *ShowMessageParams) error
	LogMessage(context.Context, *LogMessageParams) error
	Event(context.Context, *interface{}) error
	PublishDiagnostics(context.Context, *PublishDiagnosticsParams) error
	WorkspaceFolders(context.Context) ([]WorkspaceFolder, error)
	Configuration(context.Context, *ConfigurationParams) ([]interface{}, error)
	RegisterCapability(context.Context, *RegistrationParams) error
	UnregisterCapability(context.Context, *UnregistrationParams) error
	ShowMessageRequest(context.Context, *ShowMessageRequestParams) (*MessageActionItem, error)
	ApplyEdit(context.Context, *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResponse, error)
}

func clientHandler(log xlog.Logger, client Client) jsonrpc2.Handler {
	return func(ctx context.Context, conn *jsonrpc2.Conn, r *jsonrpc2.Request) {
		switch r.Method {
		case "$/cancelRequest":
			var params CancelParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			conn.Cancel(params.ID)
		case "window/showMessage": // notif
			var params ShowMessageParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.ShowMessage(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "window/logMessage": // notif
			var params LogMessageParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.LogMessage(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "telemetry/event": // notif
			var params interface{}
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.Event(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "textDocument/publishDiagnostics": // notif
			var params PublishDiagnosticsParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.PublishDiagnostics(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "workspace/workspaceFolders": // req
			if r.Params != nil {
				conn.Reply(ctx, r, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidParams, "Expected no params"))
				return
			}
			resp, err := client.WorkspaceFolders(ctx)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "workspace/configuration": // req
			var params ConfigurationParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			resp, err := client.Configuration(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "client/registerCapability": // req
			var params RegistrationParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.RegisterCapability(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "client/unregisterCapability": // req
			var params UnregistrationParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.UnregisterCapability(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "window/showMessageRequest": // req
			var params ShowMessageRequestParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			resp, err := client.ShowMessageRequest(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "workspace/applyEdit": // req
			var params ApplyWorkspaceEditParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			resp, err := client.ApplyEdit(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}

		default:
			if r.IsNotify() {
				conn.Reply(ctx, r, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeMethodNotFound, "method %q not found", r.Method))
			}
		}
	}
}

type clientDispatcher struct {
	*jsonrpc2.Conn
}

func (s *clientDispatcher) ShowMessage(ctx context.Context, params *ShowMessageParams) error {
	return s.Conn.Notify(ctx, "window/showMessage", params)
}

func (s *clientDispatcher) LogMessage(ctx context.Context, params *LogMessageParams) error {
	return s.Conn.Notify(ctx, "window/logMessage", params)
}

func (s *clientDispatcher) Event(ctx context.Context, params *interface{}) error {
	return s.Conn.Notify(ctx, "telemetry/event", params)
}

func (s *clientDispatcher) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) error {
	return s.Conn.Notify(ctx, "textDocument/publishDiagnostics", params)
}
func (s *clientDispatcher) WorkspaceFolders(ctx context.Context) ([]WorkspaceFolder, error) {
	var result []WorkspaceFolder
	if err := s.Conn.Call(ctx, "workspace/workspaceFolders", nil, &result); err != nil {
		return nil, err
	}
	return result, nil
}

func (s *clientDispatcher) Configuration(ctx context.Context, params *ConfigurationParams) ([]interface{}, error) {
	var result []interface{}
	if err := s.Conn.Call(ctx, "workspace/configuration", params, &result); err != nil {
		return nil, err
	}
	return result, nil
}

func (s *clientDispatcher) RegisterCapability(ctx context.Context, params *RegistrationParams) error {
	return s.Conn.Notify(ctx, "client/registerCapability", params) // Notify? (not Call?)
}

func (s *clientDispatcher) UnregisterCapability(ctx context.Context, params *UnregistrationParams) error {
	return s.Conn.Notify(ctx, "client/unregisterCapability", params) // Notify? (not Call?)
}

func (s *clientDispatcher) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (*MessageActionItem, error) {
	var result MessageActionItem
	if err := s.Conn.Call(ctx, "window/showMessageRequest", params, &result); err != nil {
		return nil, err
	}
	return &result, nil
}

func (s *clientDispatcher) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResponse, error) {
	var result ApplyWorkspaceEditResponse
	if err := s.Conn.Call(ctx, "workspace/applyEdit", params, &result); err != nil {
		return nil, err
	}
	return &result, nil
}
<commit_msg>internal/lsp: client/registerCapapbility is a request, not a notification<commit_after>package protocol

// Code generated (see typescript/README.md) DO NOT EDIT.

import (
	"context"
	"encoding/json"

	"golang.org/x/tools/internal/jsonrpc2"
	"golang.org/x/tools/internal/lsp/xlog"
)

type Client interface {
	ShowMessage(context.Context, *ShowMessageParams) error
	LogMessage(context.Context, *LogMessageParams) error
	Event(context.Context, *interface{}) error
	PublishDiagnostics(context.Context, *PublishDiagnosticsParams) error
	WorkspaceFolders(context.Context) ([]WorkspaceFolder, error)
	Configuration(context.Context, *ConfigurationParams) ([]interface{}, error)
	RegisterCapability(context.Context, *RegistrationParams) error
	UnregisterCapability(context.Context, *UnregistrationParams) error
	ShowMessageRequest(context.Context, *ShowMessageRequestParams) (*MessageActionItem, error)
	ApplyEdit(context.Context, *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResponse, error)
}

func clientHandler(log xlog.Logger, client Client) jsonrpc2.Handler {
	return func(ctx context.Context, conn *jsonrpc2.Conn, r *jsonrpc2.Request) {
		switch r.Method {
		case "$/cancelRequest":
			var params CancelParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			conn.Cancel(params.ID)
		case "window/showMessage": // notif
			var params ShowMessageParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.ShowMessage(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "window/logMessage": // notif
			var params LogMessageParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.LogMessage(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "telemetry/event": // notif
			var params interface{}
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.Event(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "textDocument/publishDiagnostics": // notif
			var params PublishDiagnosticsParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.PublishDiagnostics(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "workspace/workspaceFolders": // req
			if r.Params != nil {
				conn.Reply(ctx, r, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidParams, "Expected no params"))
				return
			}
			resp, err := client.WorkspaceFolders(ctx)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "workspace/configuration": // req
			var params ConfigurationParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			resp, err := client.Configuration(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "client/registerCapability": // req
			var params RegistrationParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.RegisterCapability(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "client/unregisterCapability": // req
			var params UnregistrationParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			if err := client.UnregisterCapability(ctx, &params); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "window/showMessageRequest": // req
			var params ShowMessageRequestParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			resp, err := client.ShowMessageRequest(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}
		case "workspace/applyEdit": // req
			var params ApplyWorkspaceEditParams
			if err := json.Unmarshal(*r.Params, &params); err != nil {
				sendParseError(ctx, log, conn, r, err)
				return
			}
			resp, err := client.ApplyEdit(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				log.Errorf(ctx, "%v", err)
			}

		default:
			if r.IsNotify() {
				conn.Reply(ctx, r, nil, jsonrpc2.NewErrorf(jsonrpc2.CodeMethodNotFound, "method %q not found", r.Method))
			}
		}
	}
}

type clientDispatcher struct {
	*jsonrpc2.Conn
}

func (s *clientDispatcher) ShowMessage(ctx context.Context, params *ShowMessageParams) error {
	return s.Conn.Notify(ctx, "window/showMessage", params)
}

func (s *clientDispatcher) LogMessage(ctx context.Context, params *LogMessageParams) error {
	return s.Conn.Notify(ctx, "window/logMessage", params)
}

func (s *clientDispatcher) Event(ctx context.Context, params *interface{}) error {
	return s.Conn.Notify(ctx, "telemetry/event", params)
}

func (s *clientDispatcher) PublishDiagnostics(ctx context.Context, params *PublishDiagnosticsParams) error {
	return s.Conn.Notify(ctx, "textDocument/publishDiagnostics", params)
}
func (s *clientDispatcher) WorkspaceFolders(ctx context.Context) ([]WorkspaceFolder, error) {
	var result []WorkspaceFolder
	if err := s.Conn.Call(ctx, "workspace/workspaceFolders", nil, &result); err != nil {
		return nil, err
	}
	return result, nil
}

func (s *clientDispatcher) Configuration(ctx context.Context, params *ConfigurationParams) ([]interface{}, error) {
	var result []interface{}
	if err := s.Conn.Call(ctx, "workspace/configuration", params, &result); err != nil {
		return nil, err
	}
	return result, nil
}

func (s *clientDispatcher) RegisterCapability(ctx context.Context, params *RegistrationParams) error {
	return s.Conn.Call(ctx, "client/registerCapability", params, nil) // Call, not Notify
}

func (s *clientDispatcher) UnregisterCapability(ctx context.Context, params *UnregistrationParams) error {
	return s.Conn.Call(ctx, "client/unregisterCapability", params, nil) // Call, not Notify
}

func (s *clientDispatcher) ShowMessageRequest(ctx context.Context, params *ShowMessageRequestParams) (*MessageActionItem, error) {
	var result MessageActionItem
	if err := s.Conn.Call(ctx, "window/showMessageRequest", params, &result); err != nil {
		return nil, err
	}
	return &result, nil
}

func (s *clientDispatcher) ApplyEdit(ctx context.Context, params *ApplyWorkspaceEditParams) (*ApplyWorkspaceEditResponse, error) {
	var result ApplyWorkspaceEditResponse
	if err := s.Conn.Call(ctx, "workspace/applyEdit", params, &result); err != nil {
		return nil, err
	}
	return &result, nil
}
<|endoftext|>


<commit_before>// +build linux

// Copyright 2016 CNI 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 ip

import (
	"fmt"
	"net"

	"github.com/containernetworking/cni/pkg/types"
	current "github.com/containernetworking/cni/pkg/types/100"
	"github.com/vishvananda/netlink"
)

func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) error {

	// Ensure ips
	for _, ips := range resultIPs {
		ourAddr := netlink.Addr{IPNet: &ips.Address}
		match := false

		link, err := netlink.LinkByName(ifName)
		if err != nil {
			return fmt.Errorf("Cannot find container link %v", ifName)
		}

		addrList, err := netlink.AddrList(link, netlink.FAMILY_ALL)
		if err != nil {
			return fmt.Errorf("Cannot obtain List of IP Addresses")
		}

		for _, addr := range addrList {
			if addr.Equal(ourAddr) {
				match = true
				break
			}
		}
		if match == false {
			return fmt.Errorf("Failed to match addr %v on interface %v", ourAddr, ifName)
		}

		// Convert the host/prefixlen to just prefix for route lookup.
		_, ourPrefix, err := net.ParseCIDR(ourAddr.String())

		findGwy := &netlink.Route{Dst: ourPrefix}
		routeFilter := netlink.RT_FILTER_DST

		family := netlink.FAMILY_V6
		if ips.Address.IP.To4() != nil {
			family = netlink.FAMILY_V4
		}

		gwy, err := netlink.RouteListFiltered(family, findGwy, routeFilter)
		if err != nil {
			return fmt.Errorf("Error %v trying to find Gateway %v for interface %v", err, ips.Gateway, ifName)
		}
		if gwy == nil {
			return fmt.Errorf("Failed to find Gateway %v for interface %v", ips.Gateway, ifName)
		}
	}

	return nil
}

func ValidateExpectedRoute(resultRoutes []*types.Route) error {

	// Ensure that each static route in prevResults is found in the routing table
	for _, route := range resultRoutes {
		find := &netlink.Route{Dst: &route.Dst, Gw: route.GW}
		routeFilter := netlink.RT_FILTER_DST | netlink.RT_FILTER_GW
		var family int

		switch {
		case route.Dst.IP.To4() != nil:
			family = netlink.FAMILY_V4
			// Default route needs Dst set to nil
			if route.Dst.String() == "0.0.0.0/0" {
				find = &netlink.Route{Dst: nil, Gw: route.GW}
				routeFilter = netlink.RT_FILTER_DST
			}
		case len(route.Dst.IP) == net.IPv6len:
			family = netlink.FAMILY_V6
			// Default route needs Dst set to nil
			if route.Dst.String() == "::/0" {
				find = &netlink.Route{Dst: nil, Gw: route.GW}
				routeFilter = netlink.RT_FILTER_DST
			}
		default:
			return fmt.Errorf("Invalid static route found %v", route)
		}

		wasFound, err := netlink.RouteListFiltered(family, find, routeFilter)
		if err != nil {
			return fmt.Errorf("Expected Route %v not route table lookup error %v", route, err)
		}
		if wasFound == nil {
			return fmt.Errorf("Expected Route %v not found in routing table", route)
		}
	}

	return nil
}
<commit_msg>gofmt<commit_after>//go:build linux
// +build linux

// Copyright 2016 CNI 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 ip

import (
	"fmt"
	"net"

	"github.com/containernetworking/cni/pkg/types"
	current "github.com/containernetworking/cni/pkg/types/100"
	"github.com/vishvananda/netlink"
)

func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) error {

	// Ensure ips
	for _, ips := range resultIPs {
		ourAddr := netlink.Addr{IPNet: &ips.Address}
		match := false

		link, err := netlink.LinkByName(ifName)
		if err != nil {
			return fmt.Errorf("Cannot find container link %v", ifName)
		}

		addrList, err := netlink.AddrList(link, netlink.FAMILY_ALL)
		if err != nil {
			return fmt.Errorf("Cannot obtain List of IP Addresses")
		}

		for _, addr := range addrList {
			if addr.Equal(ourAddr) {
				match = true
				break
			}
		}
		if match == false {
			return fmt.Errorf("Failed to match addr %v on interface %v", ourAddr, ifName)
		}

		// Convert the host/prefixlen to just prefix for route lookup.
		_, ourPrefix, err := net.ParseCIDR(ourAddr.String())

		findGwy := &netlink.Route{Dst: ourPrefix}
		routeFilter := netlink.RT_FILTER_DST

		family := netlink.FAMILY_V6
		if ips.Address.IP.To4() != nil {
			family = netlink.FAMILY_V4
		}

		gwy, err := netlink.RouteListFiltered(family, findGwy, routeFilter)
		if err != nil {
			return fmt.Errorf("Error %v trying to find Gateway %v for interface %v", err, ips.Gateway, ifName)
		}
		if gwy == nil {
			return fmt.Errorf("Failed to find Gateway %v for interface %v", ips.Gateway, ifName)
		}
	}

	return nil
}

func ValidateExpectedRoute(resultRoutes []*types.Route) error {

	// Ensure that each static route in prevResults is found in the routing table
	for _, route := range resultRoutes {
		find := &netlink.Route{Dst: &route.Dst, Gw: route.GW}
		routeFilter := netlink.RT_FILTER_DST | netlink.RT_FILTER_GW
		var family int

		switch {
		case route.Dst.IP.To4() != nil:
			family = netlink.FAMILY_V4
			// Default route needs Dst set to nil
			if route.Dst.String() == "0.0.0.0/0" {
				find = &netlink.Route{Dst: nil, Gw: route.GW}
				routeFilter = netlink.RT_FILTER_DST
			}
		case len(route.Dst.IP) == net.IPv6len:
			family = netlink.FAMILY_V6
			// Default route needs Dst set to nil
			if route.Dst.String() == "::/0" {
				find = &netlink.Route{Dst: nil, Gw: route.GW}
				routeFilter = netlink.RT_FILTER_DST
			}
		default:
			return fmt.Errorf("Invalid static route found %v", route)
		}

		wasFound, err := netlink.RouteListFiltered(family, find, routeFilter)
		if err != nil {
			return fmt.Errorf("Expected Route %v not route table lookup error %v", route, err)
		}
		if wasFound == nil {
			return fmt.Errorf("Expected Route %v not found in routing table", route)
		}
	}

	return nil
}
<|endoftext|>