<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package azure

import (
	"fmt"
	"testing"

	apiv1 "k8s.io/api/core/v1"
	"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
	"k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient"
	"k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient"

	"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2017-05-10/resources"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
)

func newTestAzureManager(t *testing.T) *AzureManager {
	manager := &AzureManager{
		env:                  azure.PublicCloud,
		explicitlyConfigured: make(map[string]bool),
		config: &Config{
			ResourceGroup:       "test",
			VMType:              vmTypeVMSS,
			MaxDeploymentsCount: 2,
		},

		azClient: &azClient{
			deploymentsClient: &DeploymentsClientMock{
				FakeStore: make(map[string]resources.DeploymentExtended),
			},
		},
	}

	cache, error := newAsgCache()
	assert.NoError(t, error)

	manager.asgCache = cache
	return manager
}

func newTestProvider(t *testing.T) *AzureCloudProvider {
	manager := newTestAzureManager(t)
	resourceLimiter := cloudprovider.NewResourceLimiter(
		map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
		map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})

	return &AzureCloudProvider{
		azureManager:    manager,
		resourceLimiter: resourceLimiter,
	}
}

func TestBuildAzureCloudProvider(t *testing.T) {
	resourceLimiter := cloudprovider.NewResourceLimiter(
		map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
		map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
	m := newTestAzureManager(t)
	_, err := BuildAzureCloudProvider(m, resourceLimiter)
	assert.NoError(t, err)
}

func TestName(t *testing.T) {
	provider := newTestProvider(t)
	assert.Equal(t, provider.Name(), "azure")
}

func TestNodeGroups(t *testing.T) {
	provider := newTestProvider(t)
	assert.Equal(t, len(provider.NodeGroups()), 0)

	registered := provider.azureManager.RegisterAsg(
		newTestScaleSet(provider.azureManager, "test-asg"))
	assert.True(t, registered)
	assert.Equal(t, len(provider.NodeGroups()), 1)
}

func TestNodeGroupForNode(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	expectedVMSSVMs := newTestVMSSVMList(3)
	expectedScaleSets := newTestVMSSList(3, "test-asg", "eastus")

	provider := newTestProvider(t)
	mockVMSSClient := mockvmssclient.NewMockInterface(ctrl)
	mockVMSSClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup).Return(expectedScaleSets, nil)
	provider.azureManager.azClient.virtualMachineScaleSetsClient = mockVMSSClient
	mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl)
	mockVMSSVMClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup, "test-asg", gomock.Any()).Return(expectedVMSSVMs, nil).AnyTimes()
	provider.azureManager.azClient.virtualMachineScaleSetVMsClient = mockVMSSVMClient

	registered := provider.azureManager.RegisterAsg(
		newTestScaleSet(provider.azureManager, "test-asg"))
	assert.True(t, registered)
	assert.Equal(t, len(provider.NodeGroups()), 1)

	node := &apiv1.Node{
		Spec: apiv1.NodeSpec{
			ProviderID: "azure://" + fmt.Sprintf(fakeVirtualMachineScaleSetVMID, 0),
		},
	}
	// refresh cache
	provider.azureManager.regenerateCache()
	group, err := provider.NodeGroupForNode(node)
	assert.NoError(t, err)
	assert.NotNil(t, group, "Group should not be nil")
	assert.Equal(t, group.Id(), "test-asg")
	assert.Equal(t, group.MinSize(), 1)
	assert.Equal(t, group.MaxSize(), 5)

	// test node in cluster that is not in a group managed by cluster autoscaler
	nodeNotInGroup := &apiv1.Node{
		Spec: apiv1.NodeSpec{
			ProviderID: "azure:///subscriptions/subscripion/resourceGroups/test-resource-group/providers/Microsoft.Compute/virtualMachines/test-instance-id-not-in-group",
		},
	}
	group, err = provider.NodeGroupForNode(nodeNotInGroup)
	assert.NoError(t, err)
	assert.Nil(t, group)
}

func TestNodeGroupForNodeWithNoProviderId(t *testing.T) {
	provider := newTestProvider(t)
	registered := provider.azureManager.RegisterAsg(
		newTestScaleSet(provider.azureManager, "test-asg"))
	assert.True(t, registered)
	assert.Equal(t, len(provider.NodeGroups()), 1)

	node := &apiv1.Node{
		Spec: apiv1.NodeSpec{
			ProviderID: "",
		},
	}
	group, err := provider.NodeGroupForNode(node)

	assert.NoError(t, err)
	assert.Equal(t, group, nil)
}
<commit_msg>Enrich unit tests for azure_cloud_provider<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package azure

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

	apiv1 "k8s.io/api/core/v1"
	"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
	"k8s.io/autoscaler/cluster-autoscaler/config"
	azclients "k8s.io/legacy-cloud-providers/azure/clients"
	"k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient"
	"k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient"

	"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2017-05-10/resources"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
)

func newTestAzureManager(t *testing.T) *AzureManager {
	manager := &AzureManager{
		env:                  azure.PublicCloud,
		explicitlyConfigured: make(map[string]bool),
		config: &Config{
			ResourceGroup:       "test",
			VMType:              vmTypeVMSS,
			MaxDeploymentsCount: 2,
		},

		azClient: &azClient{
			deploymentsClient: &DeploymentsClientMock{
				FakeStore: make(map[string]resources.DeploymentExtended),
			},
		},
	}

	cache, error := newAsgCache()
	assert.NoError(t, error)

	manager.asgCache = cache
	return manager
}

func newTestProvider(t *testing.T) *AzureCloudProvider {
	manager := newTestAzureManager(t)
	resourceLimiter := cloudprovider.NewResourceLimiter(
		map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
		map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})

	return &AzureCloudProvider{
		azureManager:    manager,
		resourceLimiter: resourceLimiter,
	}
}

func TestBuildAzureCloudProvider(t *testing.T) {
	resourceLimiter := cloudprovider.NewResourceLimiter(
		map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
		map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
	m := newTestAzureManager(t)
	_, err := BuildAzureCloudProvider(m, resourceLimiter)
	assert.NoError(t, err)
}

func TestName(t *testing.T) {
	provider := newTestProvider(t)
	assert.Equal(t, provider.Name(), "azure")
}

func TestNodeGroups(t *testing.T) {
	provider := newTestProvider(t)
	assert.Equal(t, len(provider.NodeGroups()), 0)

	registered := provider.azureManager.RegisterAsg(
		newTestScaleSet(provider.azureManager, "test-asg"))
	assert.True(t, registered)
	assert.Equal(t, len(provider.NodeGroups()), 1)
}

func TestNodeGroupForNode(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	expectedVMSSVMs := newTestVMSSVMList(3)
	expectedScaleSets := newTestVMSSList(3, "test-asg", "eastus")

	provider := newTestProvider(t)
	mockVMSSClient := mockvmssclient.NewMockInterface(ctrl)
	mockVMSSClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup).Return(expectedScaleSets, nil)
	provider.azureManager.azClient.virtualMachineScaleSetsClient = mockVMSSClient
	mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl)
	mockVMSSVMClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup, "test-asg", gomock.Any()).Return(expectedVMSSVMs, nil).AnyTimes()
	provider.azureManager.azClient.virtualMachineScaleSetVMsClient = mockVMSSVMClient

	registered := provider.azureManager.RegisterAsg(
		newTestScaleSet(provider.azureManager, "test-asg"))
	assert.True(t, registered)
	assert.Equal(t, len(provider.NodeGroups()), 1)

	node := &apiv1.Node{
		Spec: apiv1.NodeSpec{
			ProviderID: "azure://" + fmt.Sprintf(fakeVirtualMachineScaleSetVMID, 0),
		},
	}
	// refresh cache
	provider.azureManager.regenerateCache()
	group, err := provider.NodeGroupForNode(node)
	assert.NoError(t, err)
	assert.NotNil(t, group, "Group should not be nil")
	assert.Equal(t, group.Id(), "test-asg")
	assert.Equal(t, group.MinSize(), 1)
	assert.Equal(t, group.MaxSize(), 5)

	// test node in cluster that is not in a group managed by cluster autoscaler
	nodeNotInGroup := &apiv1.Node{
		Spec: apiv1.NodeSpec{
			ProviderID: "azure:///subscriptions/subscripion/resourceGroups/test-resource-group/providers/Microsoft.Compute/virtualMachines/test-instance-id-not-in-group",
		},
	}
	group, err = provider.NodeGroupForNode(nodeNotInGroup)
	assert.NoError(t, err)
	assert.Nil(t, group)
}

func TestNodeGroupForNodeWithNoProviderId(t *testing.T) {
	provider := newTestProvider(t)
	registered := provider.azureManager.RegisterAsg(
		newTestScaleSet(provider.azureManager, "test-asg"))
	assert.True(t, registered)
	assert.Equal(t, len(provider.NodeGroups()), 1)

	node := &apiv1.Node{
		Spec: apiv1.NodeSpec{
			ProviderID: "",
		},
	}
	group, err := provider.NodeGroupForNode(node)

	assert.NoError(t, err)
	assert.Equal(t, group, nil)
}

func TestBuildAzure(t *testing.T) {
	expectedConfig := &Config{
		Cloud:               "AzurePublicCloud",
		Location:            "southeastasia",
		TenantID:            "tenantId",
		SubscriptionID:      "subId",
		ResourceGroup:       "rg",
		VMType:              "vmss",
		AADClientID:         "clientId",
		AADClientSecret:     "clientsecret",
		MaxDeploymentsCount: 10,
		CloudProviderRateLimitConfig: CloudProviderRateLimitConfig{
			RateLimitConfig: azclients.RateLimitConfig{
				CloudProviderRateLimit:            false,
				CloudProviderRateLimitBucket:      5,
				CloudProviderRateLimitBucketWrite: 5,
				CloudProviderRateLimitQPS:         1,
				CloudProviderRateLimitQPSWrite:    1,
			},
			InterfaceRateLimit: &azclients.RateLimitConfig{
				CloudProviderRateLimit:            false,
				CloudProviderRateLimitBucket:      5,
				CloudProviderRateLimitBucketWrite: 5,
				CloudProviderRateLimitQPS:         1,
				CloudProviderRateLimitQPSWrite:    1,
			},
			VirtualMachineRateLimit: &azclients.RateLimitConfig{
				CloudProviderRateLimit:            false,
				CloudProviderRateLimitBucket:      5,
				CloudProviderRateLimitBucketWrite: 5,
				CloudProviderRateLimitQPS:         1,
				CloudProviderRateLimitQPSWrite:    1,
			},
			StorageAccountRateLimit: &azclients.RateLimitConfig{
				CloudProviderRateLimit:            false,
				CloudProviderRateLimitBucket:      5,
				CloudProviderRateLimitBucketWrite: 5,
				CloudProviderRateLimitQPS:         1,
				CloudProviderRateLimitQPSWrite:    1,
			},
			DiskRateLimit: &azclients.RateLimitConfig{
				CloudProviderRateLimit:            false,
				CloudProviderRateLimitBucket:      5,
				CloudProviderRateLimitBucketWrite: 5,
				CloudProviderRateLimitQPS:         1,
				CloudProviderRateLimitQPSWrite:    1,
			},
			VirtualMachineScaleSetRateLimit: &azclients.RateLimitConfig{
				CloudProviderRateLimit:            false,
				CloudProviderRateLimitBucket:      5,
				CloudProviderRateLimitBucketWrite: 5,
				CloudProviderRateLimitQPS:         1,
				CloudProviderRateLimitQPSWrite:    1,
			},
		},
	}

	cloudConfig := "cfg.json"
	azureCfg := `{
		"cloud": "AzurePublicCloud",
		"tenantId": "tenantId",
		"subscriptionId": "subId",
		"aadClientId": "clientId",
		"aadClientSecret": "clientsecret",
		"resourceGroup": "rg",
		"location": "southeastasia"
	}`
	err := ioutil.WriteFile(cloudConfig, []byte(azureCfg), 0644)
	assert.Nil(t, err)
	defer os.Remove(cloudConfig)

	os.Setenv("ARM_CLOUD", "AzurePublicCloud")
	os.Setenv("LOCATION", "southeastasia")
	os.Setenv("ARM_RESOURCE_GROUP", "rg")
	os.Setenv("ARM_SUBSCRIPTION_ID", "subId")
	os.Setenv("ARM_TENANT_ID", "tenantId")
	os.Setenv("ARM_CLIENT_ID", "clientId")
	os.Setenv("ARM_CLIENT_SECRET", "clientsecret")

	resourceLimiter := &cloudprovider.ResourceLimiter{}
	discoveryOptions := cloudprovider.NodeGroupDiscoveryOptions{}

	testCases := []struct {
		name        string
		cloudConfig string
	}{
		{
			name:        "BuildAzure should create Azure Manager using cloud-config file",
			cloudConfig: cloudConfig,
		},
		{
			name: "BuildAzure should create Azure Manager using environment variable",
		},
	}

	for _, test := range testCases {
		opts := config.AutoscalingOptions{
			CloudConfig: test.cloudConfig,
		}
		cloudProvider := BuildAzure(opts, discoveryOptions, resourceLimiter)
		assert.Equal(t, expectedConfig, cloudProvider.(*AzureCloudProvider).azureManager.config, test.name)
	}

	os.Unsetenv("ARM_CLOUD")
	os.Unsetenv("LOCATION")
	os.Unsetenv("ARM_RESOURCE_GROUP")
	os.Unsetenv("ARM_SUBSCRIPTION_ID")
	os.Unsetenv("ARM_TENANT_ID")
	os.Unsetenv("ARM_CLIENT_ID")
	os.Unsetenv("ARM_CLIENT_SECRET")
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Eric Barkie. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.

package main

import (
	"fmt"
	"time"
)

func ExampleMetar() {
	l := loop{Timestamp: time.Date(2006, time.January, 2, 15, 4, 5, 0, time.UTC)}
	fmt.Println(metar(l))

	// Output:
	// METAR 021504Z AUTO 00000KT M18/M18 A0000 RMK AO1 SLP000 T11781178
}
<commit_msg>Use proper Example naming convention<commit_after>// Copyright (c) 2016 Eric Barkie. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.

package main

import (
	"fmt"
	"time"
)

func Example_metar() {
	l := loop{Timestamp: time.Date(2006, time.January, 2, 15, 4, 5, 0, time.UTC)}
	fmt.Println(metar(l))

	// Output:
	// METAR 021504Z AUTO 00000KT M18/M18 A0000 RMK AO1 SLP000 T11781178
}
<|endoftext|>


<commit_before>package kafka

import (
	"log"

	"github.com/Shopify/sarama"
	"github.com/influxdata/telegraf/plugins/common/tls"
)

// ReadConfig for kafka clients meaning to read from Kafka.
type ReadConfig struct {
	Config
}

// SetConfig on the sarama.Config object from the ReadConfig struct.
func (k *ReadConfig) SetConfig(config *sarama.Config) error {
	config.Consumer.Return.Errors = true

	return k.Config.SetConfig(config)
}

// WriteConfig for kafka clients meaning to write to kafka
type WriteConfig struct {
	Config

	RequiredAcks     int  `toml:"required_acks"`
	MaxRetry         int  `toml:"max_retry"`
	MaxMessageBytes  int  `toml:"max_message_bytes"`
	IdempotentWrites bool `toml:"idempotent_writes"`
}

// SetConfig on the sarama.Config object from the WriteConfig struct.
func (k *WriteConfig) SetConfig(config *sarama.Config) error {
	config.Producer.Return.Successes = true
	config.Producer.Idempotent = k.IdempotentWrites
	config.Producer.Retry.Max = k.MaxRetry
	if k.MaxMessageBytes > 0 {
		config.Producer.MaxMessageBytes = k.MaxMessageBytes
	}
	config.Producer.RequiredAcks = sarama.RequiredAcks(k.RequiredAcks)
	return k.Config.SetConfig(config)
}

// Config common to all Kafka clients.
type Config struct {
	SASLAuth
	tls.ClientConfig

	Version          string `toml:"version"`
	ClientID         string `toml:"client_id"`
	CompressionCodec int    `toml:"compression_codec"`

	// EnableTLS deprecated
	EnableTLS *bool `toml:"enable_tls"`
}

// SetConfig on the sarama.Config object from the Config struct.
func (k *Config) SetConfig(config *sarama.Config) error {
	if k.EnableTLS != nil {
		log.Printf("W! [kafka] enable_tls is deprecated, and the setting does nothing, you can safely remove it from the config")
	}
	if k.Version != "" {
		version, err := sarama.ParseKafkaVersion(k.Version)
		if err != nil {
			return err
		}

		config.Version = version
	}

	if k.ClientID != "" {
		config.ClientID = k.ClientID
	} else {
		config.ClientID = "Telegraf"
	}

	config.Producer.Compression = sarama.CompressionCodec(k.CompressionCodec)

	tlsConfig, err := k.ClientConfig.TLSConfig()
	if err != nil {
		return err
	}

	if tlsConfig != nil {
		config.Net.TLS.Config = tlsConfig
		config.Net.TLS.Enable = true
	}

	return k.SetSASLConfig(config)
}
<commit_msg>Fix max open requests to one if idempotent writes is set to true (#8954)<commit_after>package kafka

import (
	"log"

	"github.com/Shopify/sarama"
	"github.com/influxdata/telegraf/plugins/common/tls"
)

// ReadConfig for kafka clients meaning to read from Kafka.
type ReadConfig struct {
	Config
}

// SetConfig on the sarama.Config object from the ReadConfig struct.
func (k *ReadConfig) SetConfig(config *sarama.Config) error {
	config.Consumer.Return.Errors = true

	return k.Config.SetConfig(config)
}

// WriteConfig for kafka clients meaning to write to kafka
type WriteConfig struct {
	Config

	RequiredAcks     int  `toml:"required_acks"`
	MaxRetry         int  `toml:"max_retry"`
	MaxMessageBytes  int  `toml:"max_message_bytes"`
	IdempotentWrites bool `toml:"idempotent_writes"`
}

// SetConfig on the sarama.Config object from the WriteConfig struct.
func (k *WriteConfig) SetConfig(config *sarama.Config) error {
	config.Producer.Return.Successes = true
	config.Producer.Idempotent = k.IdempotentWrites
	config.Producer.Retry.Max = k.MaxRetry
	if k.MaxMessageBytes > 0 {
		config.Producer.MaxMessageBytes = k.MaxMessageBytes
	}
	config.Producer.RequiredAcks = sarama.RequiredAcks(k.RequiredAcks)
	if config.Producer.Idempotent {
		config.Net.MaxOpenRequests = 1
	}
	return k.Config.SetConfig(config)
}

// Config common to all Kafka clients.
type Config struct {
	SASLAuth
	tls.ClientConfig

	Version          string `toml:"version"`
	ClientID         string `toml:"client_id"`
	CompressionCodec int    `toml:"compression_codec"`

	// EnableTLS deprecated
	EnableTLS *bool `toml:"enable_tls"`
}

// SetConfig on the sarama.Config object from the Config struct.
func (k *Config) SetConfig(config *sarama.Config) error {
	if k.EnableTLS != nil {
		log.Printf("W! [kafka] enable_tls is deprecated, and the setting does nothing, you can safely remove it from the config")
	}
	if k.Version != "" {
		version, err := sarama.ParseKafkaVersion(k.Version)
		if err != nil {
			return err
		}

		config.Version = version
	}

	if k.ClientID != "" {
		config.ClientID = k.ClientID
	} else {
		config.ClientID = "Telegraf"
	}

	config.Producer.Compression = sarama.CompressionCodec(k.CompressionCodec)

	tlsConfig, err := k.ClientConfig.TLSConfig()
	if err != nil {
		return err
	}

	if tlsConfig != nil {
		config.Net.TLS.Config = tlsConfig
		config.Net.TLS.Enable = true
	}

	return k.SetSASLConfig(config)
}
<|endoftext|>


<commit_before>// Copyright 2018 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

// Package discovery implements configuration discovery.
package discovery

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/open-policy-agent/opa/metrics"

	"github.com/sirupsen/logrus"

	"github.com/open-policy-agent/opa/ast"
	bundleApi "github.com/open-policy-agent/opa/bundle"
	"github.com/open-policy-agent/opa/config"
	"github.com/open-policy-agent/opa/download"
	"github.com/open-policy-agent/opa/plugins"
	"github.com/open-policy-agent/opa/plugins/bundle"
	"github.com/open-policy-agent/opa/plugins/logs"
	"github.com/open-policy-agent/opa/plugins/status"
	"github.com/open-policy-agent/opa/rego"
	"github.com/open-policy-agent/opa/storage/inmem"
)

// Discovery implements configuration discovery for OPA. When discovery is
// started it will periodically download a configuration bundle and try to
// reconfigure the OPA.
type Discovery struct {
	manager    *plugins.Manager
	config     *Config
	factories  map[string]plugins.Factory
	downloader *download.Downloader // discovery bundle downloader
	status     *bundle.Status       // discovery status
	etag       string               // discovery bundle etag for caching purposes
	metrics    metrics.Metrics
}

// Factories provides a set of factory functions to use for
// instantiating custom plugins.
func Factories(fs map[string]plugins.Factory) func(*Discovery) {
	return func(d *Discovery) {
		d.factories = fs
	}
}

// Metrics provides a metrics provider to pass to plugins.
func Metrics(m metrics.Metrics) func(*Discovery) {
	return func(d *Discovery) {
		d.metrics = m
	}
}

// New returns a new discovery plugin.
func New(manager *plugins.Manager, opts ...func(*Discovery)) (*Discovery, error) {

	result := &Discovery{
		manager: manager,
	}

	for _, f := range opts {
		f(result)
	}

	config, err := ParseConfig(manager.Config.Discovery, manager.Services())

	if err != nil {
		return nil, err
	} else if config == nil {
		if _, err := getPluginSet(result.factories, manager, manager.Config, result.metrics); err != nil {
			return nil, err
		}
		return result, nil
	}

	if manager.Config.PluginsEnabled() {
		return nil, fmt.Errorf("plugins cannot be specified in the bootstrap configuration when discovery enabled")
	}

	result.config = config
	result.downloader = download.New(config.Config, manager.Client(config.service), config.path).WithCallback(result.oneShot)
	result.status = &bundle.Status{
		Name: *config.Name,
	}

	return result, nil
}

// Start starts the dynamic discovery process if configured.
func (c *Discovery) Start(ctx context.Context) error {
	if c.downloader != nil {
		c.downloader.Start(ctx)
	}
	return nil
}

// Stop stops the dynamic discovery process if configured.
func (c *Discovery) Stop(ctx context.Context) {
	if c.downloader != nil {
		c.downloader.Stop(ctx)
	}
}

// Reconfigure is a no-op on discovery.
func (c *Discovery) Reconfigure(_ context.Context, _ interface{}) {

}

func (c *Discovery) oneShot(ctx context.Context, u download.Update) {

	c.processUpdate(ctx, u)

	if p := status.Lookup(c.manager); p != nil {
		p.UpdateDiscoveryStatus(*c.status)
	}
}

func (c *Discovery) processUpdate(ctx context.Context, u download.Update) {

	if u.Error != nil {
		c.logError("Discovery download failed: %v", u.Error)
		c.status.SetError(u.Error)
		return
	}

	if u.Bundle != nil {
		c.status.SetDownloadSuccess()

		if err := c.reconfigure(ctx, u); err != nil {
			c.logError("Discovery reconfiguration error occurred: %v", err)
			c.status.SetError(err)
			return
		}

		c.status.SetError(nil)
		c.status.SetActivateSuccess(u.Bundle.Manifest.Revision)
		if u.ETag != "" {
			c.logInfo("Discovery update processed successfully. Etag updated to %v.", u.ETag)
		} else {
			c.logInfo("Discovery update processed successfully.")
		}
		c.etag = u.ETag
		return
	}

	if u.ETag == c.etag {
		c.logError("Discovery update skipped, server replied with not modified.")
		c.status.SetError(nil)
		return
	}
}

func (c *Discovery) reconfigure(ctx context.Context, u download.Update) error {

	config, ps, err := processBundle(ctx, c.manager, c.factories, u.Bundle, c.config.query, c.metrics)
	if err != nil {
		return err
	}

	if err := c.manager.Reconfigure(config); err != nil {
		return err
	}

	// TODO(tsandall): we don't currently support changes to discovery
	// configuration. These changes are risky because errors would be
	// unrecoverable (without keeping track of changes and rolling back...)

	// TODO(tsandall): add protection against discovery -service- changing.
	for _, p := range ps.Start {
		if err := p.Start(ctx); err != nil {
			return err
		}
	}

	for _, p := range ps.Reconfig {
		p.Plugin.Reconfigure(ctx, p.Config)
	}

	return nil
}

func (c *Discovery) logError(fmt string, a ...interface{}) {
	logrus.WithFields(c.logrusFields()).Errorf(fmt, a...)
}

func (c *Discovery) logInfo(fmt string, a ...interface{}) {
	logrus.WithFields(c.logrusFields()).Infof(fmt, a...)
}

func (c *Discovery) logDebug(fmt string, a ...interface{}) {
	logrus.WithFields(c.logrusFields()).Debugf(fmt, a...)
}

func (c *Discovery) logrusFields() logrus.Fields {
	return logrus.Fields{
		"name":   *c.config.Name,
		"plugin": "discovery",
	}
}

func processBundle(ctx context.Context, manager *plugins.Manager, factories map[string]plugins.Factory, b *bundleApi.Bundle, query string, m metrics.Metrics) (*config.Config, *pluginSet, error) {

	config, err := evaluateBundle(ctx, manager.ID, manager.Info, b, query)
	if err != nil {
		return nil, nil, err
	}

	ps, err := getPluginSet(factories, manager, config, m)
	return config, ps, err
}

func evaluateBundle(ctx context.Context, id string, info *ast.Term, b *bundleApi.Bundle, query string) (*config.Config, error) {

	modules := b.ParsedModules("discovery")

	compiler := ast.NewCompiler()

	if compiler.Compile(modules); compiler.Failed() {
		return nil, compiler.Errors
	}

	store := inmem.NewFromObject(b.Data)

	rego := rego.New(
		rego.Query(query),
		rego.Compiler(compiler),
		rego.Store(store),
		rego.Runtime(info),
	)

	rs, err := rego.Eval(ctx)
	if err != nil {
		return nil, err
	}

	if len(rs) == 0 {
		return nil, fmt.Errorf("undefined configuration")
	}

	bs, err := json.Marshal(rs[0].Expressions[0].Value)
	if err != nil {
		return nil, err
	}

	return config.ParseConfig(bs, id)
}

type pluginSet struct {
	Start    []plugins.Plugin
	Reconfig []pluginreconfig
}

type pluginreconfig struct {
	Config interface{}
	Plugin plugins.Plugin
}

type pluginfactory struct {
	name    string
	factory plugins.Factory
	config  interface{}
}

func getPluginSet(factories map[string]plugins.Factory, manager *plugins.Manager, config *config.Config, m metrics.Metrics) (*pluginSet, error) {

	// Parse and validate plugin configurations.
	pluginNames := []string{}
	pluginFactories := []pluginfactory{}

	for k := range config.Plugins {
		f, ok := factories[k]
		if !ok {
			return nil, fmt.Errorf("plugin %q not registered", k)
		}

		c, err := f.Validate(manager, config.Plugins[k])
		if err != nil {
			return nil, err
		}

		pluginFactories = append(pluginFactories, pluginfactory{
			name:    k,
			factory: f,
			config:  c,
		})

		pluginNames = append(pluginNames, k)
	}

	// Parse and validate bundle/logs/status configurations.

	// If `bundle` was configured use that, otherwise try the new `bundles` option
	bundleConfig, err := bundle.ParseConfig(config.Bundle, manager.Services())
	if err != nil {
		return nil, err
	}
	if bundleConfig == nil {
		bundleConfig, err = bundle.ParseBundlesConfig(config.Bundles, manager.Services())
		if err != nil {
			return nil, err
		}
	}

	decisionLogsConfig, err := logs.ParseConfig(config.DecisionLogs, manager.Services(), pluginNames)
	if err != nil {
		return nil, err
	}

	statusConfig, err := status.ParseConfig(config.Status, manager.Services())
	if err != nil {
		return nil, err
	}

	// Accumulate plugins to start or reconfigure.
	starts := []plugins.Plugin{}
	reconfigs := []pluginreconfig{}

	if bundleConfig != nil {
		p, created := getBundlePlugin(manager, bundleConfig)
		if created {
			starts = append(starts, p)
		} else if p != nil {
			reconfigs = append(reconfigs, pluginreconfig{bundleConfig, p})
		}
	}

	if decisionLogsConfig != nil {
		p, created := getDecisionLogsPlugin(manager, decisionLogsConfig)
		if created {
			starts = append(starts, p)
		} else if p != nil {
			reconfigs = append(reconfigs, pluginreconfig{decisionLogsConfig, p})
		}
	}

	if statusConfig != nil {
		p, created := getStatusPlugin(manager, statusConfig, m)
		if created {
			starts = append(starts, p)
		} else if p != nil {
			reconfigs = append(reconfigs, pluginreconfig{statusConfig, p})
		}
	}

	result := &pluginSet{starts, reconfigs}

	getCustomPlugins(manager, pluginFactories, result)

	return result, nil
}

func getBundlePlugin(m *plugins.Manager, config *bundle.Config) (plugin *bundle.Plugin, created bool) {
	plugin = bundle.Lookup(m)
	if plugin == nil {
		plugin = bundle.New(config, m)
		m.Register(bundle.Name, plugin)
		registerBundleStatusUpdates(m)
		created = true
	}
	return plugin, created
}

func getDecisionLogsPlugin(m *plugins.Manager, config *logs.Config) (plugin *logs.Plugin, created bool) {
	plugin = logs.Lookup(m)
	if plugin == nil {
		plugin = logs.New(config, m)
		m.Register(logs.Name, plugin)
		created = true
	}
	return plugin, created
}

func getStatusPlugin(m *plugins.Manager, config *status.Config, metrics metrics.Metrics) (plugin *status.Plugin, created bool) {

	plugin = status.Lookup(m)

	if plugin == nil {
		plugin = status.New(config, m).WithMetrics(metrics)
		m.Register(status.Name, plugin)
		registerBundleStatusUpdates(m)
		created = true
	}

	return plugin, created
}

func getCustomPlugins(manager *plugins.Manager, factories []pluginfactory, result *pluginSet) {
	for _, pf := range factories {
		if plugin := manager.Plugin(pf.name); plugin != nil {
			result.Reconfig = append(result.Reconfig, pluginreconfig{pf.config, plugin})
		} else {
			plugin := pf.factory.New(manager, pf.config)
			manager.Register(pf.name, plugin)
			result.Start = append(result.Start, plugin)
		}
	}
}

func registerBundleStatusUpdates(m *plugins.Manager) {
	bp := bundle.Lookup(m)
	sp := status.Lookup(m)
	if bp == nil || sp == nil {
		return
	}
	type pluginlistener string

	// Depending on how the plugin was configured we will want to use different listeners
	// for backwards compatibility.
	if !bp.Config().IsMultiBundle() {
		bp.Register(pluginlistener(status.Name), func(s bundle.Status) {
			sp.UpdateBundleStatus(s)
		})
	} else {
		bp.RegisterBulkListener(pluginlistener(status.Name), func(s map[string]*bundle.Status) {
			sp.BulkUpdateBundleStatus(s)
		})
	}
}
<commit_msg>discovery: Fix log level message when on HTTP 304<commit_after>// Copyright 2018 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

// Package discovery implements configuration discovery.
package discovery

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/open-policy-agent/opa/metrics"

	"github.com/sirupsen/logrus"

	"github.com/open-policy-agent/opa/ast"
	bundleApi "github.com/open-policy-agent/opa/bundle"
	"github.com/open-policy-agent/opa/config"
	"github.com/open-policy-agent/opa/download"
	"github.com/open-policy-agent/opa/plugins"
	"github.com/open-policy-agent/opa/plugins/bundle"
	"github.com/open-policy-agent/opa/plugins/logs"
	"github.com/open-policy-agent/opa/plugins/status"
	"github.com/open-policy-agent/opa/rego"
	"github.com/open-policy-agent/opa/storage/inmem"
)

// Discovery implements configuration discovery for OPA. When discovery is
// started it will periodically download a configuration bundle and try to
// reconfigure the OPA.
type Discovery struct {
	manager    *plugins.Manager
	config     *Config
	factories  map[string]plugins.Factory
	downloader *download.Downloader // discovery bundle downloader
	status     *bundle.Status       // discovery status
	etag       string               // discovery bundle etag for caching purposes
	metrics    metrics.Metrics
}

// Factories provides a set of factory functions to use for
// instantiating custom plugins.
func Factories(fs map[string]plugins.Factory) func(*Discovery) {
	return func(d *Discovery) {
		d.factories = fs
	}
}

// Metrics provides a metrics provider to pass to plugins.
func Metrics(m metrics.Metrics) func(*Discovery) {
	return func(d *Discovery) {
		d.metrics = m
	}
}

// New returns a new discovery plugin.
func New(manager *plugins.Manager, opts ...func(*Discovery)) (*Discovery, error) {

	result := &Discovery{
		manager: manager,
	}

	for _, f := range opts {
		f(result)
	}

	config, err := ParseConfig(manager.Config.Discovery, manager.Services())

	if err != nil {
		return nil, err
	} else if config == nil {
		if _, err := getPluginSet(result.factories, manager, manager.Config, result.metrics); err != nil {
			return nil, err
		}
		return result, nil
	}

	if manager.Config.PluginsEnabled() {
		return nil, fmt.Errorf("plugins cannot be specified in the bootstrap configuration when discovery enabled")
	}

	result.config = config
	result.downloader = download.New(config.Config, manager.Client(config.service), config.path).WithCallback(result.oneShot)
	result.status = &bundle.Status{
		Name: *config.Name,
	}

	return result, nil
}

// Start starts the dynamic discovery process if configured.
func (c *Discovery) Start(ctx context.Context) error {
	if c.downloader != nil {
		c.downloader.Start(ctx)
	}
	return nil
}

// Stop stops the dynamic discovery process if configured.
func (c *Discovery) Stop(ctx context.Context) {
	if c.downloader != nil {
		c.downloader.Stop(ctx)
	}
}

// Reconfigure is a no-op on discovery.
func (c *Discovery) Reconfigure(_ context.Context, _ interface{}) {

}

func (c *Discovery) oneShot(ctx context.Context, u download.Update) {

	c.processUpdate(ctx, u)

	if p := status.Lookup(c.manager); p != nil {
		p.UpdateDiscoveryStatus(*c.status)
	}
}

func (c *Discovery) processUpdate(ctx context.Context, u download.Update) {

	if u.Error != nil {
		c.logError("Discovery download failed: %v", u.Error)
		c.status.SetError(u.Error)
		return
	}

	if u.Bundle != nil {
		c.status.SetDownloadSuccess()

		if err := c.reconfigure(ctx, u); err != nil {
			c.logError("Discovery reconfiguration error occurred: %v", err)
			c.status.SetError(err)
			return
		}

		c.status.SetError(nil)
		c.status.SetActivateSuccess(u.Bundle.Manifest.Revision)
		if u.ETag != "" {
			c.logInfo("Discovery update processed successfully. Etag updated to %v.", u.ETag)
		} else {
			c.logInfo("Discovery update processed successfully.")
		}
		c.etag = u.ETag
		return
	}

	if u.ETag == c.etag {
		c.logDebug("Discovery update skipped, server replied with not modified.")
		c.status.SetError(nil)
		return
	}
}

func (c *Discovery) reconfigure(ctx context.Context, u download.Update) error {

	config, ps, err := processBundle(ctx, c.manager, c.factories, u.Bundle, c.config.query, c.metrics)
	if err != nil {
		return err
	}

	if err := c.manager.Reconfigure(config); err != nil {
		return err
	}

	// TODO(tsandall): we don't currently support changes to discovery
	// configuration. These changes are risky because errors would be
	// unrecoverable (without keeping track of changes and rolling back...)

	// TODO(tsandall): add protection against discovery -service- changing.
	for _, p := range ps.Start {
		if err := p.Start(ctx); err != nil {
			return err
		}
	}

	for _, p := range ps.Reconfig {
		p.Plugin.Reconfigure(ctx, p.Config)
	}

	return nil
}

func (c *Discovery) logError(fmt string, a ...interface{}) {
	logrus.WithFields(c.logrusFields()).Errorf(fmt, a...)
}

func (c *Discovery) logInfo(fmt string, a ...interface{}) {
	logrus.WithFields(c.logrusFields()).Infof(fmt, a...)
}

func (c *Discovery) logDebug(fmt string, a ...interface{}) {
	logrus.WithFields(c.logrusFields()).Debugf(fmt, a...)
}

func (c *Discovery) logrusFields() logrus.Fields {
	return logrus.Fields{
		"name":   *c.config.Name,
		"plugin": "discovery",
	}
}

func processBundle(ctx context.Context, manager *plugins.Manager, factories map[string]plugins.Factory, b *bundleApi.Bundle, query string, m metrics.Metrics) (*config.Config, *pluginSet, error) {

	config, err := evaluateBundle(ctx, manager.ID, manager.Info, b, query)
	if err != nil {
		return nil, nil, err
	}

	ps, err := getPluginSet(factories, manager, config, m)
	return config, ps, err
}

func evaluateBundle(ctx context.Context, id string, info *ast.Term, b *bundleApi.Bundle, query string) (*config.Config, error) {

	modules := b.ParsedModules("discovery")

	compiler := ast.NewCompiler()

	if compiler.Compile(modules); compiler.Failed() {
		return nil, compiler.Errors
	}

	store := inmem.NewFromObject(b.Data)

	rego := rego.New(
		rego.Query(query),
		rego.Compiler(compiler),
		rego.Store(store),
		rego.Runtime(info),
	)

	rs, err := rego.Eval(ctx)
	if err != nil {
		return nil, err
	}

	if len(rs) == 0 {
		return nil, fmt.Errorf("undefined configuration")
	}

	bs, err := json.Marshal(rs[0].Expressions[0].Value)
	if err != nil {
		return nil, err
	}

	return config.ParseConfig(bs, id)
}

type pluginSet struct {
	Start    []plugins.Plugin
	Reconfig []pluginreconfig
}

type pluginreconfig struct {
	Config interface{}
	Plugin plugins.Plugin
}

type pluginfactory struct {
	name    string
	factory plugins.Factory
	config  interface{}
}

func getPluginSet(factories map[string]plugins.Factory, manager *plugins.Manager, config *config.Config, m metrics.Metrics) (*pluginSet, error) {

	// Parse and validate plugin configurations.
	pluginNames := []string{}
	pluginFactories := []pluginfactory{}

	for k := range config.Plugins {
		f, ok := factories[k]
		if !ok {
			return nil, fmt.Errorf("plugin %q not registered", k)
		}

		c, err := f.Validate(manager, config.Plugins[k])
		if err != nil {
			return nil, err
		}

		pluginFactories = append(pluginFactories, pluginfactory{
			name:    k,
			factory: f,
			config:  c,
		})

		pluginNames = append(pluginNames, k)
	}

	// Parse and validate bundle/logs/status configurations.

	// If `bundle` was configured use that, otherwise try the new `bundles` option
	bundleConfig, err := bundle.ParseConfig(config.Bundle, manager.Services())
	if err != nil {
		return nil, err
	}
	if bundleConfig == nil {
		bundleConfig, err = bundle.ParseBundlesConfig(config.Bundles, manager.Services())
		if err != nil {
			return nil, err
		}
	}

	decisionLogsConfig, err := logs.ParseConfig(config.DecisionLogs, manager.Services(), pluginNames)
	if err != nil {
		return nil, err
	}

	statusConfig, err := status.ParseConfig(config.Status, manager.Services())
	if err != nil {
		return nil, err
	}

	// Accumulate plugins to start or reconfigure.
	starts := []plugins.Plugin{}
	reconfigs := []pluginreconfig{}

	if bundleConfig != nil {
		p, created := getBundlePlugin(manager, bundleConfig)
		if created {
			starts = append(starts, p)
		} else if p != nil {
			reconfigs = append(reconfigs, pluginreconfig{bundleConfig, p})
		}
	}

	if decisionLogsConfig != nil {
		p, created := getDecisionLogsPlugin(manager, decisionLogsConfig)
		if created {
			starts = append(starts, p)
		} else if p != nil {
			reconfigs = append(reconfigs, pluginreconfig{decisionLogsConfig, p})
		}
	}

	if statusConfig != nil {
		p, created := getStatusPlugin(manager, statusConfig, m)
		if created {
			starts = append(starts, p)
		} else if p != nil {
			reconfigs = append(reconfigs, pluginreconfig{statusConfig, p})
		}
	}

	result := &pluginSet{starts, reconfigs}

	getCustomPlugins(manager, pluginFactories, result)

	return result, nil
}

func getBundlePlugin(m *plugins.Manager, config *bundle.Config) (plugin *bundle.Plugin, created bool) {
	plugin = bundle.Lookup(m)
	if plugin == nil {
		plugin = bundle.New(config, m)
		m.Register(bundle.Name, plugin)
		registerBundleStatusUpdates(m)
		created = true
	}
	return plugin, created
}

func getDecisionLogsPlugin(m *plugins.Manager, config *logs.Config) (plugin *logs.Plugin, created bool) {
	plugin = logs.Lookup(m)
	if plugin == nil {
		plugin = logs.New(config, m)
		m.Register(logs.Name, plugin)
		created = true
	}
	return plugin, created
}

func getStatusPlugin(m *plugins.Manager, config *status.Config, metrics metrics.Metrics) (plugin *status.Plugin, created bool) {

	plugin = status.Lookup(m)

	if plugin == nil {
		plugin = status.New(config, m).WithMetrics(metrics)
		m.Register(status.Name, plugin)
		registerBundleStatusUpdates(m)
		created = true
	}

	return plugin, created
}

func getCustomPlugins(manager *plugins.Manager, factories []pluginfactory, result *pluginSet) {
	for _, pf := range factories {
		if plugin := manager.Plugin(pf.name); plugin != nil {
			result.Reconfig = append(result.Reconfig, pluginreconfig{pf.config, plugin})
		} else {
			plugin := pf.factory.New(manager, pf.config)
			manager.Register(pf.name, plugin)
			result.Start = append(result.Start, plugin)
		}
	}
}

func registerBundleStatusUpdates(m *plugins.Manager) {
	bp := bundle.Lookup(m)
	sp := status.Lookup(m)
	if bp == nil || sp == nil {
		return
	}
	type pluginlistener string

	// Depending on how the plugin was configured we will want to use different listeners
	// for backwards compatibility.
	if !bp.Config().IsMultiBundle() {
		bp.Register(pluginlistener(status.Name), func(s bundle.Status) {
			sp.UpdateBundleStatus(s)
		})
	} else {
		bp.RegisterBulkListener(pluginlistener(status.Name), func(s map[string]*bundle.Status) {
			sp.BulkUpdateBundleStatus(s)
		})
	}
}
<|endoftext|>


<commit_before>package authorization

import (
	"context"
	"fmt"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	exutil "github.com/openshift/origin/test/extended/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var _ = g.Describe("[sig-auth][Feature:SCC][Early]", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLIWithoutNamespace("working-scc-during-install")

	g.It("should not have pod creation failures during install", func() {
		kubeClient := oc.AdminKubeClient()

		// we are seeting a few install-time failures, mostly around extremely early pods like CSI drivers, therefore
		// we allow a few failures here.
		numFailuresForFail := 2

		events, err := kubeClient.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())

		suiteStartTime := exutil.SuiteStartTime()
		var preTestDenialStrings, duringTestDenialStrings []string

		for _, event := range events.Items {
			if !strings.Contains(event.Message, "unable to validate against any security context constraint") {
				continue
			}

			// try with a short summary we can actually read first
			denialString := fmt.Sprintf("%v for %v.%v/%v -n %v happened %d times", event.Message, event.InvolvedObject.Kind, event.InvolvedObject.APIVersion, event.InvolvedObject.Name, event.InvolvedObject.Namespace, event.Count)

			if event.EventTime.Time.Before(suiteStartTime) {
				// SCCs become accessible to serviceaccounts based on RBAC resources.  We could require that every operator
				// apply their RBAC in order with respect to their operands by checking SARs against every kube-apiserver endpoint
				// and ensuring that the "use" for an SCC comes back correctly, but that isn't very useful.
				// We don't want to delay pods for an excessive period of time, so we will catch those pods that take more
				// than five seconds to make it through SCC
				durationPodFailed := event.LastTimestamp.Sub(event.FirstTimestamp.Time)
				if durationPodFailed < 5*time.Second {
					continue
				}
				preTestDenialStrings = append(preTestDenialStrings, denialString)
			} else {
				// Tests are not allowed to not take SCC propagation time into account, and so every during test SCC failure
				// is a hard fail so that we don't allow bad tests to get checked in.
				duringTestDenialStrings = append(duringTestDenialStrings, denialString)
			}
		}

		if numFailingPods := len(preTestDenialStrings); numFailingPods > numFailuresForFail {
			failMessage := fmt.Sprintf("%d pods failed before test on SCC errors\n%s\n", numFailingPods, strings.Join(preTestDenialStrings, "\n"))
			g.Fail(failMessage)
		}
		if numFailingPods := len(duringTestDenialStrings); numFailingPods > 0 {
			failMessage := fmt.Sprintf("%d pods failed during test on SCC errors\n%s\n", numFailingPods, strings.Join(duringTestDenialStrings, "\n"))
			g.Fail(failMessage)
		}
	})
})
<commit_msg>test: Suppress the SCC failure when a limit is present<commit_after>package authorization

import (
	"context"
	"fmt"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	"github.com/openshift/origin/pkg/test/ginkgo/result"
	exutil "github.com/openshift/origin/test/extended/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var _ = g.Describe("[sig-auth][Feature:SCC][Early]", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLIWithoutNamespace("working-scc-during-install")

	g.It("should not have pod creation failures during install", func() {
		kubeClient := oc.AdminKubeClient()

		// we are seeting a few install-time failures, mostly around extremely early pods like CSI drivers, therefore
		// we allow a few failures here.
		numFailuresForFail := 2

		events, err := kubeClient.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())

		suiteStartTime := exutil.SuiteStartTime()
		var suppressPreTestFailure bool
		if t := exutil.LimitTestsToStartTime(); !t.IsZero() {
			suppressPreTestFailure = true
			if t.After(suiteStartTime) {
				suiteStartTime = t
			}
		}

		var preTestDenialStrings, duringTestDenialStrings []string

		for _, event := range events.Items {
			if !strings.Contains(event.Message, "unable to validate against any security context constraint") {
				continue
			}

			// try with a short summary we can actually read first
			denialString := fmt.Sprintf("%v for %v.%v/%v -n %v happened %d times", event.Message, event.InvolvedObject.Kind, event.InvolvedObject.APIVersion, event.InvolvedObject.Name, event.InvolvedObject.Namespace, event.Count)

			if event.EventTime.Time.Before(suiteStartTime) {
				// SCCs become accessible to serviceaccounts based on RBAC resources.  We could require that every operator
				// apply their RBAC in order with respect to their operands by checking SARs against every kube-apiserver endpoint
				// and ensuring that the "use" for an SCC comes back correctly, but that isn't very useful.
				// We don't want to delay pods for an excessive period of time, so we will catch those pods that take more
				// than five seconds to make it through SCC
				durationPodFailed := event.LastTimestamp.Sub(event.FirstTimestamp.Time)
				if durationPodFailed < 5*time.Second {
					continue
				}
				preTestDenialStrings = append(preTestDenialStrings, denialString)
			} else {
				// Tests are not allowed to not take SCC propagation time into account, and so every during test SCC failure
				// is a hard fail so that we don't allow bad tests to get checked in.
				duringTestDenialStrings = append(duringTestDenialStrings, denialString)
			}
		}

		if numFailingPods := len(preTestDenialStrings); numFailingPods > numFailuresForFail {
			failMessage := fmt.Sprintf("%d pods failed before test on SCC errors\n%s\n", numFailingPods, strings.Join(preTestDenialStrings, "\n"))
			if suppressPreTestFailure {
				result.Flakef("pre-test environment had disruption and limited this test, suppressing failure: %s", failMessage)
			} else {
				g.Fail(failMessage)
			}
		}
		if numFailingPods := len(duringTestDenialStrings); numFailingPods > 0 {
			failMessage := fmt.Sprintf("%d pods failed during test on SCC errors\n%s\n", numFailingPods, strings.Join(duringTestDenialStrings, "\n"))
			g.Fail(failMessage)
		}
	})
})
<|endoftext|>


<commit_before>package gameprocessor

import (
	"gopkg.in/tomb.v2"

	"github.com/beevee/switchers"
)

// GameProcessor contains all in-game logic
type GameProcessor struct {
	TrumpCode        string
	TeamQuorum       int
	TeamMinSize      int
	PlayerRepository switchers.PlayerRepository
	RoundRepository  switchers.RoundRepository
	TaskRepository   switchers.TaskRepository
	Bot              switchers.Bot
	Logger           switchers.Logger
	tomb             tomb.Tomb
}

// Start initializes loops that make game go round
func (gp *GameProcessor) Start() error {
	gp.tomb.Go(gp.gameProgressor)

	return nil
}

// Stop gracefully stops loops
func (gp *GameProcessor) Stop() error {
	gp.tomb.Kill(nil)
	return gp.tomb.Wait()
}

// ExecuteCommand takes text command from a player, updates internal state and returns response
func (gp *GameProcessor) ExecuteCommand(command string, playerID string) {
	player, created, err := gp.PlayerRepository.GetOrCreatePlayer(playerID)
	if err != nil {
		gp.Logger.Log("msg", "error retrieving player profile while executing command", "error", err)
	}
	if created {
		gp.Logger.Log("msg", "created player profile", "playerid", player.ID)
	}

	if command == gp.TrumpCode {
		if err := gp.PlayerRepository.SetTrump(player, true); err != nil {
			gp.Bot.SendMessage(player.ID, responseSomethingWrong)
			gp.Logger.Log("msg", "failed to make player Trump", "error", err)
			return
		}
	}

	if player.Trump {
		gp.executeTrumpCommand(command, player)
	} else {
		gp.executePlayerCommand(command, player)
	}
}
<commit_msg>Execute commands for different players in different goroutines<commit_after>package gameprocessor

import (
	"gopkg.in/tomb.v2"

	"github.com/beevee/switchers"
)

// GameProcessor contains all in-game logic
type GameProcessor struct {
	TrumpCode             string
	TeamQuorum            int
	TeamMinSize           int
	PlayerRepository      switchers.PlayerRepository
	RoundRepository       switchers.RoundRepository
	TaskRepository        switchers.TaskRepository
	Bot                   switchers.Bot
	Logger                switchers.Logger
	playerCommandChannels map[string]chan string
	tomb                  tomb.Tomb
}

// Start initializes loops that make game go round
func (gp *GameProcessor) Start() error {
	gp.playerCommandChannels = make(map[string]chan string)

	gp.tomb.Go(gp.gameProgressor)

	return nil
}

// Stop gracefully stops loops
func (gp *GameProcessor) Stop() error {
	gp.tomb.Kill(nil)
	return gp.tomb.Wait()
}

// ExecuteCommand takes text command from a player and schedules it for execution in a separate channel for exch user
func (gp *GameProcessor) ExecuteCommand(command string, playerID string) {
	_, exists := gp.playerCommandChannels[playerID]

	if !exists {
		gp.playerCommandChannels[playerID] = make(chan string, 1000)
		gp.tomb.Go(func() error {
			gp.playerCommandExecutor(playerID, gp.playerCommandChannels[playerID])
			return nil
		})
		gp.Logger.Log("msg", "created new command executor goroutine for player", "playerid", playerID)
	}

	gp.playerCommandChannels[playerID] <- command
}

func (gp *GameProcessor) playerCommandExecutor(playerID string, playerCommands <-chan string) {
	for {
		select {
		case command := <-playerCommands:
			player, created, err := gp.PlayerRepository.GetOrCreatePlayer(playerID)
			if err != nil {
				gp.Logger.Log("msg", "error retrieving player profile while executing command", "error", err)
			}
			if created {
				gp.Logger.Log("msg", "created player profile", "playerid", player.ID)
			}

			if command == gp.TrumpCode {
				if err := gp.PlayerRepository.SetTrump(player, true); err != nil {
					gp.Bot.SendMessage(player.ID, responseSomethingWrong)
					gp.Logger.Log("msg", "failed to make player Trump", "error", err)
					return
				}
			}

			if player.Trump {
				gp.executeTrumpCommand(command, player)
			} else {
				gp.executePlayerCommand(command, player)
			}

		case <-gp.tomb.Dying():
			gp.Logger.Log("msg", "aborted command executor goroutine for player", "playerid", playerID)
			return
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
)

// LogResp logs all the responses to clients
// It does this by replacing the default ResponseWriter with a custom one
func LogResp(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ip := getIPAddress(r)
		log.Printf("%s - Received req for %s\n", ip, r.URL.Path)
		logger := responseLogger{w: w, ip: ip}
		fn(logger, r)
	}
}

// MustParams checks for the existence of all specified params in the request
// If they don't exist, the request is declined as BadRequest (400)
func MustParams(fn http.HandlerFunc, params ...string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		for _, param := range params {
			if len(r.Form.Get(param)) == 0 {
				errortext := fmt.Sprintf("Expected parameter %s not found", param)
				http.Error(w, errortext, http.StatusBadRequest)
				return
			}
		}
		fn(w, r)
	}
}

// SimpleAuth checks if a password has been set in the ENV and
// compares it to the request's password
// If they don't match, the request is declined as Unauthorized (401)
func SimpleAuth(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		linktopassword := os.Getenv(passwordEnv)
		if len(linktopassword) > 0 {
			password := r.Form.Get("password")
			if linktopassword != password {
				errortext := "Password param incorrect"
				http.Error(w, errortext, http.StatusUnauthorized)
				return
			}
		}
		fn(w, r)
	}
}

// RateLimit checks if the client making the request has been making
// more than numreq requests in the specified duration
// If it has, the request is declined as TooManyRequests (429)
func RateLimit(fn http.HandlerFunc, duration, numreq int, store ExpireStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ip := getIPAddress(r)
		requests, err := store.Get(ip)
		if err != nil || requests < numreq {
			store.Incr(ip, duration)
			fn(w, r)
			return
		}
		ttl, _ := store.TTL(ip)
		errortext := fmt.Sprintf("You've sent too many requests in a short span of time. Try again after %d seconds", ttl)
		http.Error(w, errortext, 429)
	}
}

// CORS enables Cross-origin resource sharing for this request.
func CORS(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
	}
}

func getIPAddress(r *http.Request) string {
	ip := r.Header.Get("X-Forwarded-For") // assuming its behind nginx
	if len(ip) > 0 {
		return ip
	}
	return strings.Split(r.RemoteAddr, ":")[0]
}

type responseLogger struct {
	w  http.ResponseWriter
	ip string
}

func (r responseLogger) Header() http.Header {
	return r.w.Header()
}

func (r responseLogger) Write(b []byte) (int, error) {
	log.Printf("%s - %s", r.ip, string(b))
	return r.w.Write(b)
}

func (r responseLogger) WriteHeader(code int) {
	log.Printf("%s - Returned code %d\n", r.ip, code)
	r.w.WriteHeader(code)
}
<commit_msg>Fix not calling fn(w,r) in CORS function<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
)

// LogResp logs all the responses to clients
// It does this by replacing the default ResponseWriter with a custom one
func LogResp(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ip := getIPAddress(r)
		log.Printf("%s - Received req for %s\n", ip, r.URL.Path)
		logger := responseLogger{w: w, ip: ip}
		fn(logger, r)
	}
}

// MustParams checks for the existence of all specified params in the request
// If they don't exist, the request is declined as BadRequest (400)
func MustParams(fn http.HandlerFunc, params ...string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		for _, param := range params {
			if len(r.Form.Get(param)) == 0 {
				errortext := fmt.Sprintf("Expected parameter %s not found", param)
				http.Error(w, errortext, http.StatusBadRequest)
				return
			}
		}
		fn(w, r)
	}
}

// SimpleAuth checks if a password has been set in the ENV and
// compares it to the request's password
// If they don't match, the request is declined as Unauthorized (401)
func SimpleAuth(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		linktopassword := os.Getenv(passwordEnv)
		if len(linktopassword) > 0 {
			password := r.Form.Get("password")
			if linktopassword != password {
				errortext := "Password param incorrect"
				http.Error(w, errortext, http.StatusUnauthorized)
				return
			}
		}
		fn(w, r)
	}
}

// RateLimit checks if the client making the request has been making
// more than numreq requests in the specified duration
// If it has, the request is declined as TooManyRequests (429)
func RateLimit(fn http.HandlerFunc, duration, numreq int, store ExpireStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ip := getIPAddress(r)
		requests, err := store.Get(ip)
		if err != nil || requests < numreq {
			store.Incr(ip, duration)
			fn(w, r)
			return
		}
		ttl, _ := store.TTL(ip)
		errortext := fmt.Sprintf("You've sent too many requests in a short span of time. Try again after %d seconds", ttl)
		http.Error(w, errortext, 429)
	}
}

// CORS enables Cross-origin resource sharing for this request.
func CORS(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
		fn(w, r)
	}
}

func getIPAddress(r *http.Request) string {
	ip := r.Header.Get("X-Forwarded-For") // assuming its behind nginx
	if len(ip) > 0 {
		return ip
	}
	return strings.Split(r.RemoteAddr, ":")[0]
}

type responseLogger struct {
	w  http.ResponseWriter
	ip string
}

func (r responseLogger) Header() http.Header {
	return r.w.Header()
}

func (r responseLogger) Write(b []byte) (int, error) {
	log.Printf("%s - %s", r.ip, string(b))
	return r.w.Write(b)
}

func (r responseLogger) WriteHeader(code int) {
	log.Printf("%s - Returned code %d\n", r.ip, code)
	r.w.WriteHeader(code)
}
<|endoftext|>


<commit_before>// Copyright 2016 Mender Software AS
//
//    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 main

import (
	"github.com/mendersoftware/go-lib-micro/mongo/migrate"
	"github.com/pkg/errors"
	"gopkg.in/mgo.v2"
)

const (
	DbVersion = "0.0.1"
	DbName    = "deployment_service"
)

func MigrateDb(version string, migrations []migrate.Migration, session *mgo.Session) error {
	m := migrate.DummyMigrator{
		Session: session,
		Db:      DbName,
	}

	ver, err := migrate.NewVersion(version)
	if err != nil {
		return errors.Wrap(err, "failed to parse service version")
	}

	err = m.Apply(ver, migrations)
	if err != nil {
		return errors.Wrap(err, "failed to apply migrations")
	}

	return nil
}
<commit_msg>migrations: update to accomodate go-lib-micro API changes<commit_after>// Copyright 2016 Mender Software AS
//
//    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 main

import (
	"context"

	"github.com/mendersoftware/go-lib-micro/mongo/migrate"
	"github.com/pkg/errors"
	"gopkg.in/mgo.v2"
)

const (
	DbVersion = "0.0.1"
	DbName    = "deployment_service"
)

func MigrateDb(ctx context.Context, version string, migrations []migrate.Migration, session *mgo.Session) error {
	m := migrate.DummyMigrator{
		Session: session,
		Db:      DbName,
	}

	ver, err := migrate.NewVersion(version)
	if err != nil {
		return errors.Wrap(err, "failed to parse service version")
	}

	err = m.Apply(ctx, *ver, migrations)
	if err != nil {
		return errors.Wrap(err, "failed to apply migrations")
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"unsafe"

	"github.com/Sirupsen/logrus"
)

const mapMaxSize = 1e4

func main() {
	for _, asset := range AssetNames() {
		mmapAsset(asset)
	}
}

func mmapAsset(assetName string) {
	logrus.Infof("Exporting asset: %s", assetName)
	asset, err := Asset(assetName)
	if err != nil {
		logrus.Fatalf("Failed to load the asset %q: %v", assetName, err)
	}

	length := len(asset)
	size := int(unsafe.Sizeof(0)) * length
	if size > mapMaxSize*int(unsafe.Sizeof(0)) {
		logrus.Fatalf("File too big for current map size: %d > %d", size, mapMaxSize*int(unsafe.Sizeof(0)))
	}

	filename := strings.Replace(assetName, "/", "_", -1)
	filepath := fmt.Sprintf("/tmp/mb-%s", filename)
	logrus.Infof("Creating map file: %q", filepath)
	mapFile, err := os.Create(filepath)
	if err != nil {
		logrus.Fatalf("Failed to create map file: %v", err)
	}

	logrus.Infof("Seeking file")
	if _, err = mapFile.Seek(int64(length-1), 0); err != nil {
		logrus.Fatalf("Failed to seek: %v", err)
	}

	logrus.Infof("Writing to file")
	if _, err = mapFile.Write([]byte(" ")); err != nil {
		logrus.Fatalf("Failed to write to file: %v", err)
	}

	logrus.Infof("MMAPing")
	fd := int(mapFile.Fd())
	mmap, err := syscall.Mmap(fd, 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
	if err != nil {
		logrus.Fatalf("Failed to mmap: %v", err)
	}

	logrus.Infof("Filling array var")
	mapArray := (*[mapMaxSize]byte)(unsafe.Pointer(&mmap[0]))
	for i := 0; i < length; i++ {
		mapArray[i] = asset[i]
	}
	// fmt.Println(*mapArray)

	logrus.Infof("MUNMAPing")
	if err = syscall.Munmap(mmap); err != nil {
		logrus.Fatalf("Failed to munmap: %v", err)
	}

	logrus.Infof("Closing")
	if err = mapFile.Close(); err != nil {
		logrus.Fatalf("Failed to close: %v", err)
	}

	logrus.Infof("Executing binary")
	cmd := exec.Command(filepath)
	output, err := cmd.CombinedOutput()
	if err != nil {
		logrus.Fatalf("Failed to execute program: %v", err)
	}
	logrus.Infof("Output: %s", output)
}
<commit_msg>Chmoding binary<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"unsafe"

	"github.com/Sirupsen/logrus"
)

const mapMaxSize = 1e4

func main() {
	for _, asset := range AssetNames() {
		mmapAsset(asset)
	}
}

func mmapAsset(assetName string) {
	logrus.Infof("Exporting asset: %s", assetName)
	asset, err := Asset(assetName)
	if err != nil {
		logrus.Fatalf("Failed to load the asset %q: %v", assetName, err)
	}

	length := len(asset)
	size := int(unsafe.Sizeof(0)) * length
	if size > mapMaxSize*int(unsafe.Sizeof(0)) {
		logrus.Fatalf("File too big for current map size: %d > %d", size, mapMaxSize*int(unsafe.Sizeof(0)))
	}

	filename := strings.Replace(assetName, "/", "_", -1)
	filepath := fmt.Sprintf("/tmp/mb-%s", filename)
	logrus.Infof("Creating map file: %q", filepath)
	mapFile, err := os.Create(filepath)
	if err != nil {
		logrus.Fatalf("Failed to create map file: %v", err)
	}

	logrus.Infof("Seeking file")
	if _, err = mapFile.Seek(int64(length-1), 0); err != nil {
		logrus.Fatalf("Failed to seek: %v", err)
	}

	logrus.Infof("Writing to file")
	if _, err = mapFile.Write([]byte(" ")); err != nil {
		logrus.Fatalf("Failed to write to file: %v", err)
	}

	logrus.Infof("MMAPing")
	fd := int(mapFile.Fd())
	mmap, err := syscall.Mmap(fd, 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
	if err != nil {
		logrus.Fatalf("Failed to mmap: %v", err)
	}

	logrus.Infof("Filling array var")
	mapArray := (*[mapMaxSize]byte)(unsafe.Pointer(&mmap[0]))
	for i := 0; i < length; i++ {
		mapArray[i] = asset[i]
	}
	// fmt.Println(*mapArray)

	logrus.Infof("MUNMAPing")
	if err = syscall.Munmap(mmap); err != nil {
		logrus.Fatalf("Failed to munmap: %v", err)
	}

	logrus.Infof("Closing")
	if err = mapFile.Close(); err != nil {
		logrus.Fatalf("Failed to close: %v", err)
	}

	logrus.Infof("Chmoding binary")
	if err = os.Chmod(filepath, 0777); err != nil {
		logrus.Fatalf("Failed to chmod program: %v", err)
	}

	logrus.Infof("Executing binary")
	cmd := exec.Command(filepath)
	output, err := cmd.CombinedOutput()
	if err != nil {
		logrus.Fatalf("Failed to execute program: %v", err)
	}
	logrus.Infof("Output: %s", output)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/asaskevich/govalidator"
	"github.com/elico/go-linux-tproxy"
	"net"
	"net/http"
  "errors"
)

func noRedirect(req *http.Request, via []*http.Request) error {
        return errors.New("Don't redirect!")
}

func main() {
	fakeIp := "192.168.101.200:0"
	var netTransport = &http.Transport{
		Dial: (func(network, addr string) (net.Conn, error) {
			// Resolve address
			//if the address is an IP
			host, port, err := net.SplitHostPort(addr)
			if err != nil {
				return nil, err
			}
			switch {
			case govalidator.IsIP(host):
				srvConn, err := tproxy.TcpDial(fakeIp, addr)
				if err != nil {
					return nil, err
				}
				return srvConn, nil
			case govalidator.IsDNSName(host):

				ips, err := net.LookupIP(host)
				if err != nil {
					return nil, err
				}
				for i, ip := range ips {
					srvConn, err := tproxy.TcpDial(fakeIp, net.JoinHostPort(ip.String(), port))
					if err != nil {
            fmt.Println(err)
						if i == len(ips) {
							return srvConn, nil
						}
						continue
					}
          fmt.Println("returning a srvconn")
					return srvConn, nil
				}
				srvConn, err := tproxy.TcpDial(fakeIp, addr)
				if err != nil {
					return nil, err
				}
				return srvConn, nil
			}
      return nil, nil
		}),
	}
	client := &http.Client{Transport: netTransport, CheckRedirect: noRedirect, }
	resp, err := client.Get("http://www.google.com/")
	if err != nil && resp == nil{
		fmt.Println(err)
		return
	}
	fmt.Println(resp)

}
<commit_msg>gofmt applied to the example file<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/asaskevich/govalidator"
	"github.com/elico/go-linux-tproxy"
	"net"
	"net/http"
)

func noRedirect(req *http.Request, via []*http.Request) error {
	return errors.New("Don't redirect!")
}

func main() {
	fakeIp := "192.168.101.200:0"
	var netTransport = &http.Transport{
		Dial: (func(network, addr string) (net.Conn, error) {
			// Resolve address
			//if the address is an IP
			host, port, err := net.SplitHostPort(addr)
			if err != nil {
				return nil, err
			}
			switch {
			case govalidator.IsIP(host):
				srvConn, err := tproxy.TcpDial(fakeIp, addr)
				if err != nil {
					return nil, err
				}
				return srvConn, nil
			case govalidator.IsDNSName(host):

				ips, err := net.LookupIP(host)
				if err != nil {
					return nil, err
				}
				for i, ip := range ips {
					srvConn, err := tproxy.TcpDial(fakeIp, net.JoinHostPort(ip.String(), port))
					if err != nil {
						fmt.Println(err)
						if i == len(ips) {
							return srvConn, nil
						}
						continue
					}
					fmt.Println("returning a srvconn")
					return srvConn, nil
				}
				srvConn, err := tproxy.TcpDial(fakeIp, addr)
				if err != nil {
					return nil, err
				}
				return srvConn, nil
			}
			return nil, nil
		}),
	}
	client := &http.Client{Transport: netTransport, CheckRedirect: noRedirect}
	resp, err := client.Get("http://www.google.com/")
	if err != nil && resp == nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp)

}
<|endoftext|>


<commit_before>// +build !windows

package filesystem

import (
	"os"
	userpkg "os/user"
	"strconv"

	"github.com/pkg/errors"
)

// OwnershipSpecification is an opaque type that encodes specification of file
// and/or directory ownership.
type OwnershipSpecification struct {
	// ownerID encodes the POSIX user ID associated with the ownership
	// specification. A value of -1 indicates the absence of specification. The
	// availability of -1 as a sentinel value for omission is guaranteed by the
	// POSIX definition of chmod.
	ownerID int
	// groupID encodes the POSIX user ID associated with the ownership
	// specification. A value of -1 indicates the absence of specification. The
	// availability of -1 as a sentinel value for omission is guaranteed by the
	// POSIX definition of chmod.
	groupID int
}

// NewOwnershipSpecification parsers owner and group specifications and resolves
// their system-level identifiers.
func NewOwnershipSpecification(owner, group string) (*OwnershipSpecification, error) {
	// Attempt to parse and look up owner user, if specified.
	ownerID := -1
	if owner != "" {
		switch kind, identifier := ParseOwnershipIdentifier(owner); kind {
		case OwnershipIdentifierKindInvalid:
			return nil, errors.New("invalid user specification")
		case OwnershipIdentifierKindPOSIXID:
			if _, err := userpkg.LookupId(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup user by ID")
			} else if userID, err := strconv.Atoi(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to convert user ID to numeric value")
			} else {
				ownerID = userID
			}
		case OwnershipIdentifierKindWindowsSID:
			return nil, errors.New("Windows SIDs not supported on POSIX systems")
		case OwnershipIdentifierKindName:
			if userObject, err := userpkg.Lookup(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup user by ID")
			} else if userID, err := strconv.Atoi(userObject.Uid); err != nil {
				return nil, errors.Wrap(err, "unable to convert user ID to numeric value")
			} else {
				ownerID = userID
			}
		default:
			panic("unhandled ownership identifier kind")
		}
	}

	// Attempt to parse and look up group, if specified.
	groupID := -1
	if group != "" {
		switch kind, identifier := ParseOwnershipIdentifier(group); kind {
		case OwnershipIdentifierKindInvalid:
			return nil, errors.New("invalid group specification")
		case OwnershipIdentifierKindPOSIXID:
			if _, err := userpkg.LookupGroupId(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup group by ID")
			} else if g, err := strconv.Atoi(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to convert group ID to numeric value")
			} else {
				groupID = g
			}
		case OwnershipIdentifierKindWindowsSID:
			return nil, errors.New("Windows SIDs not supported on POSIX systems")
		case OwnershipIdentifierKindName:
			if groupObject, err := userpkg.LookupGroup(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup group by ID")
			} else if g, err := strconv.Atoi(groupObject.Gid); err != nil {
				return nil, errors.Wrap(err, "unable to convert group ID to numeric value")
			} else {
				groupID = g
			}
		default:
			panic("unhandled ownership identifier kind")
		}
	}

	// Success.
	return &OwnershipSpecification{
		ownerID: ownerID,
		groupID: groupID,
	}, nil
}

// SetPermissionsByPath sets the permissions on the content at the specified
// path. Ownership information is set first, followed by permissions extracted
// from the mode using ModePermissionsMask. Ownership setting can be skipped
// completely by providing a nil OwnershipSpecification or a specification with
// both components unset. An OwnershipSpecification may also include only
// certain components, in which case only those components will be set.
// Permission setting can be skipped by providing a mode value that yields 0
// after permission bit masking.
func SetPermissionsByPath(path string, ownership *OwnershipSpecification, mode Mode) error {
	// Set ownership information, if specified.
	if ownership != nil && (ownership.ownerID != -1 || ownership.groupID != -1) {
		if err := os.Chown(path, ownership.ownerID, ownership.groupID); err != nil {
			return errors.Wrap(err, "unable to set ownership information")
		}
	}

	// Set permissions, if specified.
	mode = mode & ModePermissionsMask
	if mode != 0 {
		if err := os.Chmod(path, os.FileMode(mode)); err != nil {
			return errors.Wrap(err, "unable to set permission bits")
		}
	}

	// Success.
	return nil
}
<commit_msg>Added check for negative user and group IDs on POSIX systems.<commit_after>// +build !windows

package filesystem

import (
	"os"
	userpkg "os/user"
	"strconv"

	"github.com/pkg/errors"
)

// OwnershipSpecification is an opaque type that encodes specification of file
// and/or directory ownership.
type OwnershipSpecification struct {
	// ownerID encodes the POSIX user ID associated with the ownership
	// specification. A value of -1 indicates the absence of specification. The
	// availability of -1 as a sentinel value for omission is guaranteed by the
	// POSIX definition of chmod.
	ownerID int
	// groupID encodes the POSIX user ID associated with the ownership
	// specification. A value of -1 indicates the absence of specification. The
	// availability of -1 as a sentinel value for omission is guaranteed by the
	// POSIX definition of chmod.
	groupID int
}

// NewOwnershipSpecification parsers owner and group specifications and resolves
// their system-level identifiers.
func NewOwnershipSpecification(owner, group string) (*OwnershipSpecification, error) {
	// Attempt to parse and look up owner user, if specified.
	ownerID := -1
	if owner != "" {
		switch kind, identifier := ParseOwnershipIdentifier(owner); kind {
		case OwnershipIdentifierKindInvalid:
			return nil, errors.New("invalid user specification")
		case OwnershipIdentifierKindPOSIXID:
			if _, err := userpkg.LookupId(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup user by ID")
			} else if u, err := strconv.Atoi(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to convert user ID to numeric value")
			} else if u < 0 {
				return nil, errors.New("negative user ID")
			} else {
				ownerID = u
			}
		case OwnershipIdentifierKindWindowsSID:
			return nil, errors.New("Windows SIDs not supported on POSIX systems")
		case OwnershipIdentifierKindName:
			if userObject, err := userpkg.Lookup(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup user by ID")
			} else if u, err := strconv.Atoi(userObject.Uid); err != nil {
				return nil, errors.Wrap(err, "unable to convert user ID to numeric value")
			} else if u < 0 {
				return nil, errors.New("negative user ID retrieved")
			} else {
				ownerID = u
			}
		default:
			panic("unhandled ownership identifier kind")
		}
	}

	// Attempt to parse and look up group, if specified.
	groupID := -1
	if group != "" {
		switch kind, identifier := ParseOwnershipIdentifier(group); kind {
		case OwnershipIdentifierKindInvalid:
			return nil, errors.New("invalid group specification")
		case OwnershipIdentifierKindPOSIXID:
			if _, err := userpkg.LookupGroupId(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup group by ID")
			} else if g, err := strconv.Atoi(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to convert group ID to numeric value")
			} else if g < 0 {
				return nil, errors.New("negative group ID")
			} else {
				groupID = g
			}
		case OwnershipIdentifierKindWindowsSID:
			return nil, errors.New("Windows SIDs not supported on POSIX systems")
		case OwnershipIdentifierKindName:
			if groupObject, err := userpkg.LookupGroup(identifier); err != nil {
				return nil, errors.Wrap(err, "unable to lookup group by ID")
			} else if g, err := strconv.Atoi(groupObject.Gid); err != nil {
				return nil, errors.Wrap(err, "unable to convert group ID to numeric value")
			} else if g < 0 {
				return nil, errors.New("negative group ID retrieved")
			} else {
				groupID = g
			}
		default:
			panic("unhandled ownership identifier kind")
		}
	}

	// Success.
	return &OwnershipSpecification{
		ownerID: ownerID,
		groupID: groupID,
	}, nil
}

// SetPermissionsByPath sets the permissions on the content at the specified
// path. Ownership information is set first, followed by permissions extracted
// from the mode using ModePermissionsMask. Ownership setting can be skipped
// completely by providing a nil OwnershipSpecification or a specification with
// both components unset. An OwnershipSpecification may also include only
// certain components, in which case only those components will be set.
// Permission setting can be skipped by providing a mode value that yields 0
// after permission bit masking.
func SetPermissionsByPath(path string, ownership *OwnershipSpecification, mode Mode) error {
	// Set ownership information, if specified.
	if ownership != nil && (ownership.ownerID != -1 || ownership.groupID != -1) {
		if err := os.Chown(path, ownership.ownerID, ownership.groupID); err != nil {
			return errors.Wrap(err, "unable to set ownership information")
		}
	}

	// Set permissions, if specified.
	mode = mode & ModePermissionsMask
	if mode != 0 {
		if err := os.Chmod(path, os.FileMode(mode)); err != nil {
			return errors.Wrap(err, "unable to set permission bits")
		}
	}

	// Success.
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The cert-manager 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 client

import (
	"crypto/x509"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/Venafi/vcert/v4/pkg/certificate"

	"github.com/cert-manager/cert-manager/pkg/issuer/venafi/client/api"
	"github.com/cert-manager/cert-manager/pkg/util/pki"
)

// ErrCustomFieldsType provides a common error structure for an invalid Venafi custom field type
type ErrCustomFieldsType struct {
	Type api.CustomFieldType
}

func (err ErrCustomFieldsType) Error() string {
	return fmt.Sprintf("certificate request contains an invalid Venafi custom fields type: %q", err.Type)
}

var ErrorMissingSubject = errors.New("Certificate requests submitted to Venafi issuers must have the 'commonName' field or at least one other subject field set.")

// This function sends a request to Venafi to for a signed certificate.
// The CSR will be decoded to be validated against the zone configuration policy.
// Upon the template being successfully defaulted and validated, the CSR will be sent, as is.
// It will return a pickup ID which can be used with RetrieveCertificate to get the certificate
func (v *Venafi) RequestCertificate(csrPEM []byte, duration time.Duration, customFields []api.CustomField) (string, error) {
	vreq, err := v.buildVReq(csrPEM, duration, customFields)
	if err != nil {
		return "", err
	}
	return v.vcertClient.RequestCertificate(vreq)
}

func (v *Venafi) RetrieveCertificate(pickupID string, csrPEM []byte, duration time.Duration, customFields []api.CustomField) ([]byte, error) {
	vreq, err := v.buildVReq(csrPEM, duration, customFields)
	if err != nil {
		return nil, err
	}

	vreq.PickupID = pickupID
	vreq.Timeout = time.Second * 10

	// Retrieve the certificate from request
	pemCollection, err := v.vcertClient.RetrieveCertificate(vreq)
	if err != nil {
		return nil, err
	}

	// Construct the certificate chain and return the new keypair
	cs := append([]string{pemCollection.Certificate}, pemCollection.Chain...)
	chain := strings.Join(cs, "\n")

	return []byte(chain), nil
}

func (v *Venafi) buildVReq(csrPEM []byte, duration time.Duration, customFields []api.CustomField) (*certificate.Request, error) {
	// Retrieve a copy of the Venafi zone.
	// This contains default values and policy control info that we can apply
	// and check against locally.
	zoneCfg, err := v.vcertClient.ReadZoneConfiguration()
	if err != nil {
		return nil, err
	}

	tmpl, err := pki.GenerateTemplateFromCSRPEM(csrPEM, duration, false)
	if err != nil {
		return nil, err
	}

	if tmpl.Subject.String() == "" {
		return nil, ErrorMissingSubject
	}

	// Create a vcert Request structure
	vreq := newVRequest(tmpl)

	// Convert over custom fields from our struct type to venafi's
	vfields, err := convertCustomFieldsToVcert(customFields)
	if err != nil {
		return nil, err
	}
	vreq.CustomFields = append(vreq.CustomFields, vfields...)

	// Apply default values from the Venafi zone
	zoneCfg.UpdateCertificateRequest(vreq)

	// Here we are validating the request using the current policy with
	// defaulting applied to the CSR. The CSR we send will not be defaulted
	// however, as this will be done again server side.
	err = zoneCfg.ValidateCertificateRequest(vreq)
	if err != nil {
		return nil, err
	}

	friendlyName, err := getVcertFriendlyName(tmpl)
	if err != nil {
		return nil, err
	}
	vreq.FriendlyName = friendlyName

	// Set options on the request
	vreq.CsrOrigin = certificate.UserProvidedCSR

	// Set the request CSR with the passed value
	if err := vreq.SetCSR(csrPEM); err != nil {
		return nil, err
	}

	return vreq, nil
}

func convertCustomFieldsToVcert(customFields []api.CustomField) ([]certificate.CustomField, error) {
	var out []certificate.CustomField
	if len(customFields) > 0 {
		for _, field := range customFields {
			var fieldType certificate.CustomFieldType
			switch field.Type {
			case api.CustomFieldTypePlain, "":
				fieldType = certificate.CustomFieldPlain
			default:
				return nil, ErrCustomFieldsType{Type: field.Type}
			}

			out = append(out, certificate.CustomField{
				Type:  fieldType,
				Name:  field.Name,
				Value: field.Value,
			})
		}
	}

	return out, nil
}

func newVRequest(cert *x509.Certificate) *certificate.Request {
	req := certificate.NewRequest(cert)
	req.ChainOption = certificate.ChainOptionRootLast

	// overwrite entire Subject block
	req.Subject = cert.Subject
	// Add cert-manager origin tag
	req.CustomFields = []certificate.CustomField{
		{
			Type:  certificate.CustomFieldOrigin,
			Value: "cert-manager",
		},
	}
	return req
}

func getVcertFriendlyName(crt *x509.Certificate) (string, error) {
	// Set the 'ObjectName' through the vcert friendly name. This is set in
	// order of precedence CN->DNS->URI.
	switch {
	case len(crt.Subject.CommonName) > 0:
		return crt.Subject.CommonName, nil
	case len(crt.DNSNames) > 0:
		return crt.DNSNames[0], nil
	case len(crt.URIs) > 0:
		return crt.URIs[0].String(), nil
	case len(crt.EmailAddresses) > 0:
		return crt.EmailAddresses[0], nil
	case len(crt.IPAddresses) > 0:
		return crt.IPAddresses[0].String(), nil
	default:
		return "", errors.New("certificate request contains no Common Name, DNS Name, nor URI SAN, at least one must be supplied to be used as the Venafi certificate objects name")
	}
}
<commit_msg>Increase Venafi issuer timeout on retrieving certificate<commit_after>/*
Copyright 2020 The cert-manager 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 client

import (
	"crypto/x509"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/Venafi/vcert/v4/pkg/certificate"

	"github.com/cert-manager/cert-manager/pkg/issuer/venafi/client/api"
	"github.com/cert-manager/cert-manager/pkg/util/pki"
)

// ErrCustomFieldsType provides a common error structure for an invalid Venafi custom field type
type ErrCustomFieldsType struct {
	Type api.CustomFieldType
}

func (err ErrCustomFieldsType) Error() string {
	return fmt.Sprintf("certificate request contains an invalid Venafi custom fields type: %q", err.Type)
}

var ErrorMissingSubject = errors.New("Certificate requests submitted to Venafi issuers must have the 'commonName' field or at least one other subject field set.")

// This function sends a request to Venafi to for a signed certificate.
// The CSR will be decoded to be validated against the zone configuration policy.
// Upon the template being successfully defaulted and validated, the CSR will be sent, as is.
// It will return a pickup ID which can be used with RetrieveCertificate to get the certificate
func (v *Venafi) RequestCertificate(csrPEM []byte, duration time.Duration, customFields []api.CustomField) (string, error) {
	vreq, err := v.buildVReq(csrPEM, duration, customFields)
	if err != nil {
		return "", err
	}
	return v.vcertClient.RequestCertificate(vreq)
}

func (v *Venafi) RetrieveCertificate(pickupID string, csrPEM []byte, duration time.Duration, customFields []api.CustomField) ([]byte, error) {
	vreq, err := v.buildVReq(csrPEM, duration, customFields)
	if err != nil {
		return nil, err
	}

	vreq.PickupID = pickupID
	vreq.Timeout = time.Second * 60

	// Retrieve the certificate from request
	pemCollection, err := v.vcertClient.RetrieveCertificate(vreq)
	if err != nil {
		return nil, err
	}

	// Construct the certificate chain and return the new keypair
	cs := append([]string{pemCollection.Certificate}, pemCollection.Chain...)
	chain := strings.Join(cs, "\n")

	return []byte(chain), nil
}

func (v *Venafi) buildVReq(csrPEM []byte, duration time.Duration, customFields []api.CustomField) (*certificate.Request, error) {
	// Retrieve a copy of the Venafi zone.
	// This contains default values and policy control info that we can apply
	// and check against locally.
	zoneCfg, err := v.vcertClient.ReadZoneConfiguration()
	if err != nil {
		return nil, err
	}

	tmpl, err := pki.GenerateTemplateFromCSRPEM(csrPEM, duration, false)
	if err != nil {
		return nil, err
	}

	if tmpl.Subject.String() == "" {
		return nil, ErrorMissingSubject
	}

	// Create a vcert Request structure
	vreq := newVRequest(tmpl)

	// Convert over custom fields from our struct type to venafi's
	vfields, err := convertCustomFieldsToVcert(customFields)
	if err != nil {
		return nil, err
	}
	vreq.CustomFields = append(vreq.CustomFields, vfields...)

	// Apply default values from the Venafi zone
	zoneCfg.UpdateCertificateRequest(vreq)

	// Here we are validating the request using the current policy with
	// defaulting applied to the CSR. The CSR we send will not be defaulted
	// however, as this will be done again server side.
	err = zoneCfg.ValidateCertificateRequest(vreq)
	if err != nil {
		return nil, err
	}

	friendlyName, err := getVcertFriendlyName(tmpl)
	if err != nil {
		return nil, err
	}
	vreq.FriendlyName = friendlyName

	// Set options on the request
	vreq.CsrOrigin = certificate.UserProvidedCSR

	// Set the request CSR with the passed value
	if err := vreq.SetCSR(csrPEM); err != nil {
		return nil, err
	}

	return vreq, nil
}

func convertCustomFieldsToVcert(customFields []api.CustomField) ([]certificate.CustomField, error) {
	var out []certificate.CustomField
	if len(customFields) > 0 {
		for _, field := range customFields {
			var fieldType certificate.CustomFieldType
			switch field.Type {
			case api.CustomFieldTypePlain, "":
				fieldType = certificate.CustomFieldPlain
			default:
				return nil, ErrCustomFieldsType{Type: field.Type}
			}

			out = append(out, certificate.CustomField{
				Type:  fieldType,
				Name:  field.Name,
				Value: field.Value,
			})
		}
	}

	return out, nil
}

func newVRequest(cert *x509.Certificate) *certificate.Request {
	req := certificate.NewRequest(cert)
	req.ChainOption = certificate.ChainOptionRootLast

	// overwrite entire Subject block
	req.Subject = cert.Subject
	// Add cert-manager origin tag
	req.CustomFields = []certificate.CustomField{
		{
			Type:  certificate.CustomFieldOrigin,
			Value: "cert-manager",
		},
	}
	return req
}

func getVcertFriendlyName(crt *x509.Certificate) (string, error) {
	// Set the 'ObjectName' through the vcert friendly name. This is set in
	// order of precedence CN->DNS->URI.
	switch {
	case len(crt.Subject.CommonName) > 0:
		return crt.Subject.CommonName, nil
	case len(crt.DNSNames) > 0:
		return crt.DNSNames[0], nil
	case len(crt.URIs) > 0:
		return crt.URIs[0].String(), nil
	case len(crt.EmailAddresses) > 0:
		return crt.EmailAddresses[0], nil
	case len(crt.IPAddresses) > 0:
		return crt.IPAddresses[0].String(), nil
	default:
		return "", errors.New("certificate request contains no Common Name, DNS Name, nor URI SAN, at least one must be supplied to be used as the Venafi certificate objects name")
	}
}
<|endoftext|>