text:
%v, %v", status, err)
	}

	// Test that checks the update of an ipvs service
	service, _ = createTestLoadBalancerServiceIPVS("testIPVSDeleteSA", "192.168.10.34", true, true)
	service.Spec.LoadBalancerIP = "192.168.10.34"
	// Delete The service account to ensure we can't create an IPVS lb without a service account
	err = c.KubeClient.CoreV1().ServiceAccounts(lbDeploymentNamespace).Delete(context.TODO(), lbDeploymentServiceAccountName, metav1.DeleteOptions{})
	if nil != err {
		t.Fatalf("Unexpected error remove service account: %v, %v. Error: %v", lbDeploymentNamespace, lbDeploymentServiceAccountName, err)
	}

	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, service, nil)
	if nil != status || nil == err || !strings.Contains(fmt.Sprintf("%v", err), "serviceaccounts \"ibm-cloud-provider-lb\" not found") {
		t.Fatalf("Unexpected error expected service account to not be created: %v, %v", status, err)
	}

	// Verify error when making public IPVS LB private
	service, _ = createTestLoadBalancerServiceIPVS("testIPVSDeleteCM", "192.168.10.50", true, false)
	service.Spec.LoadBalancerIP = "192.168.10.50"
	// Delete The service account to ensure we can't create an IPVS lb without a service account
	err = c.KubeClient.CoreV1().ServiceAccounts(lbDeploymentNamespace).Delete(context.TODO(), lbDeploymentServiceAccountName, metav1.DeleteOptions{})
	if nil == err {
		t.Fatalf("Expected error making a public ipvs service private: %v, %v. Error: %v", lbDeploymentNamespace, lbDeploymentServiceAccountName, err)
	}

	// Verify we fail when an IPVS lb has cluster networking enabled
	servicePrivateCluster, _ := createTestLoadBalancerServiceIPVS("testIPVSClusterNetworking", "192.168.10.38", false, false)
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, servicePrivateCluster, nodes)
	if nil != status || nil == err {
		t.Fatalf("Unexpected error expected service account to not be created: %v, %v", status, err)
	}
}

func TestEnsureLoadBalancerIPVSCalicoFail(t *testing.T) {
	successCaliCount := 0
	failExecCommand := func(command string, parms ...string) *exec.Cmd {
		cs := []string{"-test.run=TestCalicoExecDummyWithError", "--"}
		cs = append(cs, parms...)
		// #nosec G204 unit test code usage that wouldn't be exploited
		cmd := exec.Command(os.Args[0], cs...)
		cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
		return cmd
	}

	successExecCommand := func(command string, parms ...string) *exec.Cmd {
		cs := []string{"-test.run=TestCalicoExecDummy", "--"}
		cs = append(cs, parms...)
		// #nosec G204 unit test code usage that wouldn't be exploited
		cmd := exec.Command(os.Args[0], cs...)
		cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
		successCaliCount++
		return cmd
	}

	execCommand = failExecCommand
	c, clusterName, _ := getTestCloud()
	service, _ := createTestLoadBalancerServiceIPVS("testIPVSDeleteCMDeploy", "192.168.10.52", true, true)
	service.Spec.LoadBalancerIP = "192.168.10.52"
	status, err := c.EnsureLoadBalancer(context.Background(), clusterName, service, nil)

	if err == nil && status != nil {
		t.Fatalf("Expected calico error returned from EnsureLoadBalancer")
	}

	execCommand = successExecCommand
	// make sure that the 2nd attempt is successful when calico failed in the first attempt
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, service, nil)
	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}
	if successCaliCount != 1 {
		t.Fatalf("Expected successCaliCount to be 1.  Actual value is: %v", successCaliCount)
	}

	// now update the service and force calico to fail during the update
	successCaliCount = 0
	execCommand = failExecCommand
	service.Spec.Ports = []v1.ServicePort{{
		Port:     81,
		Protocol: v1.ProtocolTCP,
	}}
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, service, nil)
	if err == nil && status != nil {
		t.Fatalf("Expected calico error returned from EnsureLoadBalancer")
	}

	// now make sure the update is successful on the 2nd attempt and ensure that calicoctl was called
	execCommand = successExecCommand
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, service, nil)
	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}
	if successCaliCount != 1 {
		t.Fatalf("Expected successCaliCount to be 1.  Actual value is: %v", successCaliCount)
	}

	n1, _, _, _ := createTestCloudNodes()
	nodes := []*v1.Node{n1}
	execCommand = failExecCommand
	successCaliCount = 0
	err = c.UpdateLoadBalancer(context.Background(), clusterName, service, nodes)
	if err == nil {
		t.Fatalf("Expected calico error returned from UpdateLoadBalancer")
	}

	execCommand = successExecCommand
	err = c.UpdateLoadBalancer(context.Background(), clusterName, service, nodes)
	if err != nil {
		t.Fatalf("Expected UpdateLoadBalancer to succeed. Error: %v", err)
	}
	if successCaliCount != 1 {
		t.Fatalf("Expected successCaliCount to be 1.  Actual value is: %v", successCaliCount)
	}
}

func TestEnsureLoadBalancerVlanAnnotation(t *testing.T) {
	var err error
	var status *v1.LoadBalancerStatus
	var d *apps.Deployment

	c, clusterName, _ := getTestCloud()

	// Ensure load balancer created with private IP in dal09 on vlan 2
	privateIPServiceVlanAnnotation := getLoadBalancerService("privateip-vlan-annotation")
	privateIPServiceVlanAnnotation.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	privateIPServiceVlanAnnotation.Annotations[ServiceAnnotationLoadBalancerCloudProviderVlan] = "2"
	privateIPServiceVlanAnnotation.Spec.LoadBalancerIP = "10.10.10.22"
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, privateIPServiceVlanAnnotation, nil)
	if nil == status || nil != err {
		t.Fatalf("Unexpected error ensure load balancer 'privateip-vlan-annotation' created: %v, %v", status, err)
	}
	if 1 != len(status.Ingress) || 0 != strings.Compare("10.10.10.22", status.Ingress[0].IP) || 0 != len(status.Ingress[0].Hostname) {
		t.Fatalf("Unexpected load balancer 'privateip-vlan-annotation' status: %v", status.Ingress[0].IP)
	}
	d, err = c.getLoadBalancerDeployment(getTestLoadBlancerName("privateip-vlan-annotation"))
	if nil == d || nil != err {
		t.Fatalf("Unexpected error finding load balancer 'privateip': %v, %v", d, err)
	}

	// Ensure load balancer fails with vlan from the wrong zone
	privateIPServiceBadZone := getLoadBalancerService("privateip-bad-zone")
	privateIPServiceBadZone.Annotations[ServiceAnnotationLoadBalancerCloudProviderZone] = "dal10"
	privateIPServiceBadZone.Annotations[ServiceAnnotationLoadBalancerCloudProviderVlan] = "1"
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, privateIPServiceBadZone, nil)
	if nil != status || nil == err {
		t.Fatalf("Unexpected ensure load balancer 'privateip-dal10-1' created: %v, %v", status, err)
	}

	// Ensure load balancer fails with random vlan
	privateIPServiceBadVlan := getLoadBalancerService("privateip-bad-vlan")
	privateIPServiceBadVlan.Annotations[ServiceAnnotationLoadBalancerCloudProviderVlan] = "randomVlan"
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, privateIPServiceBadVlan, nil)
	if nil != status || nil == err {
		t.Fatalf("Unexpected ensure load balancer 'privateip-dal10-bad-vlan' created: %v, %v", status, err)
	}

	// Ensure load balancer fails for public ingress controller on wrong vlan
	publicIngressService := getLoadBalancerService("public-ingress-bad-vlan")
	publicIngressService.Annotations[ServiceAnnotationIngressControllerPublic] = "192.168.10.15"
	publicIngressService.Annotations[ServiceAnnotationLoadBalancerCloudProviderVlan] = "2"
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, publicIngressService, nil)
	if nil != status || nil == err {
		t.Fatalf("Unexpected ensure load balancer 'public-ingress-bad-vlan' created: %v, %v", status, err)
	}

	// Ensure load balancer created with only the vlan annotation, on vlan: 4.
	// Note: This has to be the last test since its randomly picking an IP from the vlan
	publicIPServiceVlan := getLoadBalancerService("publicip-vlan-annotation")
	publicIPServiceVlan.Annotations[ServiceAnnotationLoadBalancerCloudProviderVlan] = "4"
	status, err = c.EnsureLoadBalancer(context.Background(), clusterName, publicIPServiceVlan, nil)
	if nil == status || nil != err {
		t.Fatalf("Unexpected error ensure load balancer 'publicip-vlan-annotation' created: %v, %v", status, err)
	}
	if 1 != len(status.Ingress) || !strings.Contains(status.Ingress[0].IP, "192.168.10.4") || 0 != len(status.Ingress[0].Hostname) {
		t.Fatalf("Unexpected load balancer 'publicip-vlan-annotation' status: %v", status.Ingress[0].IP)
	}
	d, err = c.getLoadBalancerDeployment(getTestLoadBlancerName("publicip-vlan-annotation"))
	if nil == d || nil != err {
		t.Fatalf("Unexpected error finding load balancer 'publicip': %v, %v", d, err)
	}
}

func TestEnsureLoadBalancerEdgeLabel(t *testing.T) {
	c, clusterName, _ := getTestCloud()

	// Delete nodes to ensure tests work as previously expected
	err := c.KubeClient.CoreV1().Nodes().Delete(context.TODO(), "192.168.10.7", metav1.DeleteOptions{})
	if err != nil {
		t.Fatalf("Failed to delete the node. Error: %v", err)
	}
	err = c.KubeClient.CoreV1().Nodes().Delete(context.TODO(), "192.168.10.8", metav1.DeleteOptions{})
	if err != nil {
		t.Fatalf("Failed to delete the node. Error: %v", err)
	}

	// Add dedicated=edge label to node2
	node, _ := c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.6", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = lbEdgeNodeValue
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not added to node: 192.168.10.6")
	}

	// Create a private Load Balancer - edge label NOT added to node affinity (because LB is on private network)
	privateIPService := getLoadBalancerService("privateip")
	privateIPService.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	privateIPService.Spec.LoadBalancerIP = "10.10.10.21"
	expectedKeys := map[string]string{lbPrivateVlanLabel: "2"}
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, privateIPService, "privateip", expectedKeys)

	// Create a non-edge Load Balancer - edge label NOT added to node affinity (because publicVLAN for IP selected does not have edge tag)
	nonedgeService := getLoadBalancerService("nonedge")
	expectedKeys = map[string]string{lbPublicVlanLabel: "1"}
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, nonedgeService, "nonedge", expectedKeys)

	// Remove dedicated=edge from node2
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.6", metav1.GetOptions{})
	delete(node.Labels, lbDedicatedLabel)
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 2 {
		t.Fatalf("dedicated label was not removed from node: 192.168.10.6")
	}

	// Add dedicated=edge label to node1
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = lbEdgeNodeValue
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not added to node: 192.168.10.5")
	}

	// Create a edge Load Balancer - edge label added to node affinity
	edgeService := getLoadBalancerService("edge")
	expectedKeys = map[string]string{lbPublicVlanLabel: "1", lbDedicatedLabel: "edge"}
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Create a public Load Balancer - Nil Toleration set. Expecting edge toleration to be added.
	// This tests the case when a cluster with a lb that has been deployed a very long time ago when
	// the edge code was not in production, will be updated with the edge tolerations when the service is updated.
	edgeServiceNilTolerations := getLoadBalancerService("testEdgeNodesWithNilToleration")
	edgeServiceNilTolerations.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "public"
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeServiceNilTolerations, "testEdgeNodesWithNilToleration", expectedKeys)

	// Create a public Load Balancer - Empty Toleration set. Expecting toleration to be added
	// This tests the case when a cluster with a lb that has been deployed a very long time ago when
	// the edge code was not in production, will be updated with the edge tolerations when the service is updated.
	edgeServiceEdgeEmptyTolerations := getLoadBalancerService("testEdgeNodesWithEmptyToleration")
	edgeServiceEdgeEmptyTolerations.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "public"
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeServiceEdgeEmptyTolerations, "testEdgeNodesWithEmptyToleration", expectedKeys)

	// Update edge Load Balancer - edge label should still be applied
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Remove dedicated=edge from node1
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	delete(node.Labels, lbDedicatedLabel)
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 2 {
		t.Fatalf("dedicated label was not removed from node: 192.168.10.5")
	}

	// Update the edge Load Balancer - edge label should be removed
	expectedKeys = map[string]string{lbPublicVlanLabel: "1"}
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Add dedicated=edge label to node1
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = lbEdgeNodeValue
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not added to node: 192.168.10.5")
	}

	// Update edge Load Balancer - edge label should be re-applied
	expectedKeys = map[string]string{lbPublicVlanLabel: "1", lbDedicatedLabel: "edge"}
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Change label on node1 to dedicated=worker
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = "worker"
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not changed oo node: 192.168.10.5")
	}

	// Update the edge Load Balancer - edge label should be removed
	expectedKeys = map[string]string{lbPublicVlanLabel: "1"}
	verifyLoadBalancerEdgeDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)
}

func TestEnsureLoadBalancerGatewayLabel(t *testing.T) {
	c, clusterName, _ := getTestCloud()

	// Delete nodes to ensure tests work as previously expected
	err := c.KubeClient.CoreV1().Nodes().Delete(context.TODO(), "192.168.10.7", metav1.DeleteOptions{})
	if err != nil {
		t.Fatalf("Failed to delete the node. Error: %v", err)
	}
	err = c.KubeClient.CoreV1().Nodes().Delete(context.TODO(), "192.168.10.8", metav1.DeleteOptions{})
	if err != nil {
		t.Fatalf("Failed to delete the node. Error: %v", err)
	}

	// Add dedicated=edge label to node2
	node, _ := c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.6", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = lbGatewayNodeValue
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not added to node: 192.168.10.6")
	}

	// Create a private Load Balancer - edge label NOT added to node affinity (because LB is on private network)
	privateIPService := getLoadBalancerService("privateip")
	privateIPService.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	privateIPService.Spec.LoadBalancerIP = "10.10.10.21"
	expectedKeys := map[string]string{lbPrivateVlanLabel: "2"}
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, privateIPService, "privateip", expectedKeys)

	// Create a non-edge Load Balancer - edge label NOT added to node affinity (because publicVLAN for IP selected does not have edge tag)
	nonedgeService := getLoadBalancerService("nonedge")
	expectedKeys = map[string]string{lbPublicVlanLabel: "1"}
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, nonedgeService, "nonedge", expectedKeys)

	// Remove dedicated=edge from node2
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.6", metav1.GetOptions{})
	delete(node.Labels, lbDedicatedLabel)
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 2 {
		t.Fatalf("dedicated label was not removed from node: 192.168.10.6")
	}

	// Add dedicated=edge label to node1
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = lbGatewayNodeValue
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not added to node: 192.168.10.5")
	}

	// Create a edge Load Balancer - edge label added to node affinity
	edgeService := getLoadBalancerService("edge")
	expectedKeys = map[string]string{lbPublicVlanLabel: "1", lbDedicatedLabel: "gateway"}
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Create a public Load Balancer - Nil Toleration set. Expecting edge toleration to be added.
	// This tests the case when a cluster with a lb that has been deployed a very long time ago when
	// the edge code was not in production, will be updated with the edge tolerations when the service is updated.
	edgeServiceNilTolerations := getLoadBalancerService("testGatewayNodesWithNilToleration")
	edgeServiceNilTolerations.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "public"
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeServiceNilTolerations, "testGatewayNodesWithNilToleration", expectedKeys)

	// Create a public Load Balancer - Empty Toleration set. Expecting toleration to be added
	// This tests the case when a cluster with a lb that has been deployed a very long time ago when
	// the edge code was not in production, will be updated with the edge tolerations when the service is updated.
	edgeServiceEdgeEmptyTolerations := getLoadBalancerService("testGatewayNodesWithEmptyToleration")
	edgeServiceEdgeEmptyTolerations.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "public"
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeServiceEdgeEmptyTolerations, "testGatewayNodesWithEmptyToleration", expectedKeys)

	// Update edge Load Balancer - gateway label should still be applied
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Remove dedicated=gateway from node1
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	delete(node.Labels, lbDedicatedLabel)
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 2 {
		t.Fatalf("dedicated label was not removed from node: 192.168.10.5")
	}

	// Update the edge Load Balancer - gateway label should be removed
	expectedKeys = map[string]string{lbPublicVlanLabel: "1"}
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Add dedicated=gateway label to node1
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = lbGatewayNodeValue
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not added to node: 192.168.10.5")
	}

	// Update gateway Load Balancer - gateway label should be re-applied
	expectedKeys = map[string]string{lbPublicVlanLabel: "1", lbDedicatedLabel: "gateway"}
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)

	// Change label on node1 to dedicated=worker
	node, _ = c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.5", metav1.GetOptions{})
	node.Labels[lbDedicatedLabel] = "worker"
	node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	if len(node.Labels) != 3 {
		t.Fatalf("dedicated label was not changed oo node: 192.168.10.5")
	}

	// Update the edge Load Balancer - edge label should be removed
	expectedKeys = map[string]string{lbPublicVlanLabel: "1"}
	verifyLoadBalancerGatewayDeployment(t, c, clusterName, edgeService, "edge", expectedKeys)
}

func TestEnsureLoadBalancerGatewayEdge(t *testing.T) {
	var cc CloudConfig

	execCommand = func(command string, parms ...string) *exec.Cmd {
		cs := []string{"-test.run=TestCalicoExecDummy", "--"}
		cs = append(cs, parms...)
		// #nosec G204 unit test code usage that wouldn't be exploited
		cmd := exec.Command(os.Args[0], cs...)
		cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
		return cmd
	}
	_, _, cm, _, _, _ := createTestCloudProviderVlanIPConfigMaps()
	sa := createTestServiceAccount()
	cm2, sec1 := createTestCalicoCMandSecret()
	n1 := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "192.168.10.5",
			Labels: map[string]string{lbPublicVlanLabel: "1", lbPrivateVlanLabel: "2", lbDedicatedLabel: lbGatewayNodeValue},
		},
		Status: v1.NodeStatus{
			Addresses: []v1.NodeAddress{
				{
					Type:    v1.NodeInternalIP,
					Address: "192.168.10.5",
				},
			},
		},
	}
	n2 := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "192.168.10.6",
			Labels: map[string]string{lbPublicVlanLabel: "1", lbPrivateVlanLabel: "2", lbDedicatedLabel: lbGatewayNodeValue},
		},
		Status: v1.NodeStatus{
			Addresses: []v1.NodeAddress{
				{
					Type:    v1.NodeInternalIP,
					Address: "192.168.10.6",
				},
			},
		},
	}
	n3 := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "192.168.10.7",
			Labels: map[string]string{lbPrivateVlanLabel: "5"},
		},
	}
	n4 := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "192.168.10.8",
			Labels: map[string]string{lbPrivateVlanLabel: "5"},
		},
	}
	fakeKubeClient := fake.NewSimpleClientset(
		cm, cm2,
		sec1,
		sa,
		n1, n2, n3, n4,
	)
	fakeKubeClientV1 := fake.NewSimpleClientset()

	// Build test cloud.
	cc.Global.Version = "1.0.0"
	cc.Kubernetes.ConfigFilePaths = []string{"../test-fixtures/kubernetes/k8s-config"}
	cc.LBDeployment.Image = "registry.ng.bluemix.net/armada-master/keepalived:1328"
	cc.LBDeployment.Application = "keepalived"
	cc.LBDeployment.VlanIPConfigMap = "ibm-cloud-provider-vlan-ip-config"
	c := Cloud{
		Name:       "ibm",
		KubeClient: fakeKubeClient,
		Config:     &cc,
		Recorder:   NewCloudEventRecorderV1("ibm", fakeKubeClientV1.CoreV1().Events(lbDeploymentNamespace)),
		CloudTasks: map[string]*CloudTask{},
	}

	// run first test to ensure load balancer deployment will be scheduled to nodes with dedicated:gateway label
	service, _ := createTestLoadBalancerServiceIPVS("testGatewayLabel", "192.168.10.30", true, true)
	service.Spec.LoadBalancerIP = "192.168.10.30"
	nodes := []*v1.Node{
		n1, n2, n3, n4,
	}
	status, err := c.EnsureLoadBalancer(context.Background(), "test", service, nodes)

	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}

	deployment, err := c.getLoadBalancerDeployment(getTestLoadBlancerName("testGatewayLabel"))
	if nil == deployment || nil != err {
		t.Fatalf("Unexpected error finding load balancer deployment '%v': %v, %v", "testGatewayLabel", deployment, err)
	}

	matchExpressions := deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions
	if len(matchExpressions) != 2 {
		t.Fatalf("Unexpected matchExpression size: Expected: 2; Actual: %v", len(matchExpressions))
	}
	foundDedicatedGateway := false
	foundPublicVlan1 := false
	for _, matchExpression := range matchExpressions {
		if matchExpression.Key == "dedicated" {
			for _, value := range matchExpression.Values {
				if value == "gateway" {
					foundDedicatedGateway = true
				}
			}
		} else if matchExpression.Key == "publicVLAN" {
			for _, value := range matchExpression.Values {
				if value == "1" {
					foundPublicVlan1 = true
				}
			}
		}
	}

	if !foundDedicatedGateway || !foundPublicVlan1 {
		t.Fatalf("Node Affinity selector incorrect. foundDedicatedGateway = %v; foundPublicVlan1 = %v", foundDedicatedGateway, foundPublicVlan1)
	}

	// now, run a test to make sure load balancer deployments will be still scheduled to nodes with dedicated:gateway label
	// when also introducing the dedicated:edge label on other nodes
	n3.ObjectMeta.Labels = map[string]string{lbPublicVlanLabel: "1", lbPrivateVlanLabel: "5", lbDedicatedLabel: lbEdgeNodeValue}
	n4.ObjectMeta.Labels = map[string]string{lbPublicVlanLabel: "1", lbPrivateVlanLabel: "5", lbDedicatedLabel: lbEdgeNodeValue}
	n3, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), n3, metav1.UpdateOptions{})
	if len(n3.Labels) != 3 {
		t.Fatal("labels on node n3 weren't updated")
	}
	n4, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), n4, metav1.UpdateOptions{})
	if len(n4.Labels) != 3 {
		t.Fatal("labels on node n4 weren't updated")
	}

	service, _ = createTestLoadBalancerServiceIPVS("testGatewayLabel2", "192.168.10.31", true, true)
	service.Spec.LoadBalancerIP = "192.168.10.31"
	nodes = []*v1.Node{
		n1, n2, n3, n4,
	}
	status, err = c.EnsureLoadBalancer(context.Background(), "test", service, nodes)

	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}

	deployment, err = c.getLoadBalancerDeployment(getTestLoadBlancerName("testGatewayLabel2"))
	if nil == deployment || nil != err {
		t.Fatalf("Unexpected error finding load balancer deployment '%v': %v, %v", "testGatewayLabel2", deployment, err)
	}

	matchExpressions = deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions
	if len(matchExpressions) != 2 {
		t.Fatalf("Unexpected matchExpression size: Expected: 2; Actual: %v", len(matchExpressions))
	}
	foundDedicatedGateway = false
	foundPublicVlan1 = false
	for _, matchExpression := range matchExpressions {
		if matchExpression.Key == "dedicated" {
			for _, value := range matchExpression.Values {
				if value == "gateway" {
					foundDedicatedGateway = true
				}
			}
		} else if matchExpression.Key == "publicVLAN" {
			for _, value := range matchExpression.Values {
				if value == "1" {
					foundPublicVlan1 = true
				}
			}
		}
	}

	if !foundDedicatedGateway || !foundPublicVlan1 {
		t.Fatalf("Node Affinity selector incorrect. foundDedicatedGateway = %v; foundPublicVlan1 = %v", foundDedicatedGateway, foundPublicVlan1)
	}

	// run EnsureLoadBalancer again on same service to ensure the update path doesn't move the load
	// balancer to other nodes
	status, err = c.EnsureLoadBalancer(context.Background(), "test", service, nodes)

	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}

	deployment, err = c.getLoadBalancerDeployment(getTestLoadBlancerName("testGatewayLabel2"))
	if nil == deployment || nil != err {
		t.Fatalf("Unexpected error finding load balancer deployment '%v': %v, %v", "testGatewayLabel2", deployment, err)
	}

	matchExpressions = deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions
	if len(matchExpressions) != 2 {
		t.Fatalf("Unexpected matchExpression size: Expected: 2; Actual: %v", len(matchExpressions))
	}
	foundDedicatedGateway = false
	foundPublicVlan1 = false
	for _, matchExpression := range matchExpressions {
		if matchExpression.Key == "dedicated" {
			for _, value := range matchExpression.Values {
				if value == "gateway" {
					foundDedicatedGateway = true
				}
			}
		} else if matchExpression.Key == "publicVLAN" {
			for _, value := range matchExpression.Values {
				if value == "1" {
					foundPublicVlan1 = true
				}
			}
		}
	}

	if !foundDedicatedGateway || !foundPublicVlan1 {
		t.Fatalf("Node Affinity selector incorrect. foundDedicatedGateway = %v; foundPublicVlan1 = %v", foundDedicatedGateway, foundPublicVlan1)
	}

	// now, schedule to a private-only gateway node
	n1.ObjectMeta.Labels = map[string]string{lbPrivateVlanLabel: "2", lbDedicatedLabel: lbGatewayNodeValue}
	n2.ObjectMeta.Labels = map[string]string{lbPrivateVlanLabel: "2", lbDedicatedLabel: lbGatewayNodeValue}
	n3.ObjectMeta.Labels = map[string]string{lbPrivateVlanLabel: "2", lbDedicatedLabel: lbEdgeNodeValue}
	n4.ObjectMeta.Labels = map[string]string{lbPrivateVlanLabel: "2", lbDedicatedLabel: lbEdgeNodeValue}

	nodes = []*v1.Node{
		n1, n2, n3, n4,
	}
	for _, node := range nodes {
		node, _ = c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
		if len(node.Labels) != 2 {
			t.Fatal("labels on node weren't updated")
		}
	}

	service, _ = createTestLoadBalancerServiceIPVS("testGatewayLabelPrivate", "10.10.10.21", true, false)
	service.Spec.LoadBalancerIP = "10.10.10.21"
	status, err = c.EnsureLoadBalancer(context.Background(), "test", service, nodes)

	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}

	deployment, err = c.getLoadBalancerDeployment(getTestLoadBlancerName("testGatewayLabelPrivate"))
	if nil == deployment || nil != err {
		t.Fatalf("Unexpected error finding load balancer deployment '%v': %v, %v", "testGatewayLabelPrivate", deployment, err)
	}

	matchExpressions = deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions
	if len(matchExpressions) != 2 {
		t.Fatalf("Unexpected matchExpression size: Expected: 2; Actual: %v", len(matchExpressions))
	}
	foundDedicatedGateway = false
	foundPrivateVlan2 := false
	for _, matchExpression := range matchExpressions {
		if matchExpression.Key == "dedicated" {
			for _, value := range matchExpression.Values {
				if value == "gateway" {
					foundDedicatedGateway = true
				}
			}
		} else if matchExpression.Key == "privateVLAN" {
			for _, value := range matchExpression.Values {
				if value == "2" {
					foundPrivateVlan2 = true
				}
			}
		}
	}

	if !foundDedicatedGateway || !foundPrivateVlan2 {
		t.Fatalf("Node Affinity selector incorrect. foundDedicatedGateway= %v; foundPublicVlan1 = %v", foundDedicatedGateway, foundPublicVlan1)
	}

	// now update the private service and make sure everything is still kosher
	status, err = c.EnsureLoadBalancer(context.Background(), "test", service, nodes)

	if err != nil && status == nil {
		t.Fatalf("Expected EnsureLoadBalancer to succeed. Error: %v", err)
	}

	deployment, err = c.getLoadBalancerDeployment(getTestLoadBlancerName("testGatewayLabelPrivate"))
	if nil == deployment || nil != err {
		t.Fatalf("Unexpected error finding load balancer deployment '%v': %v, %v", "testGatewayLabelPrivate", deployment, err)
	}

	matchExpressions = deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions
	if len(matchExpressions) != 2 {
		t.Fatalf("Unexpected matchExpression size: Expected: 2; Actual: %v", len(matchExpressions))
	}
	foundDedicatedGateway = false
	foundPrivateVlan2 = false
	for _, matchExpression := range matchExpressions {
		if matchExpression.Key == "dedicated" {
			for _, value := range matchExpression.Values {
				if value == "gateway" {
					foundDedicatedGateway = true
				}
			}
		} else if matchExpression.Key == "privateVLAN" {
			for _, value := range matchExpression.Values {
				if value == "2" {
					foundPrivateVlan2 = true
				}
			}
		}
	}

	if !foundDedicatedGateway || !foundPrivateVlan2 {
		t.Fatalf("Node Affinity selector incorrect. foundDedicatedGateway = %v; foundPublicVlan1 = %v", foundDedicatedGateway, foundPublicVlan1)
	}
}

func TestUpdateLoadBalancer(t *testing.T) {
	c, clusterName, _ := getTestCloud()

	calicoCMDCalled := 0
	// used to ensure the exec for calicoctl is redirected internally
	execCommand = func(command string, parms ...string) *exec.Cmd {
		cs := []string{"-test.run=TestCalicoExecDummy", "--"}
		cs = append(cs, parms...)
		// #nosec G204 unit test code usage that wouldn't be exploited
		cmd := exec.Command(os.Args[0], cs...)
		cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
		calicoCMDCalled++
		return cmd
	}

	servicePublic, cm := createTestLoadBalancerServiceIPVS("testIPVSDeleteCM", "192.168.10.50", true, true)
	n1, n2, _, _ := createTestCloudNodes()
	n3 := &v1.Node{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "192.168.10.8",
			Labels: map[string]string{lbPublicVlanLabel: "1", lbPrivateVlanLabel: "2"},
		},
		Status: v1.NodeStatus{
			Addresses: []v1.NodeAddress{
				{
					Type:    v1.NodeInternalIP,
					Address: "192.168.10.8",
				},
			},
		},
	}
	nodes := []*v1.Node{n1, n2, n3}

	// Load balancer doesn't exist
	err := c.UpdateLoadBalancer(context.Background(), clusterName, getLoadBalancerService("doesntexist"), nodes)
	if nil != err {
		t.Fatalf("Unexpected error ensuring load balancer 'doesntexist' updated: %v", err)
	}

	// Duplicate load balancers exist
	err = c.UpdateLoadBalancer(context.Background(), clusterName, getLoadBalancerService("dup"), nodes)
	if nil == err {
		t.Fatalf("Unexpected load balancer 'dup' updated: %v", err)
	}

	err = c.UpdateLoadBalancer(context.Background(), clusterName, servicePublic, nodes)
	if nil != err {
		t.Fatalf("UpdateLoadBalancer failed: %v", err)
	}

	updatedCm, err := c.KubeClient.CoreV1().ConfigMaps(lbDeploymentNamespace).Get(context.TODO(), cm.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatalf("Unexpected error while attempting to retrieve LB configmap %v", cm.Name)
	}

	if cm.Data["nodes"] == updatedCm.Data["nodes"] {
		t.Fatalf("Unexpected error: configmap node contents unchanged %v", cm.Name)
	}
	if calicoCMDCalled != 1 {
		t.Fatalf("Expected to create the calico policy. Number of times Exec was called to create the Calico policy: %d", calicoCMDCalled)
	}

	// Verify we don't create the calico policy when creating a private LB
	servicePrivate, _ := createTestLoadBalancerServiceIPVS("testEdgeNodesWithEmptyToleration", "192.168.10.38", true, false)
	calicoCMDCalled = 0
	err = c.UpdateLoadBalancer(context.Background(), clusterName, servicePrivate, nodes)
	if nil != err {
		t.Fatalf("UpdateLoadBalancer failed: %v", err)
	}
	if calicoCMDCalled != 0 {
		t.Fatalf("Expected to not create the calico policy. Number of times Exec was called to create the Calico policy: %d", calicoCMDCalled)
	}
}

func TestEnsureLoadBalancerDeleted(t *testing.T) {
	var err error
	var status *v1.LoadBalancerStatus
	var exists bool

	// used to ensure the exec for calicoctl is redirected internally
	execCommand = func(command string, parms ...string) *exec.Cmd {
		cs := []string{"-test.run=TestCalicoExecDummy", "--"}
		cs = append(cs, parms...)
		// #nosec G204 unit test code usage that wouldn't be exploited
		cmd := exec.Command(os.Args[0], cs...)
		cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
		return cmd
	}

	c, clusterName, _ := getTestCloud()

	// Load balancer doesn't exist
	err = c.EnsureLoadBalancerDeleted(context.Background(), clusterName, getLoadBalancerService("doesntexist"))
	if nil != err {
		t.Fatalf("Unexpected error ensuring load balancer 'doesntexist' deleted: %v", err)
	}

	// Duplicate load balancers exist
	err = c.EnsureLoadBalancerDeleted(context.Background(), clusterName, getLoadBalancerService("dup"))
	if nil == err {
		t.Fatalf("Unexpected load balancer 'dup' deleted: %v", err)
	}

	// Ensure load balancer deleted
	err = c.EnsureLoadBalancerDeleted(context.Background(), clusterName, getLoadBalancerService("test"))
	if nil != err {
		t.Fatalf("Unexpected error ensuring load balancer 'test' deleted: %v", err)
	}
	status, exists, err = c.GetLoadBalancer(context.Background(), clusterName, getLoadBalancerService("test"))
	if nil != status || exists || nil != err {
		t.Fatalf("Unexpected load balancer 'test' found: %v, %v, %v", status, exists, err)
	}

	// Ensure load balancer without replicas deleted
	err = c.EnsureLoadBalancerDeleted(context.Background(), clusterName, getLoadBalancerService("noreplicas"))
	if nil != err {
		t.Fatalf("Unexpected error ensuring load balancer 'noreplicas' deleted: %v", err)
	}
	status, exists, err = c.GetLoadBalancer(context.Background(), clusterName, getLoadBalancerService("noreplicas"))
	if nil != status || exists || nil != err {
		t.Fatalf("Unexpected load balancer 'noreplicas' found: %v, %v, %v", status, exists, err)
	}

	// Ensure IPVS load balancer and configmap deleted
	testIPVSDeleteCMService := getLoadBalancerService("testIPVSDeleteCM")
	annotationMap := map[string]string{}
	annotationMap[ServiceAnnotationLoadBalancerCloudProviderEnableFeatures] = lbFeatureIPVS
	testIPVSDeleteCMService.Annotations = annotationMap
	testIPVSDeleteCMService.Spec.LoadBalancerIP = "192.168.10.50"

	err = c.EnsureLoadBalancerDeleted(context.Background(), clusterName, testIPVSDeleteCMService)
	if nil != err {
		t.Fatalf("Unexpected error ensuring load balancer 'testIPVSDeleteCM' deleted: %v", err)
	}
	status, exists, err = c.GetLoadBalancer(context.Background(), clusterName, testIPVSDeleteCMService)
	if nil != status || exists || nil != err {
		t.Fatalf("Unexpected load balancer 'testIPVSDeleteCM' found: %v, %v, %v", status, exists, err)
	}
	cmName := lbDeploymentNamePrefix + getCloudProviderIPLabelValue("192.168.10.50")
	result, err := c.KubeClient.CoreV1().ConfigMaps(lbDeploymentNamespace).Get(context.TODO(), cmName, metav1.GetOptions{})
	if result != nil || err == nil {
		t.Fatalf("Unexpected error in ensuring deleted load balancer 'testIPVSDeleteCM'. Configmap found: %v", cmName)
	}

	// Test: Ensure IPVS private load balancer and configmap deleted
	testIPVSDeleteCMService = getLoadBalancerService("testIPVSDeleteCM")
	testIPVSDeleteCMService.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	testIPVSDeleteCMService.Annotations[ServiceAnnotationLoadBalancerCloudProviderZone] = "dal09"
	testIPVSDeleteCMService.Spec.LoadBalancerIP = "10.10.10.21"
	err = c.EnsureLoadBalancerDeleted(context.Background(), clusterName, testIPVSDeleteCMService)
	if nil != err {
		t.Fatalf("Unexpected error ensuring load balancer 'testIPVSDeleteCM' deleted: %v", err)
	}
	status, exists, err = c.GetLoadBalancer(context.Background(), clusterName, testIPVSDeleteCMService)
	if nil != status || exists || nil != err {
		t.Fatalf("Unexpected load balancer 'testIPVSDeleteCM' found: %v, %v, %v", status, exists, err)
	}
	cmName = lbDeploymentNamePrefix + getCloudProviderIPLabelValue("192.168.10.50")
	result, err = c.KubeClient.CoreV1().ConfigMaps(lbDeploymentNamespace).Get(context.TODO(), cmName, metav1.GetOptions{})
	if result != nil || err == nil {
		t.Fatalf("Unexpected error in ensuring deleted load balancer 'testIPVSDeleteCM'. Configmap found: %v", cmName)
	}
}

func TestMonitorLoadBalancers(t *testing.T) {
	data := map[string]string{
		"atest":        "Fake error",
		"adoesntexist": "Fake error",
	}

	c, _, _ := getTestCloud()

	// Delete The service account to ensure we keep the same flow of the test
	err := c.KubeClient.CoreV1().Services(testNamespace).Delete(context.TODO(), "testIPVSDeleteCMCreate", metav1.DeleteOptions{})
	if nil != err {
		t.Fatalf("Unexpected error remove service account: %v, %v", lbDeploymentNamespace, "testIPVSDeleteCMCreate")
	}

	// Initial monitor should result in new errors.
	MonitorLoadBalancers(c, data)
	if 3 != len(data) || 0 != len(data["atest"]) || 0 == len(data["adup"]) || 0 == len(data["anoreplicas"]) {
		t.Fatalf("Unexpected load balancer monitor data: %v", data)
	}

	// Second monitor should result in warning events.
	MonitorLoadBalancers(c, data)
	if 3 != len(data) || 0 != len(data["atest"]) || 0 == len(data["adup"]) || 0 == len(data["anoreplicas"]) {
		t.Fatalf("Unexpected load balancer monitor data: %v", data)
	}

	data["testSourceIP"] = "Fake error"
	MonitorLoadBalancers(c, data)
	if 4 != len(data) || 0 != len(data["atest"]) || 0 == len(data["adup"]) || 0 == len(data["anoreplicas"]) || 0 == len(data["testSourceIP"]) {
		t.Fatalf("Unexpected load balancer monitor data: %v", data)
	}
}

func TestEnsureLoadBalancerSourceIp(t *testing.T) {
	c, clusterName, _ := getTestCloud()

	expectedServiceSelector := map[string]string{"tomIsCool": "true"}

	// Add dedicated=edge label to node2
	node, _ := c.KubeClient.CoreV1().Nodes().Get(context.TODO(), "192.168.10.6", metav1.GetOptions{})
	c.KubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
	nodeListOptions := metav1.ListOptions{LabelSelector: "privateVLAN=2"}
	nodes, _ := c.KubeClient.CoreV1().Nodes().List(context.TODO(), nodeListOptions)

	if len(nodes.Items) != 2 {
		t.Fatalf("Invalid number of nodes. Test needs 2 nodes to ensure 100 Percent MaxUnavailable pods is applied: %d", len(nodes.Items))
	}

	// Create a private Load Balancer - Enable local only traffic with ServiceExternalTrafficPolicyTypeLocal
	privateIPService := getLoadBalancerService("privateip")
	privateIPService.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	privateIPService.Spec.LoadBalancerIP = "10.10.10.21"
	privateIPService.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
	privateIPService.Spec.Type = v1.ServiceTypeLoadBalancer
	privateIPService.Spec.Selector = expectedServiceSelector

	verifyLoadBalancerSourceIP(t, c, clusterName, privateIPService, "privateip", expectedServiceSelector)

	// Update a Service that has ServiceExternalTrafficPolicyTypeCluster and Deployment affinity set for pod affinity
	privateIPService.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
	verifyLoadBalancerSourceIPRemoved(t, c, clusterName, privateIPService, "privateip", map[string]string{}, len(nodes.Items))

	privateIPService.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
	verifyLoadBalancerSourceIP(t, c, clusterName, privateIPService, "privateip", expectedServiceSelector)

	c.EnsureLoadBalancerDeleted(context.Background(), clusterName, privateIPService)

	privateIPService.Annotations[ServiceAnnotationLoadBalancerCloudProviderEnableFeatures] = lbFeatureIPVS
	verifyLoadBalancerSourceIPIPVS(t, c, clusterName, privateIPService, "privateip", len(nodes.Items))
}

func TestEnsureLoadBalancerSourceIpUpdate(t *testing.T) {

	c, clusterName, _ := getTestCloud()

	expectedServiceSelector := map[string]string{"tomIsCool": "true"}

	nodeListOptions := metav1.ListOptions{LabelSelector: "privateVLAN=2"}
	nodes, _ := c.KubeClient.CoreV1().Nodes().List(context.TODO(), nodeListOptions)

	if len(nodes.Items) != 2 {
		t.Fatalf("Invalid number of nodes. Test needs 2 nodes to ensure 100 Percent MaxUnavailable pods is applied: %d", len(nodes.Items))
	}

	// Create a private Load Balancer - Enable local only traffic with ServiceExternalTrafficPolicyTypeLocal
	privateIPService := getLoadBalancerService("testSourceIP")
	privateIPService.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	privateIPService.Spec.LoadBalancerIP = "192.168.10.36"
	privateIPService.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
	privateIPService.Spec.Type = v1.ServiceTypeLoadBalancer
	privateIPService.Spec.Selector = expectedServiceSelector

	// Update a Service that has ServiceExternalTrafficPolicyTypeLocal and no affinity in deployment
	verifyLoadBalancerSourceIP(t, c, clusterName, privateIPService, "testSourceIP", expectedServiceSelector)

	// Update selector to verify Deployment is updated
	expectedServiceSelector = map[string]string{"tomIsReallyCool": "true", "tomIsNotCool": "false"}
	privateIPService.Spec.Selector = expectedServiceSelector
	verifyLoadBalancerSourceIP(t, c, clusterName, privateIPService, "testSourceIP", expectedServiceSelector)

	// Update selector to verify Deployment is updated
	privateIPService.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
	expectedServiceSelector = map[string]string{"tomIsReallyCool": "true", "tomIsNotCool": "false"}
	privateIPService.Spec.Selector = expectedServiceSelector
	verifyLoadBalancerSourceIP(t, c, clusterName, privateIPService, "testSourceIP", expectedServiceSelector)

	// Update a Service that has ServiceExternalTrafficPolicyTypeCluster and Deployment affinity set for pod affinity
	privateIPService.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
	verifyLoadBalancerSourceIPRemoved(t, c, clusterName, privateIPService, "testSourceIP", map[string]string{}, len(nodes.Items))
	c.EnsureLoadBalancerDeleted(context.Background(), clusterName, privateIPService)

	// Create a private Load Balancer - Enable local only traffic with ServiceExternalTrafficPolicyTypeLocal
	privateIPService1 := getLoadBalancerService("privateipp")
	privateIPService1.Annotations[ServiceAnnotationLoadBalancerCloudProviderIPType] = "private"
	privateIPService1.Spec.LoadBalancerIP = "10.10.10.31"
	privateIPService1.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
	privateIPService1.Spec.Type = v1.ServiceTypeLoadBalancer
	privateIPService1.Spec.Selector = expectedServiceSelector

	nodeListOptions1 := metav1.ListOptions{LabelSelector: "privateVLAN=5"}
	nodes1, _ := c.KubeClient.CoreV1().Nodes().List(context.TODO(), nodeListOptions1)

	if len(nodes1.Items) != 1 {
		t.Fatalf("Invalid number of nodes. Test needs 1 nodes to ensure 100 Percent MaxUnavailable pods is applied: %d", len(nodes1.Items))
	}
	// Update a Service that has ServiceExternalTrafficPolicyTypeLocal and no affinity in deployment
	verifyLoadBalancerSourceIP(t, c, clusterName, privateIPService1, "privateipp", expectedServiceSelector)

	// Update a Service that has ServiceExternalTrafficPolicyTypeCluster and Deployment affinity set for pod affinity
	privateIPService1.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
	verifyLoadBalancerSourceIPRemoved(t, c, clusterName, privateIPService1, "privateipp", map[string]string{}, len(nodes1.Items))
	c.EnsureLoadBalancerDeleted(context.Background(), clusterName, privateIPService1)

	// IPVS Tests
	privateIPService1.Annotations[ServiceAnnotationLoadBalancerCloudProviderEnableFeatures] = lbFeatureIPVS
	privateIPService1.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
	verifyLoadBalancerSourceIPIPVS(t, c, clusterName, privateIPService1, "privateipp", len(nodes1.Items))

	// Update selector to verify Deployment is updated
	expectedServiceSelector = map[string]string{"tomIsReallyCool": "true", "tomIsNotCool": "false"}
	privateIPService1.Spec.Selector = expectedServiceSelector
	verifyLoadBalancerSourceIPIPVS(t, c, clusterName, privateIPService1, "privateipp", len(nodes1.Items))

}

func TestPodAffinityMatchLabelAndServiceSelectorEqual(t *testing.T) {
	checkRequestsOnlyLocalTraffic := func(requestsOnlyLocalTrafficBool bool, lbDeploymentPodAffinity *v1.PodAffinity, serviceSelector map[string]string) {
		res := podAffinityMatchLabelAndServiceSelectorEqual(lbDeploymentPodAffinity, serviceSelector)
		if res != requestsOnlyLocalTrafficBool {
			t.Errorf("Expected requests OnlyLocal traffic = %v, got %v",
				requestsOnlyLocalTrafficBool, res)
		}
	}

	// LB Deployment Match Labels is nil and serviceSelector is empty
	checkRequestsOnlyLocalTraffic(false, &v1.PodAffinity{}, map[string]string{})

	// LB Deployment Match Labels is set and serviceSelector is empty
	checkRequestsOnlyLocalTraffic(false, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{})

	// LB Deployment Match Labels is set and serviceSelector is set and they are equal
	checkRequestsOnlyLocalTraffic(true, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{
		"tomsCool": "true",
	})

	// LB Deployment Match Labels is set and serviceSelector is set and they are equal. But serviceSelector is in a different order
	checkRequestsOnlyLocalTraffic(true, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool1": "true",
						"tomsCool2": "true",
						"tomsCool3": "true",
						"tomsCool4": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{
		"tomsCool3": "true",
		"tomsCool2": "true",
		"tomsCool4": "true",
		"tomsCool1": "true",
	})

	// LB Deployment Match Labels is set and serviceSelector is set and they are equal. But serviceSelector is in a different order
	checkRequestsOnlyLocalTraffic(false, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool5": "true",
						"tomsCool6": "true",
						"tomsCool7": "true",
						"tomsCool8": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			}, {
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool1": "true",
						"tomsCool2": "true",
						"tomsCool3": "true",
						"tomsCool4": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{
		"tomsCool3": "true",
		"tomsCool2": "true",
		"tomsCool4": "true",
		"tomsCool1": "true",
	})

	// LB Deployment Match Labels is set and serviceSelector is set and the Match Labels are a subset of the serviceSelector
	checkRequestsOnlyLocalTraffic(false, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool1": "true",
						"tomsCool2": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{
		"tomsCool3": "true",
		"tomsCool2": "true",
		"tomsCool4": "true",
		"tomsCool1": "true",
	})

	// LB Deployment Match Labels is set and serviceSelector is set and the serviceSelector are a subset of the Match Labels
	checkRequestsOnlyLocalTraffic(false, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool1": "true",
						"tomsCool2": "true",
						"tomsCool3": "true",
						"tomsCool4": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{
		"tomsCool2": "true",
		"tomsCool1": "true",
	})

	// LB Deployment Match Labels and serviceSelector have the same keys but different values
	checkRequestsOnlyLocalTraffic(false, &v1.PodAffinity{
		RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
			{
				LabelSelector: &metav1.LabelSelector{
					MatchLabels: map[string]string{
						"tomsCool1": "true",
						"tomsCool2": "true",
					},
				},
				TopologyKey: v1.LabelHostname,
				Namespaces:  []string{},
			},
		},
	}, map[string]string{
		"tomsCool1": "true",
		"tomsCool2": "false",
	})
}

license_type: permissive

branch_name: refs/heads/master

extension: go


text:
package users

import (
    "context"
    i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f "github.com/microsoft/kiota-abstractions-go"
    iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242 "github.com/microsoftgraph/msgraph-sdk-go/models"
    ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a "github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
)

// ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder provides operations to manage the phoneMethods property of the microsoft.graph.authentication entity.
type ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder struct {
    i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.BaseRequestBuilder
}
// ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderDeleteRequestConfiguration configuration for the request such as headers, query parameters, and middleware options.
type ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderDeleteRequestConfiguration struct {
    // Request headers
    Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders
    // Request options
    Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption
}
// ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetQueryParameters retrieve a single phoneAuthenticationMethod object for a user. This method is available only for standard Azure AD and B2B users, but not B2C users.
type ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetQueryParameters struct {
    // Expand related entities
    Expand []string `uriparametername:"%24expand"`
    // Select properties to be returned
    Select []string `uriparametername:"%24select"`
}
// ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetRequestConfiguration configuration for the request such as headers, query parameters, and middleware options.
type ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetRequestConfiguration struct {
    // Request headers
    Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders
    // Request options
    Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption
    // Request query parameters
    QueryParameters *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetQueryParameters
}
// ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderPatchRequestConfiguration configuration for the request such as headers, query parameters, and middleware options.
type ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderPatchRequestConfiguration struct {
    // Request headers
    Headers *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestHeaders
    // Request options
    Options []i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestOption
}
// NewItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderInternal instantiates a new PhoneAuthenticationMethodItemRequestBuilder and sets the default values.
func NewItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderInternal(pathParameters map[string]string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter)(*ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) {
    m := &ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder{
        BaseRequestBuilder: *i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewBaseRequestBuilder(requestAdapter, "{+baseurl}/users/{user%2Did}/authentication/phoneMethods/{phoneAuthenticationMethod%2Did}{?%24select,%24expand}", pathParameters),
    }
    return m
}
// NewItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder instantiates a new PhoneAuthenticationMethodItemRequestBuilder and sets the default values.
func NewItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder(rawUrl string, requestAdapter i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestAdapter)(*ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) {
    urlParams := make(map[string]string)
    urlParams["request-raw-url"] = rawUrl
    return NewItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderInternal(urlParams, requestAdapter)
}
// Delete delete a user's phone authentication method. This removes the phone number from the user and they will no longer be able to use the number for authentication, whether via SMS or voice calls. A user cannot have an alternateMobile number without a mobile number. If you want to remove a mobile number from a user that also has an alternateMobile number, first update the mobile number to the new number, then delete the alternateMobile number. If the phone number is the user's default Azure multi-factor authentication (MFA) authentication method, it cannot be deleted. Have the user change their default authentication method, and then delete the number.
// [Find more info here]
//
// [Find more info here]: https://learn.microsoft.com/graph/api/phoneauthenticationmethod-delete?view=graph-rest-1.0
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) Delete(ctx context.Context, requestConfiguration *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderDeleteRequestConfiguration)(error) {
    requestInfo, err := m.ToDeleteRequestInformation(ctx, requestConfiguration);
    if err != nil {
        return err
    }
    errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings {
        "4XX": ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a.CreateODataErrorFromDiscriminatorValue,
        "5XX": ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a.CreateODataErrorFromDiscriminatorValue,
    }
    err = m.BaseRequestBuilder.RequestAdapter.SendNoContent(ctx, requestInfo, errorMapping)
    if err != nil {
        return err
    }
    return nil
}
// DisableSmsSignIn provides operations to call the disableSmsSignIn method.
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) DisableSmsSignIn()(*ItemAuthenticationPhoneMethodsItemDisableSmsSignInRequestBuilder) {
    return NewItemAuthenticationPhoneMethodsItemDisableSmsSignInRequestBuilderInternal(m.BaseRequestBuilder.PathParameters, m.BaseRequestBuilder.RequestAdapter)
}
// EnableSmsSignIn provides operations to call the enableSmsSignIn method.
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) EnableSmsSignIn()(*ItemAuthenticationPhoneMethodsItemEnableSmsSignInRequestBuilder) {
    return NewItemAuthenticationPhoneMethodsItemEnableSmsSignInRequestBuilderInternal(m.BaseRequestBuilder.PathParameters, m.BaseRequestBuilder.RequestAdapter)
}
// Get retrieve a single phoneAuthenticationMethod object for a user. This method is available only for standard Azure AD and B2B users, but not B2C users.
// [Find more info here]
//
// [Find more info here]: https://learn.microsoft.com/graph/api/phoneauthenticationmethod-get?view=graph-rest-1.0
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) Get(ctx context.Context, requestConfiguration *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetRequestConfiguration)(iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.PhoneAuthenticationMethodable, error) {
    requestInfo, err := m.ToGetRequestInformation(ctx, requestConfiguration);
    if err != nil {
        return nil, err
    }
    errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings {
        "4XX": ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a.CreateODataErrorFromDiscriminatorValue,
        "5XX": ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a.CreateODataErrorFromDiscriminatorValue,
    }
    res, err := m.BaseRequestBuilder.RequestAdapter.Send(ctx, requestInfo, iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.CreatePhoneAuthenticationMethodFromDiscriminatorValue, errorMapping)
    if err != nil {
        return nil, err
    }
    if res == nil {
        return nil, nil
    }
    return res.(iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.PhoneAuthenticationMethodable), nil
}
// Patch update a user's phone number associated with a phone authentication method object. You can't change a phone's type. To change a phone's type, add a new number of the desired type and then delete the object with the original type. If a user is enabled by policy to use SMS to sign in and the mobile number is changed, the system will attempt to register the number for use in that system.
// [Find more info here]
//
// [Find more info here]: https://learn.microsoft.com/graph/api/phoneauthenticationmethod-update?view=graph-rest-1.0
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) Patch(ctx context.Context, body iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.PhoneAuthenticationMethodable, requestConfiguration *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderPatchRequestConfiguration)(iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.PhoneAuthenticationMethodable, error) {
    requestInfo, err := m.ToPatchRequestInformation(ctx, body, requestConfiguration);
    if err != nil {
        return nil, err
    }
    errorMapping := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.ErrorMappings {
        "4XX": ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a.CreateODataErrorFromDiscriminatorValue,
        "5XX": ia572726a95efa92ddd544552cd950653dc691023836923576b2f4bf716cf204a.CreateODataErrorFromDiscriminatorValue,
    }
    res, err := m.BaseRequestBuilder.RequestAdapter.Send(ctx, requestInfo, iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.CreatePhoneAuthenticationMethodFromDiscriminatorValue, errorMapping)
    if err != nil {
        return nil, err
    }
    if res == nil {
        return nil, nil
    }
    return res.(iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.PhoneAuthenticationMethodable), nil
}
// ToDeleteRequestInformation delete a user's phone authentication method. This removes the phone number from the user and they will no longer be able to use the number for authentication, whether via SMS or voice calls. A user cannot have an alternateMobile number without a mobile number. If you want to remove a mobile number from a user that also has an alternateMobile number, first update the mobile number to the new number, then delete the alternateMobile number. If the phone number is the user's default Azure multi-factor authentication (MFA) authentication method, it cannot be deleted. Have the user change their default authentication method, and then delete the number.
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) ToDeleteRequestInformation(ctx context.Context, requestConfiguration *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderDeleteRequestConfiguration)(*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) {
    requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation()
    requestInfo.UrlTemplate = m.BaseRequestBuilder.UrlTemplate
    requestInfo.PathParameters = m.BaseRequestBuilder.PathParameters
    requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.DELETE
    if requestConfiguration != nil {
        requestInfo.Headers.AddAll(requestConfiguration.Headers)
        requestInfo.AddRequestOptions(requestConfiguration.Options)
    }
    return requestInfo, nil
}
// ToGetRequestInformation retrieve a single phoneAuthenticationMethod object for a user. This method is available only for standard Azure AD and B2B users, but not B2C users.
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) ToGetRequestInformation(ctx context.Context, requestConfiguration *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderGetRequestConfiguration)(*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) {
    requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation()
    requestInfo.UrlTemplate = m.BaseRequestBuilder.UrlTemplate
    requestInfo.PathParameters = m.BaseRequestBuilder.PathParameters
    requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.GET
    requestInfo.Headers.Add("Accept", "application/json")
    if requestConfiguration != nil {
        if requestConfiguration.QueryParameters != nil {
            requestInfo.AddQueryParameters(*(requestConfiguration.QueryParameters))
        }
        requestInfo.Headers.AddAll(requestConfiguration.Headers)
        requestInfo.AddRequestOptions(requestConfiguration.Options)
    }
    return requestInfo, nil
}
// ToPatchRequestInformation update a user's phone number associated with a phone authentication method object. You can't change a phone's type. To change a phone's type, add a new number of the desired type and then delete the object with the original type. If a user is enabled by policy to use SMS to sign in and the mobile number is changed, the system will attempt to register the number for use in that system.
func (m *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilder) ToPatchRequestInformation(ctx context.Context, body iadcd81124412c61e647227ecfc4449d8bba17de0380ddda76f641a29edf2b242.PhoneAuthenticationMethodable, requestConfiguration *ItemAuthenticationPhoneMethodsPhoneAuthenticationMethodItemRequestBuilderPatchRequestConfiguration)(*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.RequestInformation, error) {
    requestInfo := i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.NewRequestInformation()
    requestInfo.UrlTemplate = m.BaseRequestBuilder.UrlTemplate
    requestInfo.PathParameters = m.BaseRequestBuilder.PathParameters
    requestInfo.Method = i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.PATCH
    requestInfo.Headers.Add("Accept", "application/json")
    err := requestInfo.SetContentFromParsable(ctx, m.BaseRequestBuilder.RequestAdapter, "application/json", body)
    if err != nil {
        return nil, err
    }
    if requestConfiguration != nil {
        requestInfo.Headers.AddAll(requestConfiguration.Headers)
        requestInfo.AddRequestOptions(requestConfiguration.Options)
    }
    return requestInfo, nil
}

license: MIT

repository: microsoftgraph/msgraph-sdk-go

repo_name: microsoftgraph/msgraph-sdk-go

branch_name: refs/heads/main

gha_license_id: MIT

gha_language: Go


text:
SUMMARY = "GNOME menus"
SECTION = "x11/gnome"
LICENSE = "GPLv2 & LGPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
                    file://COPYING.LIB;md5=5f30f0716dfdd0d91eb439ebec522ec2"
PR = "r1"

DEPENDS = "python libxml2 gconf popt gtk+ intltool-native"

inherit gnomebase pkgconfig python-dir pythonnative gobject-introspection

SRC_URI[archive.md5sum] = "caa6772e63ed5870cf43dc3d354e0624"
SRC_URI[archive.sha256sum] = "6dcc565006d6e8c2025ae83ab1f82edf6bd04d61c804c0dc9bf5ea50629c4caa"
GNOME_COMPRESS_TYPE="bz2"

do_configure_append () {

    # this expands to native-pthon which we don't want.
    sed -i 's:\@PYTHON\@:/usr/bin/env python:' ${S}/simple-editor/gmenu-simple-editor.in

}
PACKAGES += "${PN}-python ${PN}-python-staticdev"
FILES_${PN} += "${datadir}/desktop-directories/"
FILES_${PN}-python-staticdev = "${PYTHON_SITEPACKAGES_DIR}/gmenu.a ${PYTHON_SITEPACKAGES_DIR}/gmenu.la"
FILES_${PN}-python = "${PYTHON_SITEPACKAGES_DIR}/gmenu.so ${PYTHON_SITEPACKAGES_DIR}/GMenuSimpleEditor "
FILES_${PN}-dbg += "${PYTHON_SITEPACKAGES_DIR}/*/.debug \
                    ${PYTHON_SITEPACKAGES_DIR}/.debug"

# http://errors.yoctoproject.org/Errors/Details/81001/
PNBLACKLIST[gnome-menus] ?= "BROKEN: fails to build because of python"

extension: bb


text:
@inproceedings{Mudaliar2013Unraveling,
    author = {Mudaliar, D. N. and Modi, N. K.},
    booktitle = {Signal Processing Image Processing \& Pattern Recognition (ICSIPR), 2013 International Conference on},
    citeulike-article-id = {12741631},
    citeulike-linkout-0 = {http://dx.doi.org/10.1109/icsipr.2013.6497974},
    citeulike-linkout-1 = {http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=6497974},
    doi = {10.1109/icsipr.2013.6497974},
    institution = {Sardar Vallabhbhai Patel Inst. of Technol., Vasad, India},
    isbn = {978-1-4673-4861-4},
    keywords = {sem6120},
    month = feb,
    pages = {127--130},
    posted-at = {2013-10-31 15:38:07},
    priority = {2},
    publisher = {IEEE},
    title = {Unraveling Travelling Salesman Problem by genetic algorithm using m-crossover operator},
    url = {http://dx.doi.org/10.1109/icsipr.2013.6497974},
    year = {2013}
}

@inproceedings{SanchezVelazco2003Sexual,
    abstract = {In a standard genetic algorithm ({GA}), individuals reproduce asexually: any two organisms may be parents in crossover. Gender separation and sexual selection here inspire a model of gendered {GA} in which crossover takes place only between individuals of opposite sex and the {GA}'s evaluation, selection, and mutation strategies depend on gender. Consequently, a pattern of cross-gender cooperation and intra-gender competition emerges. A symbiotic relation between the selection and crossover operators also arises. Experimental results prove this strategy to be advantageous, significantly outperforming the standard {GA}, both in number of generations required and in the quality of solutions.},
    author = {Sanchez-Velazco, Jose and Bullinaria, John A.},
    booktitle = {In IASTED International Conference on Neural Networks and Computational Intelligence (NCI},
    citeulike-article-id = {7222103},
    citeulike-linkout-0 = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.12.7344},
    keywords = {sem6120},
    posted-at = {2013-10-14 12:13:55},
    priority = {2},
    title = {Sexual Selection with {Competitive/co-Operative} Operators for Genetic Algorithms},
    url = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.12.7344},
    year = {2003}
}

@inproceedings{Whitley1989GENITOR,
    abstract = {This paper reports work done over the past three years using rank-based allocation of reproductive trials. New evidence and arguments are presented which suggest that allocating reproductive trials according to rank is superior to fitness proportionate reproduction. Ranking can not only be used to slow search speed, but also to increase search speed when appropriate. Furthermore, the use of ranking provides a degree of control over selective pressure that is not possible with fitness proportionate reproduction. The use of rank-based allocation of reproductive trials is discussed in the context of 1) Holland's schema theorem, 2) {DeJong}'s standard test suite, and 3) a set of neural net optimization problems that are larger than the problems in the standard test suite. The {GENITOR} algorithm is also discussed; this algorithm is specifically designed to allocate reproductive trials according to rank.},
    author = {Whitley, Darrell},
    booktitle = {Proceedings of the Third International Conference on Genetic Algorithms},
    citeulike-article-id = {7372748},
    citeulike-linkout-0 = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.18.8195},
    keywords = {sem6120},
    pages = {116--121},
    posted-at = {2013-10-14 09:54:23},
    priority = {2},
    title = {The {GENITOR} Algorithm and Selection Pressure: Why {Rank-Based} Allocation of Reproductive Trials is Best},
    url = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.18.8195},
    year = {1989}
}

@article{Rogers1999Genetic,
    abstract = {A method for calculating genetic drift in terms of changing population fitness variance is presented. The method allows for an easy comparison of different selection schemes and exact analytical results are derived for traditional generational selection, steady-state selection with varying generation gap, a simple model of Eshelman's {CHC} algorithm (1991), and (\μ+\λ) evolution strategies. The effects of changing genetic drift on the convergence of a {GA} are demonstrated empirically},
    author = {Rogers, A. and Prügel-Bennett, A.},
    citeulike-article-id = {530576},
    citeulike-linkout-0 = {http://dx.doi.org/10.1109/4235.797972},
    citeulike-linkout-1 = {http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=797972},
    doi = {10.1109/4235.797972},
    institution = {Dept. of Electron. \& Comput. Sci., Southampton Univ., UK},
    issn = {1089-778X},
    journal = {Evolutionary Computation, IEEE Transactions on},
    keywords = {sem6120},
    month = nov,
    number = {4},
    pages = {298--303},
    posted-at = {2013-10-06 15:47:27},
    priority = {2},
    publisher = {IEEE},
    title = {Genetic drift in genetic algorithm selection schemes},
    url = {http://dx.doi.org/10.1109/4235.797972},
    volume = {3},
    year = {1999}
}

@inproceedings{Goldberg1991Comparative,
    abstract = {This paper considers a number of selection schemes commonly used in modern genetic algorithms. Specifically, proportionate reproduction, ranking selection, tournament selection, and Genitor (or \^{A}«steady state") selection are compared on the basis of solutions to deterministic difference or differential equations, which are verified through computer simulations. The analysis provides convenient approximate or exact solutions as well as useful convergence time and growth ratio estimates. The paper recommends practical application of the analyses and suggests a number of paths for more detailed analytical investigation of selection techniques. Keywords: proportionate selection, ranking selection, tournament selection, Genitor, takeover time, time complexity, growth ratio. 1},
    author = {Goldberg, David E. and Deb, Kalyanmoy},
    booktitle = {Foundations of Genetic Algorithms},
    citeulike-article-id = {11621868},
    citeulike-linkout-0 = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.101.9494},
    keywords = {sem6120},
    pages = {69--93},
    posted-at = {2013-10-04 14:33:15},
    priority = {2},
    title = {A comparative analysis of selection schemes used in genetic algorithms},
    url = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.101.9494},
    year = {1991}
}

@inproceedings{Miller1995Genetic,
    abstract = {Tournament selection is a useful and robust selection mechanism commonly used by genetic algorithms. The selection pressure of tournament selection directly varies with the tournament size --- the more competitors, the higher the resulting selection pressure. This article develops a model, based on order statistics, that can be used to quantitatively predict the resulting selection pressure of a tournament of a given size. This model is used to predict the convergence rates of genetic algorithms utilizing tournament selection. While tournament selection is often used in conjunction with noisy (imperfect) fitness functions, little is understood about how the noise affects the resulting selection pressure. The model is extended to quantitatively predict the selection pressure for tournament selection utilizing noisy fitness functions. Given the tournament size and noise level of a noisy fitness function, the extended model is used to predict the resulting selection pressure of tournament...},
    author = {Miller, Brad L. and Miller, Brad L. and Goldberg, David E. and Goldberg, David E.},
    booktitle = {Complex Systems},
    citeulike-article-id = {12686859},
    citeulike-linkout-0 = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.30.6625},
    keywords = {sem6120},
    pages = {193--212},
    posted-at = {2013-10-03 12:32:05},
    priority = {2},
    title = {Genetic Algorithms, Tournament Selection, and the Effects of Noise},
    url = {http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.30.6625},
    year = {1995}
}

@book{Holland1992Adaptation,
    abstract = {John Holland's {\_Adaptation} in Natural and Artificial Systems\_ is one of the
classics in the field of complex adaptive systems. Holland is known as the
father of genetic algorithms and classifier systems and in this tome he
describes the theory behind these algorithms. Drawing on ideas from the fields
of biology and economics, he shows how computer programs can evolve. The book
contains mathematical proofs that are accessible only to those with strong
backgrounds in engineering or science.},
    author = {Holland, John H.},
    citeulike-article-id = {125979},
    citeulike-linkout-0 = {http://www.amazon.ca/exec/obidos/redirect?tag=citeulike09-20&path=ASIN/0262581116},
    citeulike-linkout-1 = {http://www.amazon.de/exec/obidos/redirect?tag=citeulike01-21&path=ASIN/0262581116},
    citeulike-linkout-10 = {http://www.worldcat.org/oclc/803225327},
    citeulike-linkout-2 = {http://www.amazon.fr/exec/obidos/redirect?tag=citeulike06-21&path=ASIN/0262581116},
    citeulike-linkout-3 = {http://www.amazon.jp/exec/obidos/ASIN/0262581116},
    citeulike-linkout-4 = {http://www.amazon.co.uk/exec/obidos/ASIN/0262581116/citeulike00-21},
    citeulike-linkout-5 = {http://www.amazon.com/exec/obidos/redirect?tag=citeulike07-20&path=ASIN/0262581116},
    citeulike-linkout-6 = {http://www.worldcat.org/isbn/0262581116},
    citeulike-linkout-7 = {http://books.google.com/books?vid=ISBN0262581116},
    citeulike-linkout-8 = {http://www.amazon.com/gp/search?keywords=0262581116&index=books&linkCode=qs},
    citeulike-linkout-9 = {http://www.librarything.com/isbn/0262581116},
    day = {29},
    howpublished = {Paperback},
    isbn = {0262581116},
    keywords = {sem6120},
    month = apr,
    posted-at = {2013-10-01 13:32:50},
    priority = {2},
    publisher = {MIT Press},
    title = {Adaptation in natural and artificial systems : an introductory analysis with applications to biology, control, and artificial intelligence},
    url = {http://www.worldcat.org/isbn/0262581116},
    year = {1992}
}

@electronic{Mitchell1996Introduction,
    author = {Mitchell, Melanie},
    citeulike-article-id = {12677232},
    citeulike-linkout-0 = {http://www.worldcat.org/isbn/9780585030944},
    citeulike-linkout-1 = {http://books.google.com/books?vid=ISBN9780585030944},
    citeulike-linkout-2 = {http://www.amazon.com/gp/search?keywords=9780585030944&index=books&linkCode=qs},
    citeulike-linkout-3 = {http://www.librarything.com/isbn/9780585030944},
    citeulike-linkout-4 = {http://www.worldcat.org/oclc/42854439},
    isbn = {9780585030944},
    keywords = {sem6120},
    posted-at = {2013-10-01 12:52:31},
    priority = {2},
    publisher = {MIT Press},
    title = {An introduction to genetic algorithms},
    url = {http://www.worldcat.org/isbn/9780585030944},
    year = {1996}
}

@book{Banzhaf1998Genetic,
    abstract = {This unique introduction to {GP} provides a detailed overview of the subject and its antecedents with extensive references to the published and online literature. In addition to explaining the fundamental theory and important algorithms, the text includes practical discussions covering a wealth of potential applications and real-world implementation techniques. Software professionals needing to understand and apply {GP} concepts will find this book an invaluable practical and theoretical guide.},
    author = {Banzhaf, Wolfgang},
    citeulike-article-id = {12677204},
    citeulike-linkout-0 = {http://www.worldcat.org/isbn/9781558605107},
    citeulike-linkout-1 = {http://books.google.com/books?vid=ISBN9781558605107},
    citeulike-linkout-2 = {http://www.amazon.com/gp/search?keywords=9781558605107&index=books&linkCode=qs},
    citeulike-linkout-3 = {http://www.librarything.com/isbn/9781558605107},
    citeulike-linkout-4 = {http://www.worldcat.org/oclc/38067741},
    isbn = {9781558605107},
    keywords = {sem6120},
    posted-at = {2013-10-01 12:43:37},
    priority = {2},
    publisher = {Morgan Kaufmann Publishers ; Dpunkt-verlag},
    title = {Genetic programming : an introduction on the automatic evolution of computer programs and its applications},
    url = {http://www.worldcat.org/isbn/9781558605107},
    year = {1998}
}

@article{Man1996Genetic,
    author = {Man, K. F. and Tang, K. S. and Kwong, S.},
    citeulike-article-id = {12677102},
    citeulike-linkout-0 = {http://dx.doi.org/10.1109/41.538609},
    citeulike-linkout-1 = {http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=538609},
    doi = {10.1109/41.538609},
    institution = {City Univ. of Hong Kong, Hong Kong},
    issn = {0278-0046},
    journal = {Industrial Electronics, IEEE Transactions on},
    keywords = {sem6120},
    month = oct,
    number = {5},
    pages = {519--534},
    posted-at = {2013-10-01 12:12:22},
    priority = {2},
    publisher = {IEEE},
    title = {Genetic algorithms: concepts and applications [in engineering design]},
    url = {http://dx.doi.org/10.1109/41.538609},
    volume = {43},
    year = {1996}
}

license: Unlicense

extension: bib


text:
package keeper

import (
	"fmt"

	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/ixofoundation/ixo-blockchain/x/bonds/types"
	didexported "github.com/ixofoundation/ixo-blockchain/x/did/exported"
	"github.com/tendermint/go-amino"
)

func (k Keeper) GetBondIterator(ctx sdk.Context) sdk.Iterator {
	store := ctx.KVStore(k.storeKey)
	return sdk.KVStorePrefixIterator(store, types.BondsKeyPrefix)
}

func (k Keeper) GetBond(ctx sdk.Context, bondDid didexported.Did) (bond types.Bond, found bool) {
	store := ctx.KVStore(k.storeKey)
	if !k.BondExists(ctx, bondDid) {
		return
	}
	bz := store.Get(types.GetBondKey(bondDid))
	k.cdc.MustUnmarshalBinaryBare(bz, &bond)

	return bond, true
}

func (k Keeper) GetBondDid(ctx sdk.Context, bondToken string) (bondDid didexported.Did, found bool) {
	store := ctx.KVStore(k.storeKey)
	if !k.BondDidExists(ctx, bondToken) {
		return
	}
	bz := store.Get(types.GetBondDidsKey(bondToken))
	amino.MustUnmarshalBinaryBare(bz, &bondDid)

	return bondDid, true
}

func (k Keeper) MustGetBond(ctx sdk.Context, bondDid didexported.Did) types.Bond {
	bond, found := k.GetBond(ctx, bondDid)
	if !found {
		panic(fmt.Sprintf("bond '%s' not found\n", bondDid))
	}
	return bond
}

func (k Keeper) MustGetBondByKey(ctx sdk.Context, key []byte) types.Bond {
	store := ctx.KVStore(k.storeKey)
	if !store.Has(key) {
		panic("bond not found")
	}

	bz := store.Get(key)
	var bond types.Bond
	k.cdc.MustUnmarshalBinaryBare(bz, &bond)

	return bond
}

func (k Keeper) BondExists(ctx sdk.Context, bondDid didexported.Did) bool {
	store := ctx.KVStore(k.storeKey)
	return store.Has(types.GetBondKey(bondDid))
}

func (k Keeper) BondDidExists(ctx sdk.Context, bondToken string) bool {
	store := ctx.KVStore(k.storeKey)
	return store.Has(types.GetBondDidsKey(bondToken))
}

func (k Keeper) SetBond(ctx sdk.Context, bondDid didexported.Did, bond types.Bond) {
	store := ctx.KVStore(k.storeKey)
	store.Set(types.GetBondKey(bondDid), k.cdc.MustMarshalBinaryBare(&bond))
}

func (k Keeper) SetBondDid(ctx sdk.Context, bondToken string, bondDid didexported.Did) {
	store := ctx.KVStore(k.storeKey)
	store.Set(types.GetBondDidsKey(bondToken), amino.MustMarshalBinaryBare(bondDid))
}

func (k Keeper) DepositIntoReserve(ctx sdk.Context, bondDid didexported.Did,
	from sdk.AccAddress, amount sdk.Coins) error {

	// Send tokens to bonds reserve account
	err := k.BankKeeper.SendCoinsFromAccountToModule(
		ctx, from, types.BondsReserveAccount, amount)
	if err != nil {
		return err
	}

	// Update bond reserve
	bond := k.MustGetBond(ctx, bondDid)
	k.setReserveBalances(ctx, bondDid, bond.CurrentReserve.Add(amount...))
	k.setAvailableReserve(ctx, bondDid, bond.AvailableReserve.Add(amount...))
	return nil
}

func (k Keeper) DepositOutcomePayment(ctx sdk.Context, bondDid didexported.Did,
	from sdk.AccAddress, amount sdk.Coins) error {

	// Send tokens to bonds reserve account
	err := k.BankKeeper.SendCoinsFromAccountToModule(
		ctx, from, types.BondsReserveAccount, amount)
	if err != nil {
		return err
	}

	// Update bond outcome payment reserve
	k.setOutcomePaymentReserveBalances(ctx, bondDid,
		k.MustGetBond(ctx, bondDid).CurrentOutcomePaymentReserve.Add(amount...))
	return nil
}

func (k Keeper) DepositReserveFromModule(ctx sdk.Context, bondDid didexported.Did,
	fromModule string, amount sdk.Coins) error {

	// Send tokens to bonds reserve account
	err := k.BankKeeper.SendCoinsFromModuleToModule(
		ctx, fromModule, types.BondsReserveAccount, amount)
	if err != nil {
		return err
	}

	// Update bond reserve and available reserve
	bond := k.MustGetBond(ctx, bondDid)
	k.setReserveBalances(ctx, bondDid, bond.CurrentReserve.Add(amount...))
	k.setAvailableReserve(ctx, bondDid, bond.AvailableReserve.Add(amount...))
	return nil
}

func (k Keeper) WithdrawFromReserve(ctx sdk.Context, bondDid didexported.Did,
	to sdk.AccAddress, amount sdk.Coins) error {

	// Send tokens from bonds reserve account
	err := k.BankKeeper.SendCoinsFromModuleToAccount(
		ctx, types.BondsReserveAccount, to, amount)
	if err != nil {
		return err
	}

	// Update bond reserve and available reserve
	bond := k.MustGetBond(ctx, bondDid)
	k.setReserveBalances(ctx, bondDid, bond.CurrentReserve.Sub(amount))
	k.setAvailableReserve(ctx, bondDid, bond.AvailableReserve.Sub(amount))
	return nil
}

func (k Keeper) MoveOutcomePaymentToReserve(ctx sdk.Context, bondDid didexported.Did) {

	bond := k.MustGetBond(ctx, bondDid)
	newReserve := bond.CurrentReserve.Add(bond.CurrentOutcomePaymentReserve...)
	newAvailableReserve := bond.AvailableReserve.Add(bond.CurrentOutcomePaymentReserve...)

	// Update bond reserve, available reserve and outcome payment reserve
	k.setReserveBalances(ctx, bondDid, newReserve)
	k.setAvailableReserve(ctx, bondDid, newAvailableReserve)
	k.setOutcomePaymentReserveBalances(ctx, bondDid, nil)
}

func (k Keeper) setReserveBalances(ctx sdk.Context, bondDid didexported.Did, balance sdk.Coins) {
	bond := k.MustGetBond(ctx, bondDid)
	bond.CurrentReserve = balance
	k.SetBond(ctx, bondDid, bond)
}

func (k Keeper) setAvailableReserve(ctx sdk.Context, bondDid didexported.Did, availableReserve sdk.Coins) {
	bond := k.MustGetBond(ctx, bondDid)
	bond.AvailableReserve = availableReserve
	k.SetBond(ctx, bondDid, bond)
}

func (k Keeper) setOutcomePaymentReserveBalances(ctx sdk.Context, bondDid didexported.Did, balance sdk.Coins) {
	bond := k.MustGetBond(ctx, bondDid)
	bond.CurrentOutcomePaymentReserve = balance
	k.SetBond(ctx, bondDid, bond)
}

func (k Keeper) GetReserveBalances(ctx sdk.Context, bondDid didexported.Did) sdk.Coins {
	return k.MustGetBond(ctx, bondDid).CurrentReserve
}

func (k Keeper) GetAvailableReserve(ctx sdk.Context, bondDid didexported.Did) sdk.Coins {
	return k.MustGetBond(ctx, bondDid).AvailableReserve
}

func (k Keeper) GetSupplyAdjustedForBuy(ctx sdk.Context, bondDid didexported.Did) sdk.Coin {
	bond := k.MustGetBond(ctx, bondDid)
	batch := k.MustGetBatch(ctx, bondDid)
	supply := bond.CurrentSupply
	return supply.Add(batch.TotalBuyAmount)
}

func (k Keeper) GetSupplyAdjustedForSell(ctx sdk.Context, bondDid didexported.Did) sdk.Coin {
	bond := k.MustGetBond(ctx, bondDid)
	batch := k.MustGetBatch(ctx, bondDid)
	supply := bond.CurrentSupply
	return supply.Sub(batch.TotalSellAmount)
}

func (k Keeper) GetSupplyAdjustedForAlphaEdit(ctx sdk.Context, bondDid didexported.Did) sdk.Coin {
	bond := k.MustGetBond(ctx, bondDid)
	batch := k.MustGetBatch(ctx, bondDid)
	supply := bond.CurrentSupply
	return supply.Add(batch.TotalBuyAmount).Sub(batch.TotalSellAmount)
}

func (k Keeper) SetCurrentSupply(ctx sdk.Context, bondDid didexported.Did, currentSupply sdk.Coin) {
	if currentSupply.IsNegative() {
		panic("current supply cannot be negative")
	}
	bond := k.MustGetBond(ctx, bondDid)
	bond.CurrentSupply = currentSupply
	k.SetBond(ctx, bondDid, bond)
}

func (k Keeper) SetBondState(ctx sdk.Context, bondDid didexported.Did, newState string) {
	bond := k.MustGetBond(ctx, bondDid)
	previousState := bond.State
	bond.State = newState
	k.SetBond(ctx, bondDid, bond)

	logger := k.Logger(ctx)
	logger.Info(fmt.Sprintf("updated state for %s from %s to %s", bond.Token, previousState, newState))

	ctx.EventManager().EmitEvent(sdk.NewEvent(
		types.EventTypeStateChange,
		sdk.NewAttribute(types.AttributeKeyBondDid, bond.BondDid),
		sdk.NewAttribute(types.AttributeKeyOldState, previousState),
		sdk.NewAttribute(types.AttributeKeyNewState, newState),
	))
}

func (k Keeper) ReservedBondToken(ctx sdk.Context, bondToken string) bool {
	reservedBondTokens := k.GetParams(ctx).ReservedBondTokens
	for _, rbt := range reservedBondTokens {
		if bondToken == rbt {
			return true
		}
	}
	return false
}

repository: franono/ixo-blockchain

repo_name: franono/ixo-blockchain


text:
SRCREV_edk2           ?= "872f953262d68a11da7bc2fb3ded16df234b8700"
SRCREV_edk2-platforms ?= "3f71a8fb114ae9ce87281eb30ab0e678f6806b05"

require edk2-firmware.inc

repository: akavoukis/meta-arm

repo_name: akavoukis/meta-arm


text:
@InProceedings{salah16,
  supplementary = {Supplementary:salah16-supp.pdf},
  title = {Model-based Co-clustering for High Dimensional Sparse Data},
  author = {Salah, Aghiles and Rogovschi, Nicoleta and Nadif, Mohamed},
  pages = {866-874},
  abstract = {We propose a novel model based on the von Mises-Fisher (vMF) distribution for co-clustering high dimensional sparse matrices. While existing vMF-based models are only suitable for clustering along one dimension, our model acts simultaneously on both dimensions of a data matrix. Thereby it has the advantage of exploiting the inherent duality between rows and columns. Setting our model under the maximum likelihood (ML) approach and the classification ML (CML) approach, we derive two novel, hard and soft, co-clustering algorithms. Empirical results on numerous synthetic and real-world text datasets, demonstrate the effectiveness of our approach, for modelling high dimensional sparse data and co-clustering. Furthermore, thanks to our formulation, that performs an implicitly adaptive dimensionality reduction at each stage, our model alleviates the problem of high concentration parameters kappa's, a well known difficulty in the classical vMF-based models.},
}

repository: mreid/papersite

repo_name: mreid/papersite

gha_language: TeX


text:
@InProceedings{nsss-aplas12,
  author = 	 {{J}.{A}.{N}avas, {P}. {S}chachte and {H}. {S}{\o}ndergaard} and {P}. {J}. {S}tuckey},
  title = 	 {{S}ignedness-{A}gnostic {P}rogram {A}nalysis: {P}recise {I}nteger {B}ounds for {L}ow-{L}evel {C}ode},
  booktitle = {10th APLAS},
  publisher = springer,
  series    = lncs,
  notes     = {To appear.}
  year      = {2012}
}