<commit_before>// (C) Copyright 2021 Hewlett Packard Enterprise Development LP
//
// 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 oneview

import (
	"fmt"
	"testing"

	"github.com/HewlettPackard/oneview-golang/ov"
	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/terraform"
)

func TestAccApplianceSNMPv1TrapDestinations_1(t *testing.T) {
	var ApplianceSNMPv1TrapDestinations ov.SNMPv1Trap

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckApplianceSNMPv1TrapDestinationsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccApplianceSNMPv1TrapDestinations,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckApplianceSNMPv1TrapDestinationsExists(
						"oneview_appliance_snmp_v1_trap_destinations.test", &ApplianceSNMPv1TrapDestinations),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "destination_address", "1.1.1.1",
					),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "destination_id", "4",
					),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "community_string", "Test1",
					),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "port", "162",
					),
				),
			},
			{
				ResourceName:      testAccApplianceSNMPv1TrapDestinations,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckApplianceSNMPv1TrapDestinationsExists(n string, SNMPv1TrapDestinations *ov.SNMPv1Trap) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found :%v", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		config, err := testProviderConfig()
		if err != nil {
			return err
		}

		testSNMPv1TrapDestinations, err := config.ovClient.GetSNMPv1TrapDestinationsById(rs.Primary.ID)
		if err != nil {
			return err
		}
		*SNMPv1TrapDestinations = testSNMPv1TrapDestinations
		return nil
	}
}

func testAccCheckApplianceSNMPv1TrapDestinationsDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "oneview_appliance_snmp_v1_trap_destinations" {
			continue
		}

		testTrap, _ := config.ovClient.GetSNMPv1TrapDestinationsById(rs.Primary.ID)

		if testTrap.ID != "" {
			return fmt.Errorf("ApplianceSNMPv1TrapDestinations still exists")
		}
	}

	return nil
}

var testAccApplianceSNMPv1TrapDestinations = `resource "oneview_appliance_snmp_v1_trap_destinations" "test" {
    destination_address = "1.1.1.1"
    port = 162
    community_string = "Test1"
    destination_id = "4"
}`
<commit_msg>Fix test<commit_after>// (C) Copyright 2021 Hewlett Packard Enterprise Development LP
//
// 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 oneview

import (
	"fmt"
	"testing"

	"github.com/HewlettPackard/oneview-golang/ov"
	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/terraform"
)

func TestAccApplianceSNMPv1TrapDestinations_1(t *testing.T) {
	var ApplianceSNMPv1TrapDestinations ov.SNMPv1Trap

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckApplianceSNMPv1TrapDestinationsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccApplianceSNMPv1TrapDestinations,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckApplianceSNMPv1TrapDestinationsExists(
						"oneview_appliance_snmp_v1_trap_destinations.test", &ApplianceSNMPv1TrapDestinations),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "destination_address", "1.1.1.1",
					),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "destination_id", "4",
					),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "community_string", "Test1",
					),
					resource.TestCheckResourceAttr(
						"oneview_appliance_snmp_v1_trap_destinations.test", "port", "162",
					),
				),
			},
			{
				ResourceName:      testAccApplianceSNMPv1TrapDestinations,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckApplianceSNMPv1TrapDestinationsExists(n string, SNMPv1TrapDestinations *ov.SNMPv1Trap) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found :%v", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		config, err := testProviderConfig()
		if err != nil {
			return err
		}

		testSNMPv1TrapDestinations, err := config.ovClient.GetSNMPv1TrapDestinationsById(rs.Primary.ID)
		if err != nil {
			return err
		}
		*SNMPv1TrapDestinations = testSNMPv1TrapDestinations
		return nil
	}
}

func testAccCheckApplianceSNMPv1TrapDestinationsDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "oneview_appliance_snmp_v1_trap_destinations" {
			continue
		}

		testTrap, _ := config.ovClient.GetSNMPv1TrapDestinationsById(rs.Primary.ID)

		if testTrap.Destination != "" {
			return fmt.Errorf("ApplianceSNMPv1TrapDestinations still exists")
		}
	}

	return nil
}

var testAccApplianceSNMPv1TrapDestinations = `resource "oneview_appliance_snmp_v1_trap_destinations" "test" {
    destination_address = "1.1.1.1"
    port = 162
    community_string = "Test1"
    destination_id = "4"
}`
<|endoftext|>


<commit_before>package engine

import (
	"errors"
	"fmt"

	"github.com/keybase/go/libkb"
	keybase_1 "github.com/keybase/protocol/go"
)

type Doctor struct {
	user       *libkb.User
	docUI      libkb.DoctorUI
	secretUI   libkb.SecretUI
	logUI      libkb.LogUI
	identifyUI libkb.IdentifyUI

	signingKey libkb.GenericKey
}

func NewDoctor(docUI libkb.DoctorUI, secUI libkb.SecretUI, logUI libkb.LogUI, identifyUI libkb.IdentifyUI) *Doctor {
	return &Doctor{docUI: docUI, secretUI: secUI, logUI: logUI, identifyUI: identifyUI}
}

func (d *Doctor) LoginCheckup(u *libkb.User) error {
	d.user = u

	// This can fail, but we'll warn if it does.
	d.syncSecrets()

	if err := d.checkUID(); err != nil {
		return err
	}

	if err := d.checkKeys(); err != nil {
		return err
	}
	return nil
}

// checkUID makes sure that we've verified our own UID.  This might result in a
// self-tracking operation.
func (d *Doctor) checkUID() (err error) {
	uid := d.user.GetUid()
	if u2 := G.Env.GetVerifiedUID(); u2 != nil && !u2.Eq(uid) {
		err = libkb.UidMismatchError{Msg: fmt.Sprintf("Got wrong uid; wanted %s but got %s", uid, u2)}
	} else if u2 == nil && d.identifyUI != nil {
		d.logUI.Warning("Verifying your UID...")
		err = d.user.IdentifySelf(d.identifyUI)
		if err == nil {
			d.logUI.Warning("Setting UID to %s", uid)
		}
	}
	return err
}

func (d *Doctor) syncSecrets() (err error) {
	if err = G.SecretSyncer.Load(d.user.GetUid()); err != nil {
		G.Log.Warning("Problem syncing secrets from server: %s", err.Error())
	}
	return err
}

func (d *Doctor) checkKeys() error {
	kf := d.user.GetKeyFamily()
	if kf == nil {
		return d.addBasicKeys()
	}
	if kf.GetEldest() == nil {
		return d.addBasicKeys()
	}

	// they have at least one key

	dkey, err := d.user.GetDeviceSibkey()
	if err == nil && dkey != nil {
		// they have a device sibkey for this device
		return nil
	}

	// make sure secretsyncer loaded
	err = G.SecretSyncer.Load(d.user.GetUid())
	if err != nil {
		return err
	}

	if G.SecretSyncer.HasDevices() {
		// they have at least one device, just not this device...
		return d.deviceSign()
	}

	// they don't have any devices.  use their detkey to sign a new device.
	dk, err := d.detkey()
	if err != nil {
		return err
	}
	return d.addDeviceKeyWithDetKey(dk)
}

// addBasicKeys is used for accounts that have no device or det
// keys.
func (d *Doctor) addBasicKeys() error {
	if err := d.addDeviceKey(); err != nil {
		return err
	}

	if err := d.addDetKey(); err != nil {
		return err
	}

	return nil
}

func (d *Doctor) addDeviceKey() error {
	// XXX session id...what to put there?
	devname, err := d.docUI.PromptDeviceName(0)
	if err != nil {
		return err
	}
	tk, err := d.tspkey()
	if err != nil {
		return err
	}
	eng := NewDeviceEngine(d.user, d.logUI)
	if err := eng.Run(devname, tk.LksClientHalf()); err != nil {
		return err
	}

	d.signingKey = eng.EldestKey()
	return nil
}

func (d *Doctor) addDeviceKeyWithDetKey(eldest libkb.GenericKey) error {
	// XXX session id...what to put there?
	devname, err := d.docUI.PromptDeviceName(0)
	if err != nil {
		return err
	}
	tk, err := d.tspkey()
	if err != nil {
		return err
	}
	eng := NewDeviceEngine(d.user, d.logUI)
	if err := eng.RunWithDetKey(devname, tk.LksClientHalf(), eldest); err != nil {
		return fmt.Errorf("RunWithDetKey error: %s", err)
	}

	d.signingKey = eng.EldestKey()
	return nil
}

func (d *Doctor) addDetKey() error {
	tk, err := d.tspkey()
	if err != nil {
		return err
	}
	eng := NewDetKeyEngine(d.user, d.signingKey, d.logUI)
	return eng.Run(tk)
}

var ErrNotYetImplemented = errors.New("not yet implemented")

func (d *Doctor) deviceSign() error {
	d.docUI.SelectSigner()
	return ErrNotYetImplemented
}

func (d *Doctor) tspkey() (*libkb.TSPassKey, error) {
	t := G.LoginState.GetCachedTSPassKey()
	if t != nil {
		return t, nil
	}

	// not cached: get it from the ui
	pp, err := d.secretUI.GetKeybasePassphrase(keybase_1.GetKeybasePassphraseArg{Username: G.Env.GetUsername()})
	if err != nil {
		return nil, err
	}
	err = G.LoginState.StretchKey(pp)
	if err != nil {
		return nil, err
	}
	return G.LoginState.GetCachedTSPassKey(), nil
}

func (d *Doctor) detkey() (libkb.GenericKey, error) {
	// get server half of detkey via ss
	half, err := G.SecretSyncer.FindDetKeySrvHalf(libkb.KEY_TYPE_KB_NACL_EDDSA_SERVER_HALF)
	if err != nil {
		return nil, err
	}

	// regenerate the detkey
	tk, err := d.tspkey()
	if err != nil {
		return nil, err
	}

	detkey, err := GenSigningDetKey(tk, half)
	if err != nil {
		return nil, err
	}
	return detkey, nil
}
<commit_msg>getting devices for ui<commit_after>package engine

import (
	"errors"
	"fmt"

	"github.com/keybase/go/libkb"
	keybase_1 "github.com/keybase/protocol/go"
)

type Doctor struct {
	user       *libkb.User
	docUI      libkb.DoctorUI
	secretUI   libkb.SecretUI
	logUI      libkb.LogUI
	identifyUI libkb.IdentifyUI

	signingKey libkb.GenericKey
}

func NewDoctor(docUI libkb.DoctorUI, secUI libkb.SecretUI, logUI libkb.LogUI, identifyUI libkb.IdentifyUI) *Doctor {
	return &Doctor{docUI: docUI, secretUI: secUI, logUI: logUI, identifyUI: identifyUI}
}

func (d *Doctor) LoginCheckup(u *libkb.User) error {
	d.user = u

	// This can fail, but we'll warn if it does.
	d.syncSecrets()

	if err := d.checkUID(); err != nil {
		return err
	}

	if err := d.checkKeys(); err != nil {
		return err
	}
	return nil
}

// checkUID makes sure that we've verified our own UID.  This might result in a
// self-tracking operation.
func (d *Doctor) checkUID() (err error) {
	uid := d.user.GetUid()
	if u2 := G.Env.GetVerifiedUID(); u2 != nil && !u2.Eq(uid) {
		err = libkb.UidMismatchError{Msg: fmt.Sprintf("Got wrong uid; wanted %s but got %s", uid, u2)}
	} else if u2 == nil && d.identifyUI != nil {
		d.logUI.Warning("Verifying your UID...")
		err = d.user.IdentifySelf(d.identifyUI)
		if err == nil {
			d.logUI.Warning("Setting UID to %s", uid)
		}
	}
	return err
}

func (d *Doctor) syncSecrets() (err error) {
	if err = G.SecretSyncer.Load(d.user.GetUid()); err != nil {
		G.Log.Warning("Problem syncing secrets from server: %s", err.Error())
	}
	return err
}

func (d *Doctor) checkKeys() error {
	kf := d.user.GetKeyFamily()
	if kf == nil {
		return d.addBasicKeys()
	}
	if kf.GetEldest() == nil {
		return d.addBasicKeys()
	}

	// they have at least one key

	dkey, err := d.user.GetDeviceSibkey()
	if err == nil && dkey != nil {
		// they have a device sibkey for this device
		return nil
	}

	// make sure secretsyncer loaded
	err = G.SecretSyncer.Load(d.user.GetUid())
	if err != nil {
		return err
	}

	if G.SecretSyncer.HasDevices() {
		// they have at least one device, just not this device...
		return d.deviceSign()
	}

	// they don't have any devices.  use their detkey to sign a new device.
	dk, err := d.detkey()
	if err != nil {
		return err
	}
	return d.addDeviceKeyWithDetKey(dk)
}

// addBasicKeys is used for accounts that have no device or det
// keys.
func (d *Doctor) addBasicKeys() error {
	if err := d.addDeviceKey(); err != nil {
		return err
	}

	if err := d.addDetKey(); err != nil {
		return err
	}

	return nil
}

func (d *Doctor) addDeviceKey() error {
	// XXX session id...what to put there?
	devname, err := d.docUI.PromptDeviceName(0)
	if err != nil {
		return err
	}
	tk, err := d.tspkey()
	if err != nil {
		return err
	}
	eng := NewDeviceEngine(d.user, d.logUI)
	if err := eng.Run(devname, tk.LksClientHalf()); err != nil {
		return err
	}

	d.signingKey = eng.EldestKey()
	return nil
}

func (d *Doctor) addDeviceKeyWithDetKey(eldest libkb.GenericKey) error {
	// XXX session id...what to put there?
	devname, err := d.docUI.PromptDeviceName(0)
	if err != nil {
		return err
	}
	tk, err := d.tspkey()
	if err != nil {
		return err
	}
	eng := NewDeviceEngine(d.user, d.logUI)
	if err := eng.RunWithDetKey(devname, tk.LksClientHalf(), eldest); err != nil {
		return fmt.Errorf("RunWithDetKey error: %s", err)
	}

	d.signingKey = eng.EldestKey()
	return nil
}

func (d *Doctor) addDetKey() error {
	tk, err := d.tspkey()
	if err != nil {
		return err
	}
	eng := NewDetKeyEngine(d.user, d.signingKey, d.logUI)
	return eng.Run(tk)
}

var ErrNotYetImplemented = errors.New("not yet implemented")

func (d *Doctor) deviceSign() error {
	devs, err := G.SecretSyncer.Devices()
	if err != nil {
		return err
	}

	for k, v := range devs {
		G.Log.Info("Device %s: %+v", k, v)
	}

	_, err = d.docUI.SelectSigner()
	if err != nil {
		return err
	}
	return ErrNotYetImplemented
}

func (d *Doctor) tspkey() (*libkb.TSPassKey, error) {
	t := G.LoginState.GetCachedTSPassKey()
	if t != nil {
		return t, nil
	}

	// not cached: get it from the ui
	pp, err := d.secretUI.GetKeybasePassphrase(keybase_1.GetKeybasePassphraseArg{Username: G.Env.GetUsername()})
	if err != nil {
		return nil, err
	}
	err = G.LoginState.StretchKey(pp)
	if err != nil {
		return nil, err
	}
	return G.LoginState.GetCachedTSPassKey(), nil
}

func (d *Doctor) detkey() (libkb.GenericKey, error) {
	// get server half of detkey via ss
	half, err := G.SecretSyncer.FindDetKeySrvHalf(libkb.KEY_TYPE_KB_NACL_EDDSA_SERVER_HALF)
	if err != nil {
		return nil, err
	}

	// regenerate the detkey
	tk, err := d.tspkey()
	if err != nil {
		return nil, err
	}

	detkey, err := GenSigningDetKey(tk, half)
	if err != nil {
		return nil, err
	}
	return detkey, nil
}
<|endoftext|>


<commit_before>package globalnamespaceaccess

import (
	"encoding/base32"
	"fmt"
	"strings"

	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/norman/types/slice"
	"github.com/rancher/types/apis/management.cattle.io/v3"
	"github.com/rancher/types/client/management/v3"

	"github.com/rancher/norman/api/access"
	managementschema "github.com/rancher/types/apis/management.cattle.io/v3/schema"
	"k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

type MemberAccess struct {
	Users              v3.UserInterface
	RoleTemplateLister v3.RoleTemplateLister
	PrtbLister         v3.ProjectRoleTemplateBindingLister
	CrtbLister         v3.ClusterRoleTemplateBindingLister
}

const (
	ImpersonateUserHeader  = "Impersonate-User"
	ImpersonateGroupHeader = "Impersonate-Group"
	OwnerAccess            = "owner"
	ReadonlyAccess         = "read-only"
	localPrincipalPrefix   = "local://"
)

func (ma *MemberAccess) CheckCallerAccessToTargets(request *types.APIContext, targets []string, resourceType string, into interface{}) error {
	for _, targetID := range targets {
		if err := access.ByID(request, &managementschema.Version, resourceType, targetID, into); err != nil {
			return err
		}
	}
	return nil
}

func (ma *MemberAccess) EnsureRoleInTargets(targetProjects, roleTemplates []string, callerID string) error {
	newProjectRoleTemplateMap := make(map[string]bool)
	newClusterRoleTemplateMap := make(map[string]bool)
	projects := make(map[string]bool)
	clusters := make(map[string]bool)
	for _, r := range roleTemplates {
		rt, err := ma.RoleTemplateLister.Get("", r)
		if err != nil {
			return err
		}
		switch rt.Context {
		case "project":
			if !newProjectRoleTemplateMap[r] {
				newProjectRoleTemplateMap[r] = true
			}
		case "cluster":
			if !newClusterRoleTemplateMap[r] {
				newClusterRoleTemplateMap[r] = true
			}
		}
	}
	for _, t := range targetProjects {
		split := strings.SplitN(t, ":", 2)
		if len(split) != 2 {
			return fmt.Errorf("invalid project ID %v", t)
		}
		clusterName := split[0]
		projectName := split[1]

		if !projects[projectName] {
			projects[projectName] = true
		}
		if !clusters[clusterName] {
			clusters[clusterName] = true
		}
	}

	for pname := range projects {
		projectRoleTemplateFoundCount := 0
		prtbs, err := ma.PrtbLister.List(pname, labels.NewSelector())
		if err != nil {
			return err
		}
		for _, prtb := range prtbs {
			if prtb.UserName == callerID && newProjectRoleTemplateMap[prtb.RoleTemplateName] {
				projectRoleTemplateFoundCount++
			}
		}
		if projectRoleTemplateFoundCount != len(newProjectRoleTemplateMap) {
			return fmt.Errorf("user %v does not have all project roles provided in project %v", callerID, pname)
		}
	}
	for cname := range clusters {
		clusterRoleTemplateFoundCount := 0
		crtbs, err := ma.CrtbLister.List(cname, labels.NewSelector())
		if err != nil {
			return err
		}
		for _, crtb := range crtbs {
			if crtb.UserName == callerID && newClusterRoleTemplateMap[crtb.RoleTemplateName] {
				clusterRoleTemplateFoundCount++
			}
		}
		if clusterRoleTemplateFoundCount != len(newClusterRoleTemplateMap) {
			return fmt.Errorf("user %v does not have all cluster roles provided in cluster %v", callerID, cname)
		}
	}
	return nil
}

// CheckAccessToUpdateMembers checks if the request is updating members list, and if the caller has permission to do so
func CheckAccessToUpdateMembers(members []v3.Member, data map[string]interface{}, ownerAccess bool) error {
	var requestUpdatesMembers bool
	// Check if members are being updated, if yes, make sure only member with owner permission is making this update request
	newMembers := convert.ToMapSlice(data[client.GlobalDNSFieldMembers])
	originalMembers := members
	if len(newMembers) != len(originalMembers) && !ownerAccess {
		return fmt.Errorf("only members with owner access can update members")
	}

	newMemberAccessType := make(map[string]string)
	for _, m := range newMembers {
		if _, ok := m[client.MemberFieldUserPrincipalID]; ok {
			newMemberAccessType[convert.ToString(m[client.MemberFieldUserPrincipalID])] = convert.ToString(m[client.MemberFieldAccessType])
		}
		if _, ok := m[client.MemberFieldGroupPrincipalID]; ok {
			newMemberAccessType[convert.ToString(m[client.MemberFieldGroupPrincipalID])] = convert.ToString(m[client.MemberFieldAccessType])
		}
	}

	originalMemberAccessType := make(map[string]string)
	originalMembersFoundInRequest := make(map[string]bool) // map to check whether all existing members are present in the current request, if not then this request is trying to update members list
	for _, m := range originalMembers {
		if m.UserPrincipalName != "" {
			originalMemberAccessType[m.UserPrincipalName] = m.AccessType
		}
		if m.GroupPrincipalName != "" {
			originalMemberAccessType[m.GroupPrincipalName] = m.AccessType
		}
	}

	// go through all members in the current request, check if each exists in the original global DNS
	// if it exists, check that the access type hasn't changed, if it has changed, this means the req is updating members
	// if the member from req doesn't exist in original global DNS, this means the new request is adding a new member, hence updating members list
	for key, accessType := range newMemberAccessType {
		if val, ok := originalMemberAccessType[key]; ok {
			if val != accessType {
				requestUpdatesMembers = true
				break
			}
			// mark this original member as present in the current request
			originalMembersFoundInRequest[key] = true
		} else {
			requestUpdatesMembers = true
			break
		}
	}
	if requestUpdatesMembers && !ownerAccess {
		return fmt.Errorf("only members with owner access can add new members")
	}

	// at this point, all members in the new request have been found in the original global DNS with the same access type
	// but we need to check if all members from the original global DNS are also present in the current request
	for member := range originalMemberAccessType {
		// if any member is not found, this means the current request is updating members list by deleting this member
		if !originalMembersFoundInRequest[member] && !ownerAccess {
			return fmt.Errorf("only members with owner access can delete existing members")
		}
	}
	return nil
}

func (ma *MemberAccess) GetAccessTypeOfCaller(callerID, creatorID, name string, members []v3.Member) (string, error) {
	var username string
	if callerID == creatorID {
		return OwnerAccess, nil
	}
	for _, m := range members {
		if m.UserName == "" && m.UserPrincipalName != "" {
			user, err := ma.getUserFromUserPrincipalID(m.UserPrincipalName)
			if err != nil {
				return "", err
			}
			if user == nil {
				return "", fmt.Errorf("no user found for principal %v", m.UserPrincipalName)
			}
			if user.Name == callerID {
				username = user.Name
			}
		} else if m.UserName == callerID {
			username = m.UserName
		}
		if username != "" { // found the caller
			return m.AccessType, nil
		}
	}
	return "", fmt.Errorf("user %v is not in members list", callerID)
}

func (ma *MemberAccess) getUserFromUserPrincipalID(userPrincipalID string) (*v3.User, error) {
	encodedPrincipalID := base32.HexEncoding.WithPadding(base32.NoPadding).EncodeToString([]byte(userPrincipalID))
	if len(encodedPrincipalID) > 63 {
		encodedPrincipalID = encodedPrincipalID[:63]
	}
	set := labels.Set(map[string]string{encodedPrincipalID: "hashed-principal-name"})
	usersList, err := ma.Users.List(v1.ListOptions{LabelSelector: set.String()})
	if err != nil {
		return nil, err
	}

	if len(usersList.Items) == 0 {
		// check for local auth principals
		if strings.HasPrefix(userPrincipalID, localPrincipalPrefix) {
			userID := strings.TrimPrefix(userPrincipalID, localPrincipalPrefix)
			user, err := ma.Users.Controller().Lister().Get("", userID)
			return user, err
		}
		return nil, nil
	}

	var match *v3.User
	for _, u := range usersList.Items {
		if slice.ContainsString(u.PrincipalIDs, userPrincipalID) {
			if match != nil {
				// error out on duplicates
				return nil, fmt.Errorf("can't find unique user for principal %v", userPrincipalID)
			}
			match = &u
		}
	}
	return match, nil
}
<commit_msg>Throw 422 when any of the mcapp.Roles is invalid/does not exist<commit_after>package globalnamespaceaccess

import (
	"encoding/base32"
	"fmt"
	"strings"

	"github.com/rancher/norman/api/access"
	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/norman/types/slice"
	"github.com/rancher/types/apis/management.cattle.io/v3"
	managementschema "github.com/rancher/types/apis/management.cattle.io/v3/schema"
	"github.com/rancher/types/client/management/v3"

	"github.com/rancher/norman/httperror"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

type MemberAccess struct {
	Users              v3.UserInterface
	RoleTemplateLister v3.RoleTemplateLister
	PrtbLister         v3.ProjectRoleTemplateBindingLister
	CrtbLister         v3.ClusterRoleTemplateBindingLister
}

const (
	ImpersonateUserHeader  = "Impersonate-User"
	ImpersonateGroupHeader = "Impersonate-Group"
	OwnerAccess            = "owner"
	ReadonlyAccess         = "read-only"
	localPrincipalPrefix   = "local://"
)

func (ma *MemberAccess) CheckCallerAccessToTargets(request *types.APIContext, targets []string, resourceType string, into interface{}) error {
	for _, targetID := range targets {
		if err := access.ByID(request, &managementschema.Version, resourceType, targetID, into); err != nil {
			return err
		}
	}
	return nil
}

func (ma *MemberAccess) EnsureRoleInTargets(targetProjects, roleTemplates []string, callerID string) error {
	newProjectRoleTemplateMap := make(map[string]bool)
	newClusterRoleTemplateMap := make(map[string]bool)
	projects := make(map[string]bool)
	clusters := make(map[string]bool)
	for _, r := range roleTemplates {
		rt, err := ma.RoleTemplateLister.Get("", r)
		if err != nil {
			if apierrors.IsNotFound(err) {
				return httperror.WrapAPIError(err, httperror.InvalidBodyContent, "Role "+r+" does not exist")
			}
			return err
		}
		switch rt.Context {
		case "project":
			if !newProjectRoleTemplateMap[r] {
				newProjectRoleTemplateMap[r] = true
			}
		case "cluster":
			if !newClusterRoleTemplateMap[r] {
				newClusterRoleTemplateMap[r] = true
			}
		}
	}
	for _, t := range targetProjects {
		split := strings.SplitN(t, ":", 2)
		if len(split) != 2 {
			return fmt.Errorf("invalid project ID %v", t)
		}
		clusterName := split[0]
		projectName := split[1]

		if !projects[projectName] {
			projects[projectName] = true
		}
		if !clusters[clusterName] {
			clusters[clusterName] = true
		}
	}

	for pname := range projects {
		projectRoleTemplateFoundCount := 0
		prtbs, err := ma.PrtbLister.List(pname, labels.NewSelector())
		if err != nil {
			return err
		}
		for _, prtb := range prtbs {
			if prtb.UserName == callerID && newProjectRoleTemplateMap[prtb.RoleTemplateName] {
				projectRoleTemplateFoundCount++
			}
		}
		if projectRoleTemplateFoundCount != len(newProjectRoleTemplateMap) {
			return fmt.Errorf("user %v does not have all project roles provided in project %v", callerID, pname)
		}
	}
	for cname := range clusters {
		clusterRoleTemplateFoundCount := 0
		crtbs, err := ma.CrtbLister.List(cname, labels.NewSelector())
		if err != nil {
			return err
		}
		for _, crtb := range crtbs {
			if crtb.UserName == callerID && newClusterRoleTemplateMap[crtb.RoleTemplateName] {
				clusterRoleTemplateFoundCount++
			}
		}
		if clusterRoleTemplateFoundCount != len(newClusterRoleTemplateMap) {
			return fmt.Errorf("user %v does not have all cluster roles provided in cluster %v", callerID, cname)
		}
	}
	return nil
}

// CheckAccessToUpdateMembers checks if the request is updating members list, and if the caller has permission to do so
func CheckAccessToUpdateMembers(members []v3.Member, data map[string]interface{}, ownerAccess bool) error {
	var requestUpdatesMembers bool
	// Check if members are being updated, if yes, make sure only member with owner permission is making this update request
	newMembers := convert.ToMapSlice(data[client.GlobalDNSFieldMembers])
	originalMembers := members
	if len(newMembers) != len(originalMembers) && !ownerAccess {
		return fmt.Errorf("only members with owner access can update members")
	}

	newMemberAccessType := make(map[string]string)
	for _, m := range newMembers {
		if _, ok := m[client.MemberFieldUserPrincipalID]; ok {
			newMemberAccessType[convert.ToString(m[client.MemberFieldUserPrincipalID])] = convert.ToString(m[client.MemberFieldAccessType])
		}
		if _, ok := m[client.MemberFieldGroupPrincipalID]; ok {
			newMemberAccessType[convert.ToString(m[client.MemberFieldGroupPrincipalID])] = convert.ToString(m[client.MemberFieldAccessType])
		}
	}

	originalMemberAccessType := make(map[string]string)
	originalMembersFoundInRequest := make(map[string]bool) // map to check whether all existing members are present in the current request, if not then this request is trying to update members list
	for _, m := range originalMembers {
		if m.UserPrincipalName != "" {
			originalMemberAccessType[m.UserPrincipalName] = m.AccessType
		}
		if m.GroupPrincipalName != "" {
			originalMemberAccessType[m.GroupPrincipalName] = m.AccessType
		}
	}

	// go through all members in the current request, check if each exists in the original global DNS
	// if it exists, check that the access type hasn't changed, if it has changed, this means the req is updating members
	// if the member from req doesn't exist in original global DNS, this means the new request is adding a new member, hence updating members list
	for key, accessType := range newMemberAccessType {
		if val, ok := originalMemberAccessType[key]; ok {
			if val != accessType {
				requestUpdatesMembers = true
				break
			}
			// mark this original member as present in the current request
			originalMembersFoundInRequest[key] = true
		} else {
			requestUpdatesMembers = true
			break
		}
	}
	if requestUpdatesMembers && !ownerAccess {
		return fmt.Errorf("only members with owner access can add new members")
	}

	// at this point, all members in the new request have been found in the original global DNS with the same access type
	// but we need to check if all members from the original global DNS are also present in the current request
	for member := range originalMemberAccessType {
		// if any member is not found, this means the current request is updating members list by deleting this member
		if !originalMembersFoundInRequest[member] && !ownerAccess {
			return fmt.Errorf("only members with owner access can delete existing members")
		}
	}
	return nil
}

func (ma *MemberAccess) GetAccessTypeOfCaller(callerID, creatorID, name string, members []v3.Member) (string, error) {
	var username string
	if callerID == creatorID {
		return OwnerAccess, nil
	}
	for _, m := range members {
		if m.UserName == "" && m.UserPrincipalName != "" {
			user, err := ma.getUserFromUserPrincipalID(m.UserPrincipalName)
			if err != nil {
				return "", err
			}
			if user == nil {
				return "", fmt.Errorf("no user found for principal %v", m.UserPrincipalName)
			}
			if user.Name == callerID {
				username = user.Name
			}
		} else if m.UserName == callerID {
			username = m.UserName
		}
		if username != "" { // found the caller
			return m.AccessType, nil
		}
	}
	return "", fmt.Errorf("user %v is not in members list", callerID)
}

func (ma *MemberAccess) getUserFromUserPrincipalID(userPrincipalID string) (*v3.User, error) {
	encodedPrincipalID := base32.HexEncoding.WithPadding(base32.NoPadding).EncodeToString([]byte(userPrincipalID))
	if len(encodedPrincipalID) > 63 {
		encodedPrincipalID = encodedPrincipalID[:63]
	}
	set := labels.Set(map[string]string{encodedPrincipalID: "hashed-principal-name"})
	usersList, err := ma.Users.List(v1.ListOptions{LabelSelector: set.String()})
	if err != nil {
		return nil, err
	}

	if len(usersList.Items) == 0 {
		// check for local auth principals
		if strings.HasPrefix(userPrincipalID, localPrincipalPrefix) {
			userID := strings.TrimPrefix(userPrincipalID, localPrincipalPrefix)
			user, err := ma.Users.Controller().Lister().Get("", userID)
			return user, err
		}
		return nil, nil
	}

	var match *v3.User
	for _, u := range usersList.Items {
		if slice.ContainsString(u.PrincipalIDs, userPrincipalID) {
			if match != nil {
				// error out on duplicates
				return nil, fmt.Errorf("can't find unique user for principal %v", userPrincipalID)
			}
			match = &u
		}
	}
	return match, nil
}
<|endoftext|>


<commit_before><commit_msg>Removed seeding from ring-generation in gtet_shell<commit_after><|endoftext|>


<commit_before>package cluster

import (
	"encoding/base64"
	"encoding/pem"
	"fmt"

	lxd "github.com/lxc/lxd/client"
	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/pkg/errors"
)

// Connect is a convenience around lxd.ConnectLXD that configures the client
// with the correct parameters for node-to-node communication.
//
// If 'notify' switch is true, then the user agent will be set to the special
// value 'lxd-cluster-notifier', which can be used in some cases to distinguish
// between a regular client request and an internal cluster request.
func Connect(address string, cert *shared.CertInfo, notify bool) (lxd.ContainerServer, error) {
	args := &lxd.ConnectionArgs{
		TLSServerCert: string(cert.PublicKey()),
		TLSClientCert: string(cert.PublicKey()),
		TLSClientKey:  string(cert.PrivateKey()),
		SkipGetServer: true,
	}
	if notify {
		args.UserAgent = "lxd-cluster-notifier"
	}

	url := fmt.Sprintf("https://%s", address)
	return lxd.ConnectLXD(url, args)
}

// ConnectIfContainerIsRemote figures out the address of the node which is
// running the container with the given name. If it's not the local node will
// connect to it and return the connected client, otherwise it will just return
// nil.
func ConnectIfContainerIsRemote(cluster *db.Cluster, project, name string, cert *shared.CertInfo) (lxd.ContainerServer, error) {
	var address string // Node address
	err := cluster.Transaction(func(tx *db.ClusterTx) error {
		var err error
		address, err = tx.ContainerNodeAddress(project, name)
		return err
	})
	if err != nil {
		return nil, err
	}
	if address == "" {
		// The container is running right on this node, no need to connect.
		return nil, nil
	}
	return Connect(address, cert, false)
}

// ConnectIfVolumeIsRemote figures out the address of the node on which the
// volume with the given name is defined. If it's not the local node will
// connect to it and return the connected client, otherwise it will just return
// nil.
//
// If there is more than one node with a matching volume name, an error is
// returned.
func ConnectIfVolumeIsRemote(cluster *db.Cluster, poolID int64, volumeName string, volumeType int, cert *shared.CertInfo) (lxd.ContainerServer, error) {
	var addresses []string // Node addresses
	err := cluster.Transaction(func(tx *db.ClusterTx) error {
		var err error
		addresses, err = tx.StorageVolumeNodeAddresses(poolID, "default", volumeName, volumeType)
		return err
	})
	if err != nil {
		return nil, err
	}

	if len(addresses) > 1 {
		var driver string
		err := cluster.Transaction(func(tx *db.ClusterTx) error {
			var err error
			driver, err = tx.StoragePoolDriver(poolID)
			return err
		})
		if err != nil {
			return nil, err
		}

		if driver == "ceph" {
			return nil, nil
		}

		return nil, fmt.Errorf("more than one node has a volume named %s", volumeName)
	}

	address := addresses[0]
	if address == "" {
		return nil, nil
	}

	return Connect(address, cert, false)
}

// SetupTrust is a convenience around ContainerServer.CreateCertificate that
// adds the given client certificate to the trusted pool of the cluster at the
// given address, using the given password.
func SetupTrust(cert, targetAddress, targetCert, targetPassword string) error {
	// Connect to the target cluster node.
	args := &lxd.ConnectionArgs{
		TLSServerCert: targetCert,
	}
	target, err := lxd.ConnectLXD(fmt.Sprintf("https://%s", targetAddress), args)
	if err != nil {
		return errors.Wrap(err, "failed to connect to target cluster node")
	}
	block, _ := pem.Decode([]byte(cert))
	if block == nil {
		return errors.Wrap(err, "failed to decode certificate")
	}
	certificate := base64.StdEncoding.EncodeToString(block.Bytes)
	post := api.CertificatesPost{
		Password:    targetPassword,
		Certificate: certificate,
	}
	fingerprint, err := shared.CertFingerprintStr(cert)
	if err != nil {
		return errors.Wrap(err, "failed to calculate fingerprint")
	}
	post.Name = fmt.Sprintf("lxd.cluster.%s", fingerprint)
	post.Type = "client"
	err = target.CreateCertificate(post)
	if err != nil && err.Error() != "Certificate already in trust store" {
		return errors.Wrap(err, "Failed to add client cert to cluster")
	}
	return nil
}
<commit_msg>lxd/cluster/connect: Adds instanceType filter to ConnectIfContainerIsRemote<commit_after>package cluster

import (
	"encoding/base64"
	"encoding/pem"
	"fmt"

	lxd "github.com/lxc/lxd/client"
	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/pkg/errors"
)

// Connect is a convenience around lxd.ConnectLXD that configures the client
// with the correct parameters for node-to-node communication.
//
// If 'notify' switch is true, then the user agent will be set to the special
// value 'lxd-cluster-notifier', which can be used in some cases to distinguish
// between a regular client request and an internal cluster request.
func Connect(address string, cert *shared.CertInfo, notify bool) (lxd.ContainerServer, error) {
	args := &lxd.ConnectionArgs{
		TLSServerCert: string(cert.PublicKey()),
		TLSClientCert: string(cert.PublicKey()),
		TLSClientKey:  string(cert.PrivateKey()),
		SkipGetServer: true,
	}
	if notify {
		args.UserAgent = "lxd-cluster-notifier"
	}

	url := fmt.Sprintf("https://%s", address)
	return lxd.ConnectLXD(url, args)
}

// ConnectIfContainerIsRemote figures out the address of the node which is
// running the container with the given name. If it's not the local node will
// connect to it and return the connected client, otherwise it will just return
// nil.
func ConnectIfContainerIsRemote(cluster *db.Cluster, project, name string, cert *shared.CertInfo, instanceType instance.Type) (lxd.ContainerServer, error) {
	var address string // Node address
	err := cluster.Transaction(func(tx *db.ClusterTx) error {
		var err error
		address, err = tx.ContainerNodeAddress(project, name, instanceType)
		return err
	})
	if err != nil {
		return nil, err
	}
	if address == "" {
		// The container is running right on this node, no need to connect.
		return nil, nil
	}
	return Connect(address, cert, false)
}

// ConnectIfVolumeIsRemote figures out the address of the node on which the
// volume with the given name is defined. If it's not the local node will
// connect to it and return the connected client, otherwise it will just return
// nil.
//
// If there is more than one node with a matching volume name, an error is
// returned.
func ConnectIfVolumeIsRemote(cluster *db.Cluster, poolID int64, volumeName string, volumeType int, cert *shared.CertInfo) (lxd.ContainerServer, error) {
	var addresses []string // Node addresses
	err := cluster.Transaction(func(tx *db.ClusterTx) error {
		var err error
		addresses, err = tx.StorageVolumeNodeAddresses(poolID, "default", volumeName, volumeType)
		return err
	})
	if err != nil {
		return nil, err
	}

	if len(addresses) > 1 {
		var driver string
		err := cluster.Transaction(func(tx *db.ClusterTx) error {
			var err error
			driver, err = tx.StoragePoolDriver(poolID)
			return err
		})
		if err != nil {
			return nil, err
		}

		if driver == "ceph" {
			return nil, nil
		}

		return nil, fmt.Errorf("more than one node has a volume named %s", volumeName)
	}

	address := addresses[0]
	if address == "" {
		return nil, nil
	}

	return Connect(address, cert, false)
}

// SetupTrust is a convenience around ContainerServer.CreateCertificate that
// adds the given client certificate to the trusted pool of the cluster at the
// given address, using the given password.
func SetupTrust(cert, targetAddress, targetCert, targetPassword string) error {
	// Connect to the target cluster node.
	args := &lxd.ConnectionArgs{
		TLSServerCert: targetCert,
	}
	target, err := lxd.ConnectLXD(fmt.Sprintf("https://%s", targetAddress), args)
	if err != nil {
		return errors.Wrap(err, "failed to connect to target cluster node")
	}
	block, _ := pem.Decode([]byte(cert))
	if block == nil {
		return errors.Wrap(err, "failed to decode certificate")
	}
	certificate := base64.StdEncoding.EncodeToString(block.Bytes)
	post := api.CertificatesPost{
		Password:    targetPassword,
		Certificate: certificate,
	}
	fingerprint, err := shared.CertFingerprintStr(cert)
	if err != nil {
		return errors.Wrap(err, "failed to calculate fingerprint")
	}
	post.Name = fmt.Sprintf("lxd.cluster.%s", fingerprint)
	post.Type = "client"
	err = target.CreateCertificate(post)
	if err != nil && err.Error() != "Certificate already in trust store" {
		return errors.Wrap(err, "Failed to add client cert to cluster")
	}
	return nil
}
<|endoftext|>


<commit_before>package backenddisruption

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	"github.com/openshift/origin/pkg/monitor/monitorapi"
	"github.com/stretchr/testify/assert"

	"k8s.io/client-go/tools/events"
)

func TestBackendSampler_checkConnection(t *testing.T) {
	testServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		switch {
		case req.URL.Path == "/200":
			w.WriteHeader(200)
			w.Write([]byte("200"))
		case req.URL.Path == "/302-bad-response":
			w.WriteHeader(302)
			w.Write([]byte("302-bad-response"))
		//case req.URL.Path == "/302": // the client-auto-follows
		//	w.Header().Set("Location", "http://google.com")
		//	w.WriteHeader(302)
		//	w.Write([]byte("302"))
		case req.URL.Path == "/503":
			w.WriteHeader(503)
			w.Write([]byte("503"))
		case req.URL.Path == "/timeout":
			time.Sleep(2 * time.Second)
			w.WriteHeader(200)
			w.Write([]byte("200"))
		default:
			w.WriteHeader(404)
		}
	}))
	testHost := testServer.URL
	defer testServer.Close()

	type fields struct {
		disruptionBackendName string
		connectionType        BackendConnectionType
		path                  string
		expect                string
		expectRegexp          string

		cancelImmediately bool
	}
	tests := []struct {
		name    string
		fields  fields
		wantErr bool
	}{
		{
			name: "simple-200",
			fields: fields{
				disruptionBackendName: "simple-200",
				connectionType:        NewConnectionType,
				path:                  "/200",
				expect:                "200",
			},
			wantErr: false,
		},
		{
			name: "200-bad-exect",
			fields: fields{
				disruptionBackendName: "simple-200",
				connectionType:        NewConnectionType,
				path:                  "/200",
				expect:                "other",
			},
			wantErr: true,
		},
		{
			// 302 response missing Location header
			name: "302-no-expect-bad-response",
			fields: fields{
				disruptionBackendName: "302-bad-response",
				connectionType:        NewConnectionType,
				path:                  "/302-bad-response",
			},
			wantErr: true,
		},
		{
			name: "302-no-expect",
			fields: fields{
				disruptionBackendName: "302",
				connectionType:        NewConnectionType,
				path:                  "/302",
			},
			wantErr: false,
		},
		{
			name: "503",
			fields: fields{
				disruptionBackendName: "503",
				connectionType:        NewConnectionType,
				path:                  "/503",
			},
			wantErr: true,
		},
		{
			name: "timeout",
			fields: fields{
				disruptionBackendName: "timeout",
				connectionType:        NewConnectionType,
				path:                  "/timeout",
			},
			wantErr: true,
		},
		{
			name: "cancel-immediately",
			fields: fields{
				disruptionBackendName: "timeout",
				connectionType:        NewConnectionType,
				path:                  "/timeout",
				cancelImmediately:     true,
			},
			wantErr: false, // cancelling doesn't produce errors, it just means we were shutdown
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			backend := NewSimpleBackend(testHost, tt.fields.disruptionBackendName, tt.fields.path, tt.fields.connectionType)
			timeout := 1 * time.Second
			backend.timeout = &timeout
			if len(tt.fields.expect) > 0 {
				backend = backend.WithExpectedBody(tt.fields.expect)
			}
			if len(tt.fields.expectRegexp) > 0 {
				backend = backend.WithExpectedBodyRegex(tt.fields.expectRegexp)
			}

			ctx, cancel := context.WithCancel(context.Background())
			defer cancel()

			if tt.fields.cancelImmediately {
				cancel()
			}

			if err := backend.checkConnection(ctx); (err != nil) != tt.wantErr {
				t.Errorf("checkConnection() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func Test_disruptionSampler_consumeSamples(t *testing.T) {
	tests := []struct {
		name            string
		estimatedTime   time.Duration
		produceSamples  func(ctx context.Context, backendSampler *disruptionSampler)
		validateSamples func(t *testing.T, eventIntervals []monitorapi.EventInterval) error
	}{
		{
			name:          "in-order",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(nil)
				close(firstSample.finished)

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(nil)
				close(secondSample.finished)

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(fmt.Errorf("now fail"))
				close(thirdSample.finished)

				fourthSample := backendSampler.newSample(ctx)
				fourthSample.startTime = thirdSample.startTime.Add(1 * time.Second)
				fourthSample.setSampleError(fmt.Errorf("now fail"))
				close(fourthSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {
				if len(eventIntervals) != 2 {
					t.Fatal(eventIntervals)
				}
				if duration := eventIntervals[0].To.Sub(eventIntervals[0].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[0].Message, "started responding") {
					t.Error(eventIntervals[0])
				}
				if duration := eventIntervals[1].To.Sub(eventIntervals[1].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[1].Message, "now fail") {
					t.Error(eventIntervals[1])
				}
				return nil
			},
		},
		{
			name:          "out-of-order-finish",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(nil)

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(nil)

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(fmt.Errorf("now fail"))

				fourthSample := backendSampler.newSample(ctx)
				fourthSample.startTime = thirdSample.startTime.Add(1 * time.Second)
				fourthSample.setSampleError(fmt.Errorf("now fail"))

				close(fourthSample.finished)
				close(secondSample.finished)
				close(firstSample.finished)
				close(thirdSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {
				if len(eventIntervals) != 2 {
					t.Fatal(eventIntervals)
				}
				if duration := eventIntervals[0].To.Sub(eventIntervals[0].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[0].Message, "started responding") {
					t.Error(eventIntervals[0])
				}
				if duration := eventIntervals[1].To.Sub(eventIntervals[1].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[1].Message, "now fail") {
					t.Error(eventIntervals[1])
				}
				return nil
			},
		},
		{
			name:          "new-interval-on-different-message",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(fmt.Errorf("early"))

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(fmt.Errorf("early"))

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(fmt.Errorf("late"))

				fourthSample := backendSampler.newSample(ctx)
				fourthSample.startTime = thirdSample.startTime.Add(1 * time.Second)
				fourthSample.setSampleError(fmt.Errorf("late"))

				close(fourthSample.finished)
				close(secondSample.finished)
				close(firstSample.finished)
				close(thirdSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {
				if len(eventIntervals) != 2 {
					t.Fatal(eventIntervals)
				}
				if duration := eventIntervals[0].To.Sub(eventIntervals[0].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[0].Message, "early") {
					t.Error(eventIntervals[0])
				}
				if duration := eventIntervals[1].To.Sub(eventIntervals[1].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[1].Message, "late") {
					t.Error(eventIntervals[1])
				}
				return nil
			},
		},
		{
			// Disruption with a message of "dial tcp: lookup [hostname]: i/o timeout" should not be considered real disruption
			name:          "dial-tcp-lookup-warn-not-error",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(nil)

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(fmt.Errorf("dial tcp: lookup static.redhat.com: i/o timeout"))

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(nil)

				close(secondSample.finished)
				close(firstSample.finished)
				close(thirdSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {

				if !assert.Equal(t, 3, len(eventIntervals)) {
					return nil
				}

				assert.Equal(t, 1*time.Second, eventIntervals[0].To.Sub(eventIntervals[0].From))
				assert.Equal(t, 1*time.Second, eventIntervals[1].To.Sub(eventIntervals[1].From))
				assert.Equal(t, monitorapi.Warning, eventIntervals[1].Level,
					"DNS lookup i/o timeout should be warning level, not error")
				assert.Contains(t, eventIntervals[1].Message, "DNS lookup timeouts began")
				assert.Contains(t, eventIntervals[1].Message, "i/o timeout") // make sure the orig message is also preserved
				return nil
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()

			parent := NewSimpleBackend("host", "backend", "path", NewConnectionType)
			backendSampler := newDisruptionSampler(parent)
			interval := 1 * time.Second
			monitor := newSimpleMonitor()
			fakeEventRecorder := events.NewFakeRecorder(100)
			go func() {
				backendSampler.consumeSamples(ctx, interval, monitor, fakeEventRecorder)
			}()

			// now we start supplying the samples
			tt.produceSamples(ctx, backendSampler)
			time.Sleep(2 * time.Second) // wait just a bit for the consumption to happen before cancelling. this must be longer than the interval above
			cancel()
			time.Sleep(1 * time.Second) // wait just a bit for the consumption finish and complete the deferal

			tt.validateSamples(t, monitor.Intervals(time.Time{}, time.Time{}))
		})
	}
}
<commit_msg>Fix backend sampler check connection test.<commit_after>package backenddisruption

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	"github.com/openshift/origin/pkg/monitor/monitorapi"
	"github.com/stretchr/testify/assert"

	"k8s.io/client-go/tools/events"
)

func TestBackendSampler_checkConnection(t *testing.T) {
	testServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		switch {
		case req.URL.Path == "/200":
			w.WriteHeader(200)
			w.Write([]byte("200"))
		case req.URL.Path == "/302-bad-response":
			w.WriteHeader(302)
			w.Write([]byte("302-bad-response"))
		case req.URL.Path == "/302": // the client-auto-follows
			w.Header().Set("Location", "http://google.com")
			w.WriteHeader(302)
			w.Write([]byte("302"))
		case req.URL.Path == "/503":
			w.WriteHeader(503)
			w.Write([]byte("503"))
		case req.URL.Path == "/timeout":
			time.Sleep(2 * time.Second)
			w.WriteHeader(200)
			w.Write([]byte("200"))
		default:
			w.WriteHeader(404)
		}
	}))
	testHost := testServer.URL
	defer testServer.Close()

	type fields struct {
		disruptionBackendName string
		connectionType        BackendConnectionType
		path                  string
		expect                string
		expectRegexp          string

		cancelImmediately bool
	}
	tests := []struct {
		name    string
		fields  fields
		wantErr bool
	}{
		{
			name: "simple-200",
			fields: fields{
				disruptionBackendName: "simple-200",
				connectionType:        NewConnectionType,
				path:                  "/200",
				expect:                "200",
			},
			wantErr: false,
		},
		{
			name: "200-bad-exect",
			fields: fields{
				disruptionBackendName: "simple-200",
				connectionType:        NewConnectionType,
				path:                  "/200",
				expect:                "other",
			},
			wantErr: true,
		},
		{
			// 302 response missing Location header
			name: "302-no-expect-bad-response",
			fields: fields{
				disruptionBackendName: "302-bad-response",
				connectionType:        NewConnectionType,
				path:                  "/302-bad-response",
			},
			wantErr: true,
		},
		{
			name: "302-no-expect",
			fields: fields{
				disruptionBackendName: "302",
				connectionType:        NewConnectionType,
				path:                  "/302",
			},
			wantErr: false,
		},
		{
			name: "503",
			fields: fields{
				disruptionBackendName: "503",
				connectionType:        NewConnectionType,
				path:                  "/503",
			},
			wantErr: true,
		},
		{
			name: "timeout",
			fields: fields{
				disruptionBackendName: "timeout",
				connectionType:        NewConnectionType,
				path:                  "/timeout",
			},
			wantErr: true,
		},
		{
			name: "cancel-immediately",
			fields: fields{
				disruptionBackendName: "timeout",
				connectionType:        NewConnectionType,
				path:                  "/timeout",
				cancelImmediately:     true,
			},
			wantErr: false, // cancelling doesn't produce errors, it just means we were shutdown
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			backend := NewSimpleBackend(testHost, tt.fields.disruptionBackendName, tt.fields.path, tt.fields.connectionType)
			timeout := 1 * time.Second
			backend.timeout = &timeout
			if len(tt.fields.expect) > 0 {
				backend = backend.WithExpectedBody(tt.fields.expect)
			}
			if len(tt.fields.expectRegexp) > 0 {
				backend = backend.WithExpectedBodyRegex(tt.fields.expectRegexp)
			}

			ctx, cancel := context.WithCancel(context.Background())
			defer cancel()

			if tt.fields.cancelImmediately {
				cancel()
			}

			if err := backend.checkConnection(ctx); (err != nil) != tt.wantErr {
				t.Errorf("checkConnection() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func Test_disruptionSampler_consumeSamples(t *testing.T) {
	tests := []struct {
		name            string
		estimatedTime   time.Duration
		produceSamples  func(ctx context.Context, backendSampler *disruptionSampler)
		validateSamples func(t *testing.T, eventIntervals []monitorapi.EventInterval) error
	}{
		{
			name:          "in-order",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(nil)
				close(firstSample.finished)

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(nil)
				close(secondSample.finished)

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(fmt.Errorf("now fail"))
				close(thirdSample.finished)

				fourthSample := backendSampler.newSample(ctx)
				fourthSample.startTime = thirdSample.startTime.Add(1 * time.Second)
				fourthSample.setSampleError(fmt.Errorf("now fail"))
				close(fourthSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {
				if len(eventIntervals) != 2 {
					t.Fatal(eventIntervals)
				}
				if duration := eventIntervals[0].To.Sub(eventIntervals[0].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[0].Message, "started responding") {
					t.Error(eventIntervals[0])
				}
				if duration := eventIntervals[1].To.Sub(eventIntervals[1].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[1].Message, "now fail") {
					t.Error(eventIntervals[1])
				}
				return nil
			},
		},
		{
			name:          "out-of-order-finish",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(nil)

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(nil)

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(fmt.Errorf("now fail"))

				fourthSample := backendSampler.newSample(ctx)
				fourthSample.startTime = thirdSample.startTime.Add(1 * time.Second)
				fourthSample.setSampleError(fmt.Errorf("now fail"))

				close(fourthSample.finished)
				close(secondSample.finished)
				close(firstSample.finished)
				close(thirdSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {
				if len(eventIntervals) != 2 {
					t.Fatal(eventIntervals)
				}
				if duration := eventIntervals[0].To.Sub(eventIntervals[0].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[0].Message, "started responding") {
					t.Error(eventIntervals[0])
				}
				if duration := eventIntervals[1].To.Sub(eventIntervals[1].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[1].Message, "now fail") {
					t.Error(eventIntervals[1])
				}
				return nil
			},
		},
		{
			name:          "new-interval-on-different-message",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(fmt.Errorf("early"))

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(fmt.Errorf("early"))

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(fmt.Errorf("late"))

				fourthSample := backendSampler.newSample(ctx)
				fourthSample.startTime = thirdSample.startTime.Add(1 * time.Second)
				fourthSample.setSampleError(fmt.Errorf("late"))

				close(fourthSample.finished)
				close(secondSample.finished)
				close(firstSample.finished)
				close(thirdSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {
				if len(eventIntervals) != 2 {
					t.Fatal(eventIntervals)
				}
				if duration := eventIntervals[0].To.Sub(eventIntervals[0].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[0].Message, "early") {
					t.Error(eventIntervals[0])
				}
				if duration := eventIntervals[1].To.Sub(eventIntervals[1].From); duration != 2*time.Second {
					t.Error(eventIntervals[0])
				}
				if !strings.Contains(eventIntervals[1].Message, "late") {
					t.Error(eventIntervals[1])
				}
				return nil
			},
		},
		{
			// Disruption with a message of "dial tcp: lookup [hostname]: i/o timeout" should not be considered real disruption
			name:          "dial-tcp-lookup-warn-not-error",
			estimatedTime: 1 * time.Second,
			produceSamples: func(ctx context.Context, backendSampler *disruptionSampler) {
				now := time.Now()
				firstSample := backendSampler.newSample(ctx)
				firstSample.startTime = now
				firstSample.setSampleError(nil)

				secondSample := backendSampler.newSample(ctx)
				secondSample.startTime = firstSample.startTime.Add(1 * time.Second)
				secondSample.setSampleError(fmt.Errorf("dial tcp: lookup static.redhat.com: i/o timeout"))

				thirdSample := backendSampler.newSample(ctx)
				thirdSample.startTime = secondSample.startTime.Add(1 * time.Second)
				thirdSample.setSampleError(nil)

				close(secondSample.finished)
				close(firstSample.finished)
				close(thirdSample.finished)
			},
			validateSamples: func(t *testing.T, eventIntervals []monitorapi.EventInterval) error {

				if !assert.Equal(t, 3, len(eventIntervals)) {
					return nil
				}

				assert.Equal(t, 1*time.Second, eventIntervals[0].To.Sub(eventIntervals[0].From))
				assert.Equal(t, 1*time.Second, eventIntervals[1].To.Sub(eventIntervals[1].From))
				assert.Equal(t, monitorapi.Warning, eventIntervals[1].Level,
					"DNS lookup i/o timeout should be warning level, not error")
				assert.Contains(t, eventIntervals[1].Message, "DNS lookup timeouts began")
				assert.Contains(t, eventIntervals[1].Message, "i/o timeout") // make sure the orig message is also preserved
				return nil
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()

			parent := NewSimpleBackend("host", "backend", "path", NewConnectionType)
			backendSampler := newDisruptionSampler(parent)
			interval := 1 * time.Second
			monitor := newSimpleMonitor()
			fakeEventRecorder := events.NewFakeRecorder(100)
			go func() {
				backendSampler.consumeSamples(ctx, interval, monitor, fakeEventRecorder)
			}()

			// now we start supplying the samples
			tt.produceSamples(ctx, backendSampler)
			time.Sleep(2 * time.Second) // wait just a bit for the consumption to happen before cancelling. this must be longer than the interval above
			cancel()
			time.Sleep(1 * time.Second) // wait just a bit for the consumption finish and complete the deferal

			tt.validateSamples(t, monitor.Intervals(time.Time{}, time.Time{}))
		})
	}
}
<|endoftext|>


<commit_before>package selinux

import (
	"testing"

	"k8s.io/kubernetes/pkg/api"

	securityapi "github.com/openshift/origin/pkg/security/apis/security"
)

func TestRunAsAnyOptions(t *testing.T) {
	_, err := NewRunAsAny(nil)
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	_, err = NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
	if err != nil {
		t.Errorf("unexpected error initializing NewRunAsAny %v", err)
	}
}

func TestRunAsAnyGenerate(t *testing.T) {
	s, err := NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	uid, err := s.Generate(nil, nil)
	if uid != nil {
		t.Errorf("expected nil uid but got %d", *uid)
	}
	if err != nil {
		t.Errorf("unexpected error generating uid %v", err)
	}
}

func TestRunAsAnyValidate(t *testing.T) {
	s, err := NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{
		SELinuxOptions: &api.SELinuxOptions{
			Level: "foo",
		},
	},
	)
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	errs := s.Validate(nil, nil)
	if len(errs) != 0 {
		t.Errorf("unexpected errors validating with ")
	}
	s, err = NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	errs = s.Validate(nil, nil)
	if len(errs) != 0 {
		t.Errorf("unexpected errors validating %v", errs)
	}
}
<commit_msg>Fix go vet in TestRunAsAnyGenerate<commit_after>package selinux

import (
	"testing"

	"k8s.io/kubernetes/pkg/api"

	securityapi "github.com/openshift/origin/pkg/security/apis/security"
)

func TestRunAsAnyOptions(t *testing.T) {
	_, err := NewRunAsAny(nil)
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	_, err = NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
	if err != nil {
		t.Errorf("unexpected error initializing NewRunAsAny %v", err)
	}
}

func TestRunAsAnyGenerate(t *testing.T) {
	s, err := NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	uid, err := s.Generate(nil, nil)
	if uid != nil {
		t.Errorf("expected nil uid but got %v", *uid)
	}
	if err != nil {
		t.Errorf("unexpected error generating uid %v", err)
	}
}

func TestRunAsAnyValidate(t *testing.T) {
	s, err := NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{
		SELinuxOptions: &api.SELinuxOptions{
			Level: "foo",
		},
	},
	)
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	errs := s.Validate(nil, nil)
	if len(errs) != 0 {
		t.Errorf("unexpected errors validating with ")
	}
	s, err = NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
	if err != nil {
		t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
	}
	errs = s.Validate(nil, nil)
	if len(errs) != 0 {
		t.Errorf("unexpected errors validating %v", errs)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppdump

import (
	"fmt"
	"net"

	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/measure"
	l3ba "github.com/ligato/vpp-agent/plugins/defaultplugins/l3plugin/bin_api/ip"
	l3nb "github.com/ligato/vpp-agent/plugins/defaultplugins/l3plugin/model/l3"
	"time"
)

// StaticRoutes is the wrapper structure for the static routes API structure.
type StaticRoutes struct {
	IP []*StaticRouteIP
}

// StaticRouteIP is the wrapper structure for the static IP route API structure.
// NOTE: NextHops in StaticRoutes_Ip is overridden by the local NextHops member.
type StaticRouteIP struct {
	NextHops []*NextHop
	l3nb.StaticRoutes_Route
}

// NextHop is the wrapper structure for the bridge domain interface northbound API structure.
type NextHop struct {
	OutgoingInterfaceSwIfIdx    uint32
	OutgoingInterfaceConfigured bool
}

// DumpStaticRoutes dumps l3 routes from VPP and fills them into the provided static route map.
func DumpStaticRoutes(log logging.Logger, vppChan *govppapi.Channel, stopwatch measure.StopWatchEntry) (map[uint32]*StaticRoutes, error) {
	// IPFibDump time measurement
	start := time.Now()
	defer func() {
		if stopwatch != nil {
			stopwatch.LogTimeEntry(time.Since(start))
		}
	}()

	// map for the resulting l3 FIBs
	routes := make(map[uint32]*StaticRoutes)

	// dump IPv4 l3 FIB
	reqCtx := vppChan.SendMultiRequest(&l3ba.IPFibDump{})
	for {
		fibDetails := &l3ba.IPFibDetails{}
		stop, err := reqCtx.ReceiveReply(fibDetails)
		if stop {
			break // break out of the loop
		}
		if err != nil {
			log.Error(err)
			return nil, err
		}
		dumpStaticRouteDetails(routes, fibDetails.TableID, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, true)
	}

	// dump IPv6 l3 FIB
	reqCtx = vppChan.SendMultiRequest(&l3ba.IP6FibDump{})
	for {
		fibDetails := &l3ba.IP6FibDetails{}
		stop, err := reqCtx.ReceiveReply(fibDetails)
		if stop {
			break // break out of the loop
		}
		if err != nil {
			log.Error(err)
			return nil, err
		}
		dumpStaticRouteDetails(routes, fibDetails.TableID, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, true)
	}

	return routes, nil
}

// dumpStaticRouteDetails processes static route details and fills them into the provided routes map.
func dumpStaticRouteDetails(routes map[uint32]*StaticRoutes, tableID uint32,
	address []byte, prefixLen uint8, paths []l3ba.FibPath, ipv6 bool) {

	// route details
	var ipAddr string
	if ipv6 {
		ipAddr = fmt.Sprintf("%s/%d", net.IP(address).To16().String(), uint32(prefixLen))
	} else {
		ipAddr = fmt.Sprintf("%s/%d", net.IP(address[:4]).To4().String(), uint32(prefixLen))
	}
	if _, ok := routes[tableID]; !ok {
		routes[tableID] = &StaticRoutes{
			IP: make([]*StaticRouteIP, 0),
		}
	}
	route := &StaticRouteIP{
		StaticRoutes_Route: l3nb.StaticRoutes_Route{
			VrfId:     tableID,
			DstIpAddr: ipAddr,
		},
		NextHops: []*NextHop{},
	}
	routes[tableID].IP = append(routes[tableID].IP, route)

	// next hops
	for _, path := range paths {
		var nextHopAddr string
		if ipv6 {
			nextHopAddr = net.IP(path.NextHop).To16().String()
		} else {
			nextHopAddr = net.IP(path.NextHop[:4]).To4().String()
		}
		route.NextHops = append(route.NextHops, &NextHop{
			OutgoingInterfaceSwIfIdx:    path.SwIfIndex,
			OutgoingInterfaceConfigured: path.SwIfIndex < ^uint32(0),
		})
		route.NextHopAddr = nextHopAddr
		route.Weight = uint32(path.Weight)
		route.Preference = uint32(path.Preference)
	}
}
<commit_msg>SPOPT-1690 - REST API for VPP - static routes<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppdump

import (
	"fmt"
	"net"

	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/measure"
	l3ba "github.com/ligato/vpp-agent/plugins/defaultplugins/l3plugin/bin_api/ip"
	l3nb "github.com/ligato/vpp-agent/plugins/defaultplugins/l3plugin/model/l3"
	"time"
)

// StaticRoutes is the wrapper structure for the static routes API structure.
type StaticRoutes struct {
	IP []*StaticRouteIP
}

// StaticRouteIP is the wrapper structure for the static IP route API structure.
// NOTE: NextHops in StaticRoutes_Ip is overridden by the local NextHops member.
type StaticRouteIP struct {
	NextHops []*NextHop
	l3nb.StaticRoutes_Route
}

// NextHop is the wrapper structure for the bridge domain interface northbound API structure.
type NextHop struct {
	OutgoingInterfaceSwIfIdx    uint32
	OutgoingInterfaceConfigured bool
}

// DumpStaticRoutes dumps l3 routes from VPP and fills them into the provided static route map.
func DumpStaticRoutes(log logging.Logger, vppChan *govppapi.Channel, stopwatch measure.StopWatchEntry) (map[uint32]*StaticRoutes, error) {
	// IPFibDump time measurement
	start := time.Now()
	defer func() {
		if stopwatch != nil {
			stopwatch.LogTimeEntry(time.Since(start))
		}
	}()

	// map for the resulting l3 FIBs
	routes := make(map[uint32]*StaticRoutes)

	// dump IPv4 l3 FIB
	reqCtx := vppChan.SendMultiRequest(&l3ba.IPFibDump{})
	for {
		fibDetails := &l3ba.IPFibDetails{}
		stop, err := reqCtx.ReceiveReply(fibDetails)
		if stop {
			break // break out of the loop
		}
		if err != nil {
			log.Error(err)
			return nil, err
		}
		dumpStaticRouteDetails(routes, fibDetails.TableID, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, false)
	}

	// dump IPv6 l3 FIB
	reqCtx = vppChan.SendMultiRequest(&l3ba.IP6FibDump{})
	for {
		fibDetails := &l3ba.IP6FibDetails{}
		stop, err := reqCtx.ReceiveReply(fibDetails)
		if stop {
			break // break out of the loop
		}
		if err != nil {
			log.Error(err)
			return nil, err
		}
		dumpStaticRouteDetails(routes, fibDetails.TableID, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, true)
	}

	return routes, nil
}

// dumpStaticRouteDetails processes static route details and fills them into the provided routes map.
func dumpStaticRouteDetails(routes map[uint32]*StaticRoutes, tableID uint32,
	address []byte, prefixLen uint8, paths []l3ba.FibPath, ipv6 bool) {

	// route details
	var ipAddr string
	if ipv6 {
		ipAddr = fmt.Sprintf("%s/%d", net.IP(address).To16().String(), uint32(prefixLen))
	} else {
		ipAddr = fmt.Sprintf("%s/%d", net.IP(address[:4]).To4().String(), uint32(prefixLen))
	}
	if _, ok := routes[tableID]; !ok {
		routes[tableID] = &StaticRoutes{
			IP: make([]*StaticRouteIP, 0),
		}
	}
	route := &StaticRouteIP{
		StaticRoutes_Route: l3nb.StaticRoutes_Route{
			VrfId:     tableID,
			DstIpAddr: ipAddr,
		},
		NextHops: []*NextHop{},
	}
	routes[tableID].IP = append(routes[tableID].IP, route)

	// next hops
	for _, path := range paths {
		var nextHopAddr string
		if ipv6 {
			nextHopAddr = net.IP(path.NextHop).To16().String()
		} else {
			nextHopAddr = net.IP(path.NextHop[:4]).To4().String()
		}
		route.NextHops = append(route.NextHops, &NextHop{
			OutgoingInterfaceSwIfIdx:    path.SwIfIndex,
			OutgoingInterfaceConfigured: path.SwIfIndex < ^uint32(0),
		})
		route.NextHopAddr = nextHopAddr
		route.Weight = uint32(path.Weight)
		route.Preference = uint32(path.Preference)
	}
}
<|endoftext|>


<commit_before><commit_msg>test/compilationdatabase: fix struct variables<commit_after><|endoftext|>


<commit_before>package daemon

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/pkg/errors"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
	"github.com/weaveworks/common/middleware"

	"github.com/weaveworks/flux"
	transport "github.com/weaveworks/flux/http"
	"github.com/weaveworks/flux/job"
	fluxmetrics "github.com/weaveworks/flux/metrics"
	"github.com/weaveworks/flux/policy"
	"github.com/weaveworks/flux/remote"
	"github.com/weaveworks/flux/update"
)

var (
	requestDuration = stdprometheus.NewHistogramVec(stdprometheus.HistogramOpts{
		Namespace: "flux",
		Name:      "request_duration_seconds",
		Help:      "Time (in seconds) spent serving HTTP requests.",
		Buckets:   stdprometheus.DefBuckets,
	}, []string{fluxmetrics.LabelMethod, fluxmetrics.LabelRoute, "status_code", "ws"})
)

// An API server for the daemon
func NewRouter() *mux.Router {
	r := transport.NewAPIRouter()
	// All old versions are deprecated in the daemon. Use an up to
	// date client!
	transport.DeprecateVersions(r, "v1", "v2", "v3", "v4", "v5")
	// We assume every request that doesn't match a route is a client
	// calling an old or hitherto unsupported API.
	r.NewRoute().Name("NotFound").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		transport.WriteError(w, r, http.StatusNotFound, transport.MakeAPINotFound(r.URL.Path))
	})

	return r
}

func NewHandler(d remote.Platform, r *mux.Router) http.Handler {
	handle := HTTPServer{d}
	r.Get("SyncNotify").HandlerFunc(handle.SyncNotify)
	r.Get("JobStatus").HandlerFunc(handle.JobStatus)
	r.Get("SyncStatus").HandlerFunc(handle.SyncStatus)
	r.Get("UpdateImages").HandlerFunc(handle.UpdateImages)
	r.Get("UpdatePolicies").HandlerFunc(handle.UpdatePolicies)
	r.Get("ListServices").HandlerFunc(handle.ListServices)
	r.Get("ListImages").HandlerFunc(handle.ListImages)
	r.Get("Export").HandlerFunc(handle.Export)
	r.Get("GetPublicSSHKey").HandlerFunc(handle.GetPublicSSHKey)
	r.Get("RegeneratePublicSSHKey").HandlerFunc(handle.RegeneratePublicSSHKey)

	return middleware.Instrument{
		RouteMatcher: r,
		Duration:     requestDuration,
	}.Wrap(r)
}

type HTTPServer struct {
	daemon remote.Platform
}

func (s HTTPServer) SyncNotify(w http.ResponseWriter, r *http.Request) {
	err := s.daemon.SyncNotify()
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	w.WriteHeader(http.StatusAccepted)
}

func (s HTTPServer) JobStatus(w http.ResponseWriter, r *http.Request) {
	id := job.ID(mux.Vars(r)["id"])
	status, err := s.daemon.JobStatus(id)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, status)
}

func (s HTTPServer) SyncStatus(w http.ResponseWriter, r *http.Request) {
	ref := mux.Vars(r)["ref"]
	commits, err := s.daemon.SyncStatus(ref)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, commits)
}

func (s HTTPServer) ListImages(w http.ResponseWriter, r *http.Request) {
	service := mux.Vars(r)["service"]
	spec, err := update.ParseServiceSpec(service)
	if err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing service spec %q", service))
		return
	}

	d, err := s.daemon.ListImages(spec)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, d)
}

func (s HTTPServer) UpdateImages(w http.ResponseWriter, r *http.Request) {
	var (
		vars  = mux.Vars(r)
		image = vars["image"]
		kind  = vars["kind"]
	)
	if err := r.ParseForm(); err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing form"))
		return
	}
	var serviceSpecs []update.ServiceSpec
	for _, service := range r.Form["service"] {
		serviceSpec, err := update.ParseServiceSpec(service)
		if err != nil {
			transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing service spec %q", service))
			return
		}
		serviceSpecs = append(serviceSpecs, serviceSpec)
	}
	imageSpec, err := update.ParseImageSpec(image)
	if err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing image spec %q", image))
		return
	}
	releaseKind, err := update.ParseReleaseKind(kind)
	if err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing release kind %q", kind))
		return
	}

	var excludes []flux.ServiceID
	for _, ex := range r.URL.Query()["exclude"] {
		s, err := flux.ParseServiceID(ex)
		if err != nil {
			transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing excluded service %q", ex))
			return
		}
		excludes = append(excludes, s)
	}

	spec := update.ReleaseSpec{
		ServiceSpecs: serviceSpecs,
		ImageSpec:    imageSpec,
		Kind:         releaseKind,
		Excludes:     excludes,
	}
	cause := update.Cause{
		User:    r.FormValue("user"),
		Message: r.FormValue("message"),
	}
	result, err := s.daemon.UpdateManifests(update.Spec{Type: update.Images, Cause: cause, Spec: spec})
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, result)
}

func (s HTTPServer) UpdatePolicies(w http.ResponseWriter, r *http.Request) {
	var updates policy.Updates
	if err := json.NewDecoder(r.Body).Decode(&updates); err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, err)
		return
	}

	cause := update.Cause{
		User:    r.FormValue("user"),
		Message: r.FormValue("message"),
	}

	jobID, err := s.daemon.UpdateManifests(update.Spec{Type: update.Policy, Cause: cause, Spec: updates})
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}

	transport.JSONResponse(w, r, jobID)
}

func (s HTTPServer) ListServices(w http.ResponseWriter, r *http.Request) {
	namespace := mux.Vars(r)["namespace"]
	res, err := s.daemon.ListServices(namespace)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, res)
}

func (s HTTPServer) Export(w http.ResponseWriter, r *http.Request) {
	status, err := s.daemon.Export()
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}

	transport.JSONResponse(w, r, status)
}

func (s HTTPServer) GetPublicSSHKey(w http.ResponseWriter, r *http.Request) {
	res, err := s.daemon.GitRepoConfig(false)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, res)
}

func (s HTTPServer) RegeneratePublicSSHKey(w http.ResponseWriter, r *http.Request) {
	_, err := s.daemon.GitRepoConfig(true)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
	return
}
<commit_msg>Fix fluxctl identity<commit_after>package daemon

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/pkg/errors"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
	"github.com/weaveworks/common/middleware"

	"github.com/weaveworks/flux"
	transport "github.com/weaveworks/flux/http"
	"github.com/weaveworks/flux/job"
	fluxmetrics "github.com/weaveworks/flux/metrics"
	"github.com/weaveworks/flux/policy"
	"github.com/weaveworks/flux/remote"
	"github.com/weaveworks/flux/update"
)

var (
	requestDuration = stdprometheus.NewHistogramVec(stdprometheus.HistogramOpts{
		Namespace: "flux",
		Name:      "request_duration_seconds",
		Help:      "Time (in seconds) spent serving HTTP requests.",
		Buckets:   stdprometheus.DefBuckets,
	}, []string{fluxmetrics.LabelMethod, fluxmetrics.LabelRoute, "status_code", "ws"})
)

// An API server for the daemon
func NewRouter() *mux.Router {
	r := transport.NewAPIRouter()
	// All old versions are deprecated in the daemon. Use an up to
	// date client!
	transport.DeprecateVersions(r, "v1", "v2", "v3", "v4", "v5")
	// We assume every request that doesn't match a route is a client
	// calling an old or hitherto unsupported API.
	r.NewRoute().Name("NotFound").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		transport.WriteError(w, r, http.StatusNotFound, transport.MakeAPINotFound(r.URL.Path))
	})

	return r
}

func NewHandler(d remote.Platform, r *mux.Router) http.Handler {
	handle := HTTPServer{d}
	r.Get("SyncNotify").HandlerFunc(handle.SyncNotify)
	r.Get("JobStatus").HandlerFunc(handle.JobStatus)
	r.Get("SyncStatus").HandlerFunc(handle.SyncStatus)
	r.Get("UpdateImages").HandlerFunc(handle.UpdateImages)
	r.Get("UpdatePolicies").HandlerFunc(handle.UpdatePolicies)
	r.Get("ListServices").HandlerFunc(handle.ListServices)
	r.Get("ListImages").HandlerFunc(handle.ListImages)
	r.Get("Export").HandlerFunc(handle.Export)
	r.Get("GetPublicSSHKey").HandlerFunc(handle.GetPublicSSHKey)
	r.Get("RegeneratePublicSSHKey").HandlerFunc(handle.RegeneratePublicSSHKey)

	return middleware.Instrument{
		RouteMatcher: r,
		Duration:     requestDuration,
	}.Wrap(r)
}

type HTTPServer struct {
	daemon remote.Platform
}

func (s HTTPServer) SyncNotify(w http.ResponseWriter, r *http.Request) {
	err := s.daemon.SyncNotify()
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	w.WriteHeader(http.StatusAccepted)
}

func (s HTTPServer) JobStatus(w http.ResponseWriter, r *http.Request) {
	id := job.ID(mux.Vars(r)["id"])
	status, err := s.daemon.JobStatus(id)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, status)
}

func (s HTTPServer) SyncStatus(w http.ResponseWriter, r *http.Request) {
	ref := mux.Vars(r)["ref"]
	commits, err := s.daemon.SyncStatus(ref)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, commits)
}

func (s HTTPServer) ListImages(w http.ResponseWriter, r *http.Request) {
	service := mux.Vars(r)["service"]
	spec, err := update.ParseServiceSpec(service)
	if err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing service spec %q", service))
		return
	}

	d, err := s.daemon.ListImages(spec)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, d)
}

func (s HTTPServer) UpdateImages(w http.ResponseWriter, r *http.Request) {
	var (
		vars  = mux.Vars(r)
		image = vars["image"]
		kind  = vars["kind"]
	)
	if err := r.ParseForm(); err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing form"))
		return
	}
	var serviceSpecs []update.ServiceSpec
	for _, service := range r.Form["service"] {
		serviceSpec, err := update.ParseServiceSpec(service)
		if err != nil {
			transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing service spec %q", service))
			return
		}
		serviceSpecs = append(serviceSpecs, serviceSpec)
	}
	imageSpec, err := update.ParseImageSpec(image)
	if err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing image spec %q", image))
		return
	}
	releaseKind, err := update.ParseReleaseKind(kind)
	if err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing release kind %q", kind))
		return
	}

	var excludes []flux.ServiceID
	for _, ex := range r.URL.Query()["exclude"] {
		s, err := flux.ParseServiceID(ex)
		if err != nil {
			transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing excluded service %q", ex))
			return
		}
		excludes = append(excludes, s)
	}

	spec := update.ReleaseSpec{
		ServiceSpecs: serviceSpecs,
		ImageSpec:    imageSpec,
		Kind:         releaseKind,
		Excludes:     excludes,
	}
	cause := update.Cause{
		User:    r.FormValue("user"),
		Message: r.FormValue("message"),
	}
	result, err := s.daemon.UpdateManifests(update.Spec{Type: update.Images, Cause: cause, Spec: spec})
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, result)
}

func (s HTTPServer) UpdatePolicies(w http.ResponseWriter, r *http.Request) {
	var updates policy.Updates
	if err := json.NewDecoder(r.Body).Decode(&updates); err != nil {
		transport.WriteError(w, r, http.StatusBadRequest, err)
		return
	}

	cause := update.Cause{
		User:    r.FormValue("user"),
		Message: r.FormValue("message"),
	}

	jobID, err := s.daemon.UpdateManifests(update.Spec{Type: update.Policy, Cause: cause, Spec: updates})
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}

	transport.JSONResponse(w, r, jobID)
}

func (s HTTPServer) ListServices(w http.ResponseWriter, r *http.Request) {
	namespace := mux.Vars(r)["namespace"]
	res, err := s.daemon.ListServices(namespace)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, res)
}

func (s HTTPServer) Export(w http.ResponseWriter, r *http.Request) {
	status, err := s.daemon.Export()
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}

	transport.JSONResponse(w, r, status)
}

func (s HTTPServer) GetPublicSSHKey(w http.ResponseWriter, r *http.Request) {
	res, err := s.daemon.GitRepoConfig(false)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	transport.JSONResponse(w, r, res.PublicSSHKey)
}

func (s HTTPServer) RegeneratePublicSSHKey(w http.ResponseWriter, r *http.Request) {
	_, err := s.daemon.GitRepoConfig(true)
	if err != nil {
		transport.ErrorResponse(w, r, err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
	return
}
<|endoftext|>