text:
package cloud

import (
	"context"
	"errors"
	"reflect"
	"testing"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/client-go/kubernetes/fake"
	"k8s.io/client-go/kubernetes/scheme"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/client-go/informers"
	"k8s.io/client-go/tools/record"
	"k8s.io/cloud-provider"
	fakecloud "k8s.io/cloud-provider/fake"
	"k8s.io/kubernetes/pkg/controller/testutil"
	kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
	schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"

	"github.com/stretchr/testify/assert"
	"k8s.io/klog"
)

func TestEnsureNodeExistsByProviderID(t *testing.T) {

	testCases := []struct {
		testName           string
		node               *v1.Node
		expectedCalls      []string
		expectedNodeExists bool
		hasInstanceID      bool
		existsByProviderID bool
		nodeNameErr        error
		providerIDErr      error
	}{
		{
			testName:           "node exists by provider id",
			existsByProviderID: true,
			providerIDErr:      nil,
			hasInstanceID:      true,
			nodeNameErr:        errors.New("unimplemented"),
			expectedCalls:      []string{"instance-exists-by-provider-id"},
			expectedNodeExists: true,
			node: &v1.Node{
				ObjectMeta: metav1.ObjectMeta{
					Name: "node0",
				},
				Spec: v1.NodeSpec{
					ProviderID: "node0",
				},
			},
		},
		{
			testName:           "does not exist by provider id",
			existsByProviderID: false,
			providerIDErr:      nil,
			hasInstanceID:      true,
			nodeNameErr:        errors.New("unimplemented"),
			expectedCalls:      []string{"instance-exists-by-provider-id"},
			expectedNodeExists: false,
			node: &v1.Node{
				ObjectMeta: metav1.ObjectMeta{
					Name: "node0",
				},
				Spec: v1.NodeSpec{
					ProviderID: "node0",
				},
			},
		},
		{
			testName:           "exists by instance id",
			existsByProviderID: true,
			providerIDErr:      nil,
			hasInstanceID:      true,
			nodeNameErr:        nil,
			expectedCalls:      []string{"instance-id", "instance-exists-by-provider-id"},
			expectedNodeExists: true,
			node: &v1.Node{
				ObjectMeta: metav1.ObjectMeta{
					Name: "node0",
				},
			},
		},
		{
			testName:           "does not exist by no instance id",
			existsByProviderID: true,
			providerIDErr:      nil,
			hasInstanceID:      false,
			nodeNameErr:        cloudprovider.InstanceNotFound,
			expectedCalls:      []string{"instance-id"},
			expectedNodeExists: false,
			node: &v1.Node{
				ObjectMeta: metav1.ObjectMeta{
					Name: "node0",
				},
			},
		},
		{
			testName:           "provider id returns error",
			existsByProviderID: false,
			providerIDErr:      errors.New("unimplemented"),
			hasInstanceID:      true,
			nodeNameErr:        cloudprovider.InstanceNotFound,
			expectedCalls:      []string{"instance-exists-by-provider-id"},
			expectedNodeExists: false,
			node: &v1.Node{
				ObjectMeta: metav1.ObjectMeta{
					Name: "node0",
				},
				Spec: v1.NodeSpec{
					ProviderID: "node0",
				},
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.testName, func(t *testing.T) {
			fc := &fakecloud.Cloud{
				ExistsByProviderID: tc.existsByProviderID,
				Err:                tc.nodeNameErr,
				ErrByProviderID:    tc.providerIDErr,
			}

			if tc.hasInstanceID {
				fc.ExtID = map[types.NodeName]string{
					types.NodeName(tc.node.Name): "provider-id://a",
				}
			}

			instances, _ := fc.Instances()
			exists, err := ensureNodeExistsByProviderID(context.TODO(), instances, tc.node)
			assert.Equal(t, err, tc.providerIDErr)

			assert.EqualValues(t, tc.expectedCalls, fc.Calls,
				"expected cloud provider methods `%v` to be called but `%v` was called ",
				tc.expectedCalls, fc.Calls)

			assert.Equal(t, tc.expectedNodeExists, exists,
				"expected exists to be `%t` but got `%t`",
				tc.existsByProviderID, exists)
		})
	}

}

// This test checks that a node with the external cloud provider taint is cloudprovider initialized
func TestNodeInitialized(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{
			types.NodeName("node0"): "t1.micro",
		},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Err: nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:                fnh,
		nodeInformer:              factory.Core().V1().Nodes(),
		cloud:                     fakeCloud,
		recorder:                  eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
		nodeStatusUpdateFrequency: 1 * time.Second,
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	assert.Equal(t, 0, len(fnh.UpdatedNodes[0].Spec.Taints), "Node Taint was not removed after cloud init")
}

// This test checks that a node without the external cloud provider taint are NOT cloudprovider initialized
func TestNodeIgnored(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{
			types.NodeName("node0"): "t1.micro",
		},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Err: nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:   fnh,
		nodeInformer: factory.Core().V1().Nodes(),
		cloud:        fakeCloud,
		recorder:     eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])
	assert.Equal(t, 0, len(fnh.UpdatedNodes), "Node was wrongly updated")

}

// This test checks that a node with the external cloud provider taint is cloudprovider initialized and
// the GCE route condition is added if cloudprovider is GCE
func TestGCECondition(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{
			types.NodeName("node0"): "t1.micro",
		},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Provider: "gce",
		Err:      nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:   fnh,
		nodeInformer: factory.Core().V1().Nodes(),
		cloud:        fakeCloud,
		recorder:     eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	assert.Equal(t, 2, len(fnh.UpdatedNodes[0].Status.Conditions), "No new conditions were added for GCE")

	conditionAdded := false
	for _, cond := range fnh.UpdatedNodes[0].Status.Conditions {
		if cond.Status == "True" && cond.Type == "NetworkUnavailable" && cond.Reason == "NoRouteCreated" {
			conditionAdded = true
		}
	}

	assert.True(t, conditionAdded, "Network Route Condition for GCE not added by external cloud initializer")
}

// This test checks that a node with the external cloud provider taint is cloudprovider initialized and
// and that zone labels are added correctly
func TestZoneInitialized(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
					Labels:            map[string]string{},
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{
			types.NodeName("node0"): "t1.micro",
		},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Provider: "aws",
		Zone: cloudprovider.Zone{
			FailureDomain: "us-west-1a",
			Region:        "us-west",
		},
		Err: nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:   fnh,
		nodeInformer: factory.Core().V1().Nodes(),
		cloud:        fakeCloud,
		recorder:     eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	assert.Equal(t, 4, len(fnh.UpdatedNodes[0].ObjectMeta.Labels),
		"Node label for Region and Zone were not set")
	assert.Equal(t, "us-west", fnh.UpdatedNodes[0].ObjectMeta.Labels[v1.LabelZoneRegionStable],
		"Node Region not correctly updated")
	assert.Equal(t, "us-west-1a", fnh.UpdatedNodes[0].ObjectMeta.Labels[v1.LabelZoneFailureDomainStable],
		"Node FailureDomain not correctly updated")
	assert.Equal(t, "us-west", fnh.UpdatedNodes[0].ObjectMeta.Labels[v1.LabelZoneRegion],
		"Node Region not correctly updated")
	assert.Equal(t, "us-west-1a", fnh.UpdatedNodes[0].ObjectMeta.Labels[v1.LabelZoneFailureDomain],
		"Node FailureDomain not correctly updated")
}

// This test checks that a node with the external cloud provider taint is cloudprovider initialized and
// and nodeAddresses are updated from the cloudprovider
func TestNodeAddresses(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
					Labels:            map[string]string{},
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    "ImproveCoverageTaint",
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Provider: "aws",
		Zone: cloudprovider.Zone{
			FailureDomain: "us-west-1a",
			Region:        "us-west",
		},
		ExistsByProviderID: true,
		Err:                nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:                fnh,
		nodeInformer:              factory.Core().V1().Nodes(),
		cloud:                     fakeCloud,
		nodeStatusUpdateFrequency: 1 * time.Second,
		recorder:                  eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	assert.Equal(t, 3, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status not updated")

	fakeCloud.Addresses = []v1.NodeAddress{
		{
			Type:    v1.NodeHostName,
			Address: "node0.cloud.internal",
		},
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
	}

	cloudNodeController.UpdateNodeStatus(context.TODO())

	updatedNodes := fnh.GetUpdatedNodesCopy()

	assert.Equal(t, 2, len(updatedNodes[0].Status.Addresses), "Node Addresses not correctly updated")

}

// This test checks that a node with the external cloud provider taint is cloudprovider initialized and
// and the provided node ip is validated with the cloudprovider and nodeAddresses are updated from the cloudprovider
func TestNodeProvidedIPAddresses(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
					Labels:            map[string]string{},
					Annotations: map[string]string{
						kubeletapis.AnnotationProvidedIPAddr: "10.0.0.1",
					},
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
					Addresses: []v1.NodeAddress{
						{
							Type:    v1.NodeHostName,
							Address: "node0.cloud.internal",
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    "ImproveCoverageTaint",
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
					ProviderID: "node0.aws.12345",
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{
			types.NodeName("node0"):           "t1.micro",
			types.NodeName("node0.aws.12345"): "t2.macro",
		},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Provider: "aws",
		Zone: cloudprovider.Zone{
			FailureDomain: "us-west-1a",
			Region:        "us-west",
		},
		ExistsByProviderID: true,
		Err:                nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:                fnh,
		nodeInformer:              factory.Core().V1().Nodes(),
		cloud:                     fakeCloud,
		nodeStatusUpdateFrequency: 1 * time.Second,
		recorder:                  eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	assert.Equal(t, 3, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status unexpectedly updated")

	cloudNodeController.UpdateNodeStatus(context.TODO())

	updatedNodes := fnh.GetUpdatedNodesCopy()

	assert.Equal(t, 3, len(updatedNodes[0].Status.Addresses), "Node Addresses not correctly updated")
	assert.Equal(t, "10.0.0.1", updatedNodes[0].Status.Addresses[0].Address, "Node Addresses not correctly updated")
}

func Test_reconcileNodeLabels(t *testing.T) {
	testcases := []struct {
		name           string
		labels         map[string]string
		expectedLabels map[string]string
		expectedErr    error
	}{
		{
			name: "requires reconcile",
			labels: map[string]string{
				v1.LabelZoneFailureDomain: "foo",
				v1.LabelZoneRegion:        "bar",
				v1.LabelInstanceType:      "the-best-type",
			},
			expectedLabels: map[string]string{
				v1.LabelZoneFailureDomain:       "foo",
				v1.LabelZoneRegion:              "bar",
				v1.LabelZoneFailureDomainStable: "foo",
				v1.LabelZoneRegionStable:        "bar",
				v1.LabelInstanceType:            "the-best-type",
				v1.LabelInstanceTypeStable:      "the-best-type",
			},
			expectedErr: nil,
		},
		{
			name: "doesn't require reconcile",
			labels: map[string]string{
				v1.LabelZoneFailureDomain:       "foo",
				v1.LabelZoneRegion:              "bar",
				v1.LabelZoneFailureDomainStable: "foo",
				v1.LabelZoneRegionStable:        "bar",
				v1.LabelInstanceType:            "the-best-type",
				v1.LabelInstanceTypeStable:      "the-best-type",
			},
			expectedLabels: map[string]string{
				v1.LabelZoneFailureDomain:       "foo",
				v1.LabelZoneRegion:              "bar",
				v1.LabelZoneFailureDomainStable: "foo",
				v1.LabelZoneRegionStable:        "bar",
				v1.LabelInstanceType:            "the-best-type",
				v1.LabelInstanceTypeStable:      "the-best-type",
			},
			expectedErr: nil,
		},
		{
			name: "require reconcile -- secondary labels are different from primary",
			labels: map[string]string{
				v1.LabelZoneFailureDomain:       "foo",
				v1.LabelZoneRegion:              "bar",
				v1.LabelZoneFailureDomainStable: "wrongfoo",
				v1.LabelZoneRegionStable:        "wrongbar",
				v1.LabelInstanceType:            "the-best-type",
				v1.LabelInstanceTypeStable:      "the-wrong-type",
			},
			expectedLabels: map[string]string{
				v1.LabelZoneFailureDomain:       "foo",
				v1.LabelZoneRegion:              "bar",
				v1.LabelZoneFailureDomainStable: "foo",
				v1.LabelZoneRegionStable:        "bar",
				v1.LabelInstanceType:            "the-best-type",
				v1.LabelInstanceTypeStable:      "the-best-type",
			},
			expectedErr: nil,
		},
	}

	for _, test := range testcases {
		t.Run(test.name, func(t *testing.T) {
			testNode := &v1.Node{
				ObjectMeta: metav1.ObjectMeta{
					Name:   "node01",
					Labels: test.labels,
				},
			}

			clientset := fake.NewSimpleClientset(testNode)
			factory := informers.NewSharedInformerFactory(clientset, 0)

			cnc := &CloudNodeController{
				kubeClient:   clientset,
				nodeInformer: factory.Core().V1().Nodes(),
			}

			// activate node informer
			factory.Core().V1().Nodes().Informer()
			factory.Start(nil)
			factory.WaitForCacheSync(nil)

			err := cnc.reconcileNodeLabels("node01")
			if err != test.expectedErr {
				t.Logf("actual err: %v", err)
				t.Logf("expected err: %v", test.expectedErr)
				t.Errorf("unexpected error")
			}

			actualNode, err := clientset.CoreV1().Nodes().Get("node01", metav1.GetOptions{})
			if err != nil {
				t.Fatalf("error getting updated node: %v", err)
			}

			if !reflect.DeepEqual(actualNode.Labels, test.expectedLabels) {
				t.Logf("actual node labels: %v", actualNode.Labels)
				t.Logf("expected node labels: %v", test.expectedLabels)
				t.Errorf("updated node did not match expected node")
			}
		})
	}

}

// Tests that node address changes are detected correctly
func TestNodeAddressesChangeDetected(t *testing.T) {
	addressSet1 := []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.163",
		},
	}
	addressSet2 := []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.163",
		},
	}

	assert.False(t, nodeAddressesChangeDetected(addressSet1, addressSet2),
		"Node address changes are not detected correctly")

	addressSet1 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.164",
		},
	}
	addressSet2 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.163",
		},
	}

	assert.True(t, nodeAddressesChangeDetected(addressSet1, addressSet2),
		"Node address changes are not detected correctly")

	addressSet1 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.164",
		},
		{
			Type:    v1.NodeHostName,
			Address: "hostname.zone.region.aws.test",
		},
	}
	addressSet2 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.164",
		},
	}

	assert.True(t, nodeAddressesChangeDetected(addressSet1, addressSet2),
		"Node address changes are not detected correctly")

	addressSet1 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.164",
		},
	}
	addressSet2 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.164",
		},
		{
			Type:    v1.NodeHostName,
			Address: "hostname.zone.region.aws.test",
		},
	}

	assert.True(t, nodeAddressesChangeDetected(addressSet1, addressSet2),
		"Node address changes are not detected correctly")

	addressSet1 = []v1.NodeAddress{
		{
			Type:    v1.NodeExternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeInternalIP,
			Address: "132.143.154.163",
		},
	}
	addressSet2 = []v1.NodeAddress{
		{
			Type:    v1.NodeInternalIP,
			Address: "10.0.0.1",
		},
		{
			Type:    v1.NodeExternalIP,
			Address: "132.143.154.163",
		},
	}

	assert.True(t, nodeAddressesChangeDetected(addressSet1, addressSet2),
		"Node address changes are not detected correctly")
}

// This test checks that a node with the external cloud provider taint is cloudprovider initialized and
// and node addresses will not be updated when node isn't present according to the cloudprovider
func TestNodeAddressesNotUpdate(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
					Labels:            map[string]string{},
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    "ImproveCoverageTaint",
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		ExistsByProviderID: false,
		Err:                nil,
	}

	cloudNodeController := &CloudNodeController{
		kubeClient:   fnh,
		nodeInformer: factory.Core().V1().Nodes(),
		cloud:        fakeCloud,
	}

	cloudNodeController.updateNodeAddress(context.TODO(), fnh.Existing[0], fakeCloud)

	if len(fnh.UpdatedNodes) != 0 {
		t.Errorf("Node was not correctly updated, the updated len(nodes) got: %v, wanted=0", len(fnh.UpdatedNodes))
	}
}

// This test checks that a node is set with the correct providerID
func TestNodeProviderID(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
					Labels:            map[string]string{},
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    "ImproveCoverageTaint",
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Provider: "test",
		ExtID: map[types.NodeName]string{
			types.NodeName("node0"): "12345",
		},
		Err: nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:                fnh,
		nodeInformer:              factory.Core().V1().Nodes(),
		cloud:                     fakeCloud,
		nodeStatusUpdateFrequency: 1 * time.Second,
		recorder:                  eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	assert.Equal(t, "test://12345", fnh.UpdatedNodes[0].Spec.ProviderID, "Node ProviderID not set correctly")
}

// This test checks that a node's provider ID will not be overwritten
func TestNodeProviderIDAlreadySet(t *testing.T) {
	fnh := &testutil.FakeNodeHandler{
		Existing: []*v1.Node{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:              "node0",
					CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
					Labels:            map[string]string{},
				},
				Status: v1.NodeStatus{
					Conditions: []v1.NodeCondition{
						{
							Type:               v1.NodeReady,
							Status:             v1.ConditionUnknown,
							LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
							LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
						},
					},
				},
				Spec: v1.NodeSpec{
					ProviderID: "test-provider-id",
					Taints: []v1.Taint{
						{
							Key:    "ImproveCoverageTaint",
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
						{
							Key:    schedulerapi.TaintExternalCloudProvider,
							Value:  "true",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
		},
		Clientset:      fake.NewSimpleClientset(&v1.PodList{}),
		DeleteWaitChan: make(chan struct{}),
	}

	factory := informers.NewSharedInformerFactory(fnh, 0)

	fakeCloud := &fakecloud.Cloud{
		InstanceTypes: map[types.NodeName]string{},
		Addresses: []v1.NodeAddress{
			{
				Type:    v1.NodeHostName,
				Address: "node0.cloud.internal",
			},
			{
				Type:    v1.NodeInternalIP,
				Address: "10.0.0.1",
			},
			{
				Type:    v1.NodeExternalIP,
				Address: "132.143.154.163",
			},
		},
		Provider: "test",
		ExtID: map[types.NodeName]string{
			types.NodeName("node0"): "12345",
		},
		Err: nil,
	}

	eventBroadcaster := record.NewBroadcaster()
	cloudNodeController := &CloudNodeController{
		kubeClient:                fnh,
		nodeInformer:              factory.Core().V1().Nodes(),
		cloud:                     fakeCloud,
		nodeStatusUpdateFrequency: 1 * time.Second,
		recorder:                  eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}),
	}
	eventBroadcaster.StartLogging(klog.Infof)

	cloudNodeController.AddCloudNode(context.TODO(), fnh.Existing[0])

	assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
	assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
	// CCM node controller should not overwrite provider if it's already set
	assert.Equal(t, "test-provider-id", fnh.UpdatedNodes[0].Spec.ProviderID, "Node ProviderID not set correctly")
}


text:
Index of /repositories/wso2-public/org/antlr/antlr-runtime
3.0.1/ Wed Oct 30 10:54:40 IST 2013
3.0/ Wed Jul 22 13:10:09 IST 2015
3.1.1/ Sun Jul 08 03:11:37 IST 2012
3.1.2/ Sun Dec 09 23:51:44 IST 2018
3.1.3/ Sun May 12 04:41:10 IST 2013
3.1/ Thu Mar 16 09:26:06 IST 2017
3.2/ Wed Jan 28 19:42:04 IST 2015
3.3/ Mon Mar 04 15:17:02 IST 2013
3.4.1-preview-jbossorg-0/ Mon Apr 29 23:43:06 IST 2013
3.4/ Wed Oct 08 13:24:53 IST 2014
3.5.1/ Wed Sep 11 15:48:12 IST 2019
3.5.2/ Wed Feb 11 13:57:03 IST 2015
3.5/ Tue Apr 21 12:11:25 IST 2015
maven-metadata.xml Tue Mar 25 17:46:22 IST 2014 850

redpajama_set_name: RedPajamaCommonCrawl


text:
Tar Baby: Chapter 3
On a foggy day on the island, Valerian, Margaret, and Jadine are eating dinner together, waited on by Sydney. Margaret feels awkward, and Valerian needles her by correcting her pronunciation of a foreign word. Margaret ignores him and continues to talk to Jadine but when she makes a mistake in her table manners (something she fears), Valerian shouts a rebuke at her. They all quickly pretend that nothing has happened and Margaret resumes her talk with Jadine, who is speaking about an invitation the Streets have received from the Brandts to spend Christmas with them. Valerian dismisses the invitation, and Margaret informs Jadine that Michael is coming for Christmas. Valerian continues to snipe at her, saying that Michael will not come. Margaret protests, and they continue to bicker and taunt each other, while Jadine can think of nothing to say that would deflect the conversation. Jadine has been staying with them for two months, and she is starting to notice "flecks of menace" (p. 68) in their quarrels. The argument turns to Margaret's belief that Valerian's sister Cissy has hated her from the beginning. She explains how Cissy had asked her when they first met, thirty years ago, to remove the crucifix she wore around her neck, saying that "only whores wore crosses" (p. 70). Valerian laughs, thinking the remark funny. The quarrel gets more intense, and Margaret leaves the table. Valerian apologizes to Jadine, who comments about how she likes Michael. She cannot think of much to say, and struggles to find a way to leave the table. But they end up discussing Michael. Jadine remembers meeting him during her first year in college, and he reproached her for what he called abandoning her history and her people. Valerian speaks disparagingly of his son's commitment to progressive social causes, while Jadine tries to be a little easier on him. She goes on to explain that she does not regret favoring Western culture over her black heritage. She was never convinced by Michael's arguments that the social and economic system as it concerned blacks was broken and the only solution was a return to handicrafts such as pottery and a new system of barter.
Valerian then laments that Margaret brought Michael up in the wrong way and made a loser out of "the most beautiful, the brightest boy in the land" (p. 75). He had wanted Michael to make more of his life than he has. He insists that he loves his son, although Margaret refuses to recognize this. He also explains to Jadine his belief that Margaret was not ready for Michael when the boy was young, and now she wants to take care of him, but it is too late. He tells of how he used to come home when Michael was two and find him singing in a cabinet under the sink. This happened more than once; Valerian complains that Margaret was not consistent in the way she treated her baby; sometimes she was interested in him and would interact with him and sometimes not. He hoped that when Michael went to college he would escape from his dependence on her, and acknowledges that since Michael rarely calls or writes, this has indeed happened. But now Valerian fears that Margaret wants to get control of her son again. Then when he is dependent on her, she will change her mind and leave him.
Jadine is bored listening to Valerian. But their conversation is interrupted by Margaret who re-enters the room screaming. She talks incoherently about something in her closet. Sydney is sent to investigate. When he returns, he is pointing his pistol at a black man with dreadlock hair. Margaret exclaims, "It's him!" But instead of calling the police, Valerian invites the man to have a drink.
There are two important points in this chapter, giving further insight into Margaret and Jadine. There is some strange mental instability about Margaret. It was glimpsed in the last chapter when it was explained that sometimes she would be forgetful in ways that she forgot the names and uses of things. Like suddenly not knowing whether a tube of lipstick is for licking or writing your name. There is some kind of glitch in her brain. At dinner with Valerian she is never sure when this confusion will return, which makes her nervous. Once she forgot to unwrap the Amaretti cookie at the side of her plate and put the whole thing in her mouth. Sometimes she would pick up a knife instead of a celery stalk. It is as if at certain moments she is not in full control of herself. The reader wonders at her psychological states, which seems brittle. Sometimes she thinks Ondine is trying to trick her in the way in which she prepares the food. Margaret is therefore clearly a little disturbed. This adds to the tension in the dialogue between her and Valerian. This fragile equilibrium, behind which lies so many years of unexamined issues between them, seems sure to burst open at some point, with consequences that cannot be guessed at.
The other main point of interest in this chapter is what we learn about Jadine. She is extremely sensitive to the fact that she identifies more with white culture than black. Margaret makes her uncomfortable because she seems to have fixed ideas about racial characteristics that Jadine does not share. And years ago, Michael would make Jadine feel guilty about her preferences, the fact that she preferred "Ave Maria" to gospel music. In the present, she defends her views to Valerian, saying that "Picasso is better than an Itumba mask. The fact that he was intrigued by them is proof of his genius, not the mask-makers'" (p. 74). She despises the black artists whose work she has seen in Europe, believing them to be pretentious.
Jadine, a black American woman who has become a Euro-centered lover and beneficiary of white culture, will soon face a direct challenge to the lifestyle she has chosen, in the form of the black intruder into the Street household.
A Man For All Seasons: Act 1, Scene Seven
A Man For All Seasons: Act 1, Scene Four
Tar Baby: Essay Q&A
Tar Baby: Prologue
Tar Baby: Biography
Tar Baby: Theme Analysis
Tar Baby: Top Ten Quotes
Tar Baby: Metaphor Analysis
Tar Baby: Character Profiles
Tar Baby: Chapter 10


text:
Q: react native for ios seems to include a library from a previous project So I am trying my first few tutorials with react native and therefore am still quite unfamiliar. I had followed this tutorial for using an npm camera in an IOS app. The camera worked find but I had to go an link this library for the camera. I tried it both the manual approach and rnpm. However, now I have a different tutorial on the go which I was messing around with prior to the camera one, and the simulator throws this error.
undefined is not an object (evaluating 'CameraManager.Aspect'), and further down there is also an error about a file which I know was only in my other tutorial(because I wrote it).
So this seems to me like xCode or the node modules for react are somehow still holding this code. I had previously added an entry to the header search paths under the projects build settings, but I looked at it and this path I needed for the camera is not there. So I don't know where this is coming in from.
I ran react-native run-ios on my project, and I tried cleaning the product in xcode and running from there. So far I haven't had very much luck figuring this out.

A: Ok so this was a simple human error on my behalf. I will post an answer to it anyhow as it might help some react-native beginners. So I had recently made the switch from linux to OSX, and when I started on there linux I had always run the packager for react native manually, and then I found out on OSX I can just run react-native run-ios in the root of the project and it starts another terminal window with the packager running.
The react-native packager was causing the issue. When I ran the react-native run-ios command the following day(didn't turn off my computer) the packager in the other window was forgotten about and I thought it be smart enough to kill that process and restart a new packager for the other project, but it didn't. Hopefully if anyone makes the same assumption you can save some time with this answer.

redpajama_set_name: RedPajamaStackExchange


text:
Mistrzostwa Świata w Szermierce 1951 – 21. edycja mistrzostw odbyła się w szwedzkiej stolicy Sztokholm.

Klasyfikacja medalowa

Medaliści

Mężczyźni

Kobiety

Mistrzostwa świata w szermierce
1951 w sporcie

redpajama_set_name: RedPajamaWikipedia


text:
Skip to main content Politics Fact Checker Biden administration The 202s Polling Redistricting tracker Debt ceiling
IRS targeted groups critical of government, documents from agency probe show
The exterior of the Internal Revenue Service building in Washington March 22, 2013. (Susan Walsh/AP)
Juliet Eilperin
Deputy editor overseeing climate and environmental coverage
At various points over the past two years, Internal Revenue Service officials singled out for scrutiny not only groups with "tea party" or "patriot" in their names but also nonprofit groups that criticized the government and sought to educate Americans about the U.S. Constitution, according to documents in an audit conducted by the agency's inspector general.
The documents, obtained by The Washington Post from a congressional aide with knowledge of the findings, show that the IRS field office in charge of evaluating applications for tax-exempt status decided to focus on groups making statements that "criticize how the country is being run" and those that were involved in educating Americans "on the Constitution and Bill of Rights."
The staffers in the Cincinnati field office were making high-level decisions on how to evaluate the groups because a decade ago the IRS assigned all applications to that unit. The IRS also eliminated an automatic after-the-fact review process Washington used to conduct such determinations.
Marcus Owens, who oversaw tax-exempt groups at the IRS between 1990 and 1999, said that delegation "carries with it a risk" because the Cincinnati office "isn't as plugged into what's [politically] sensitive as Washington."
Owens, now with the firm Caplin & Drysdale, said that before the agency's most recent reorganization, it had a series of "tripwires in place" that could catch unfair targeting, including the fact that the IRS identified its criteria for special scrutiny in a public manual.
A report due this week says the IRS targeted groups with names containing "tea party" and "patriot."
"There's no longer that safety valve, and as a result, the IRS has been rolling the dice ever since," said Owens, who worked at the agency for nearly a quarter-century and now represents some organizations seeking tax-exempt status.
The IRS came under withering attack from GOP lawmakers Sunday. Sen. Susan Collins of Maine, a moderate Republican, described the practice as "absolutely chilling" and called on President Obama to condemn the effort.
"This is truly outrageous," she said on CNN's "State of the Union," adding that even though White House spokesman Jay Carney has said the matter deserves an investigation, "the president needs to make crystal clear that this is totally unacceptable in America."
In March 2012, then-IRS Commissioner Douglas H. Shulman, who was appointed by President George W. Bush, told Congress that the agency was not targeting conservative groups. On Sunday, the agency declined to answer questions about whether senior officials asked IRS exempt organizations division chief Lois G. Lerner and her staff in Cincinnati about this heightened scrutiny before testifying it did not take place.
"There has to be accountability for the people who did it," House Oversight and Government Reform Committee Chairman Darrell Issa (R-Calif.) said on NBC's "Meet the Press," adding: "And, quite frankly, up until a few days ago, there's got to be accountability for people who were telling lies about it being done."
The appendix of the inspector general's report — which was requested by the House Oversight and Government Reform Committee and has yet to be publicly released — chronicles the extent to which the IRS's exempt organizations division kept redefining what sort of "social welfare" groups it should single out for extra attention since the 2010 Supreme Court ruling Citizens United v. Federal Election Commission. That decision allowed corporations and labor unions to raise and spend unlimited sums on elections as well as register for tax-exempt status under Section 501(c)(4) of the tax code, as long as their "primary purpose" was not targeting electoral candidates.
The number of political groups applying for tax-exempt status more than doubled in the wake of the Citizens United ruling, forcing agency officials to make a slew of determinations despite uncertainty about the category's ambiguous definition.
Of the 298 groups selected for special scrutiny, according to the congressional aide, 72 had "tea party" in their title, 13 had "patriot" and 11 had "9/12." Lerner, who apologized Friday for the targeting of such groups, described it as a misguided effort to deal with a flood of applications for tax-exempt status. She did not release the names of the groups.
On June 29, 2011, according to the documents, IRS staffers held a briefing with Lerner in which they described giving special attention to instances where "statements in the case file criticize how the country is being run." She raised an objection, and the agency adopted a more general set of standards. Lerner, who is a Democrat, is not a political appointee.
But six months later, the IRS applied a new political test to social welfare groups, the document says. On Jan. 15, 2012, the agency decided to look at "political action type organizations involved in limiting/expanding Government, educating on the Constitution and Bill of Rights, social economic reform movement," according to the appendix in the IG's report.
The agency did not appear to adopt a more neutral test for 501(c)(4) groups until May 17, 2012, according to the timeline in the report. At that point, the IRS again updated its criteria to focus on "organizations with indicators of significant amounts of political campaign intervention (raising questions as to exempt purpose and/or excess private benefit.)"
Campaign reform groups have been pressing the IRS for several years to conduct greater oversight of nonprofits formed in the wake of the Citizens United case, given that many have become heavily involved in elections. "But this isn't the type of enforcement we want," said Paul Ryan, a senior counsel at the Campaign Legal Center. "We want nonpartisan, non-biased enforcement."
Loyola Law School professor Ellen Aprill, who specializes in tax law, said any groups that have applied for tax-exempt status has "opened themselves up to scrutiny" by the IRS. "It's part of their job to look for organizations that may be more likely to have too much campaign intervention," she said. "But it is important to try to make these criteria as politically neutral as possible."
Aprill said one of the problems is the agency's top officials have not provided clear enough guidelines on what constitutes too much political activity for a social welfare group because it's been "a hot potato," and that now with this new controversy, "it's going to make it even more difficult to do so."
Toby Marie Walker, president of the Waco Tea Party, said the IRS subjected her group to a series of unreasonable requests after it applied for tax-exempt status in June 2010. The requests came in early 2012, Walker said, after being initially informed by an official in the Cincinnati field office that he was "sitting on a stack of tea party applications and they were awaiting word from higher-ups as to how to process them."
The agency asked the group's treasurer to supply information on its "close relationship" with current candidates and elected officials as well as future candidates, along with detailed information about its contributors and members. It also asked for transcripts of any radio interviews its officials had done and hard copies of any news articles mentioning them.
"That would take me years to do," Walker said, noting that in some cases, Chinese media outlets referred to her organization. "Am I responsible for every news article across the globe?"
The group had even more difficulty providing transcripts and details of speakers at its events, since they hosted informal gatherings such as "rant contests" where anyone could come and express their views.
While the IRS awarded the Waco Tea Party tax-exempt status about six weeks ago, Walker said the group was now considering suing the agency since the process not only consumed time and effort but prompted the group to scale back its 2012 get-out-the-vote operation. "We were afraid to do it and get in trouble," she said.
Sal Russo, chief strategist for the Tea Party Express, said that even though the agency's actions intimidated tea party adherents, he gives the IRS "credit for standing up and admitting" it targeted them. And while only two of the agency's officials — the commissioner and the chief counsel — are political appointees, Russo said the administration needs to conduct better oversight.
"The culture is set at the top," Russo said. "Obviously you can't control what every employee does. But you have to set a standard, particularly with the IRS, to be squeaky clean."
Josh Hicks and Julie Tate contributed to this report.
Discuss this topic and other political issues in the politics discussion forums.
Juliet Eilperin Juliet Eilperin is a Pulitzer Prize-winning journalist at The Washington Post, editing stories on climate and the environment. She has written two books, "Demon Fish: Travels Through the Hidden World of Sharks" and "Fight Club Politics: How Partisanship is Poisoning the House of Representatives." Follow


text:
Q: how to profile a page request for a spring mvc app what options do I have to profile a page request in a spring mvc app?
I want to get a breakdown of how long the page request takes, along with the various stages like how long it takes to render the freemarker template, hibernate db calls, etc.

A: We just accomplished something similar with an interceptor and a custom tag.  This solution is "light" enough to be used in production, presents its data as HTML comments at the bottom of the response, and allows you to opt into the more verbose logging with a request parameter.  You apply the interceptor below to all request paths you want to profile, and you add the custom tag to the bottom of the desired pages.  The placement of the custom tag is important; it should be invoked as close to the end of request processing as possible, as it's only aware of time spent (and objects loaded) prior to its invocation.
package com.foo.web.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class PageGenerationTimeInterceptor extends HandlerInterceptorAdapter {

    public static final String PAGE_START_TIME = "page_start_time";
    public static final String PAGE_GENERATION_TIME = "page_generation_time";

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object handler) throws Exception {
        request.setAttribute(PAGE_START_TIME, new Long(System.currentTimeMillis()));
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response,
            Object handler, ModelAndView modelAndView) throws Exception {
        Long startTime = (Long) request.getAttribute(PAGE_START_TIME);
        if (startTime != null) {
            request.setAttribute(PAGE_GENERATION_TIME, new Long(System.currentTimeMillis() - startTime.longValue()));
        }
    }
}

The custom tag looks for the request attributes, and uses them to compute the handler time, the view time, and the total time.  It can also query the current Hibernate session for first-level cache statistics, which can shed some light on how many objects were loaded by the handler and view.  If you don't need the Hibernate information, you can delete the big if block.
package com.foo.web.taglib;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TryCatchFinally;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.engine.CollectionKey;
import org.hibernate.engine.EntityKey;
import org.hibernate.stat.SessionStatistics;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.tags.RequestContextAwareTag;

import com.foo.web.interceptor.PageGenerationTimeInterceptor;

public class PageInfoTag extends RequestContextAwareTag implements TryCatchFinally {
    private static final long serialVersionUID = -8448960221093136401L;
    private static final Logger LOGGER = LogManager.getLogger(PageInfoTag.class);
    public static final String SESSION_STATS_PARAM_NAME = "PageInfoTag.SessionStats";

    @Override
    public int doStartTagInternal() throws JspException {
        try {
            JspWriter out = pageContext.getOut();
            Long startTime = (Long)pageContext.getRequest().getAttribute(PageGenerationTimeInterceptor.PAGE_START_TIME);
            Long handlerTime = (Long)pageContext.getRequest().getAttribute(PageGenerationTimeInterceptor.PAGE_GENERATION_TIME);
            if (startTime != null && handlerTime != null) {
                long responseTime = System.currentTimeMillis() - startTime.longValue();
                long viewTime = responseTime - handlerTime;
                out.append(String.format("<!-- total: %dms, handler: %dms, view: %dms -->", responseTime, handlerTime, viewTime));
            }
            if (ServletRequestUtils.getBooleanParameter(pageContext.getRequest(), SESSION_STATS_PARAM_NAME, false)) {
                //write another long HTML comment with information about contents of Hibernate first-level cache
                ServletContext servletContext = pageContext.getServletContext();
                ApplicationContext context =  WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
                String[] beans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
                        SessionFactory.class, false, false);

                if (beans.length > 0) {
                    SessionFactory sessionFactory = (SessionFactory) context.getBean(beans[0]);
                    Session session = sessionFactory.getCurrentSession();
                    SessionStatistics stats = session.getStatistics();
                    Map<String, NamedCount> entityHistogram = new HashMap<String, NamedCount>();
                    out.append("\n<!-- session statistics:\n");
                    out.append("\tObject keys (").append(String.valueOf(stats.getEntityCount())).append("):\n");
                    for (Object obj: stats.getEntityKeys()) {
                        EntityKey key = (EntityKey)obj;
                        out.append("\t\t").append(key.getEntityName()).append("#").append(key.getIdentifier().toString()).append("\n");
                        increment(entityHistogram, key.getEntityName());
                    }
                    out.append("\tObject key histogram:\n");
                    SortedSet<NamedCount> orderedEntityHistogram = new TreeSet<NamedCount>(entityHistogram.values());
                    for (NamedCount entry: orderedEntityHistogram) {
                        out.append("\t\t").append(entry.name).append(": ").append(String.valueOf(entry.count)).append("\n");
                    }
                    Map<String, NamedCount> collectionHistogram = new HashMap<String, NamedCount>();
                    out.append("\tCollection keys (").append(String.valueOf(stats.getCollectionCount())).append("):\n");
                    for (Object obj: stats.getCollectionKeys()) {
                        CollectionKey key = (CollectionKey)obj;
                        out.append("\t\t").append(key.getRole()).append("#").append(key.getKey().toString()).append("\n");
                        increment(collectionHistogram, key.getRole());
                    }
                    out.append("\tCollection key histogram:\n");
                    SortedSet<NamedCount> orderedCollectionHistogram = new TreeSet<NamedCount>(collectionHistogram.values());
                    for (NamedCount entry: orderedCollectionHistogram) {
                        out.append("\t\t").append(entry.name).append(": ").append(String.valueOf(entry.count)).append("\n");
                    }
                    out.append("-->");
                }
            }
        } catch (IOException e) {
            LOGGER.error("Unable to write page info tag");
            throw new RuntimeException(e);
        }
        return Tag.EVAL_BODY_INCLUDE;
    }

    protected void increment(Map<String, NamedCount> histogram, String key) {
        NamedCount count = histogram.get(key);
        if (count == null) {
            count = new NamedCount(key);
            histogram.put(key, count);
        }
        count.count++;
    }

    class NamedCount implements Comparable<NamedCount>  {
        public String name;
        public int count;

        public NamedCount(String name) {
            this.name = name;
            count = 0;
        }

        @Override
        public int compareTo(NamedCount other) {
            //descending count, ascending name
            int compared = other.count - this.count;
            if (compared == 0) {
                compared = this.name.compareTo(other.name);
            }
            return compared;
        }
    }
}

A: Take a look here:
Profiling with Eclipse and remote profile agents on Linux
Tutorial: Profiling with TPTP and Tomcat
An introduction to profiling Java applications using TPTP
TPTP = Eclipse Test and Performance Tools Platform
More links to the stack:
Open Source Profilers in Java


text:
Home Blog Cities: Digitize curb assets today
Cities: Digitize curb assets today
CURBED DEMANDS: The humble curb is fast becoming the city's hottest asset, by Karen Hao, 26 Jan 2018, Quartz Curbed
Could this be the key to solving urban congestion? (Rikki Chan/Unsplash)
Karen Hao
In the city of the future, the ability to get people from point A to point B will be as much about the vehicle as it will be about the curb. Most experts estimate that an average of 30% of the traffic in busy urban areas can be accounted for by vehicles searching for places along the curb to pull over. Without a proper place for our future driverless vehicles to drop off passengers, they won't be able to reduce congestion.
Rather than physically expand curb space, however, a city only needs to create a more sophisticated management system, one that would allow passenger cars to use a curb during the day, for instance, and delivery trucks to use it overnight. This is easier said than done given that cities traditionally manage curb access with physical paper.
Julia Thayne, the director of urban development at Germany's Siemens, proposes an easy fix for cities to get started: by digitally mapping out all of their curbs, including everything from parking signs to fire hydrants to bike lanes. "This is not big dollars, but it has big benefits," she says.
Once a city knows the exact location of every curb, it can evaluate its current space allocation against curbside users' demands. Do cars spend a long time circling the block to find parking? How often are delivery trucks stopping in the middle of a road because there is no loading dock? Armed with that data, the city can more effectively reallocate the curb and implement dynamic management schemes.
DC: A Case Study
Only a few cities have begun to digitally map their curbs, and among them, Washington DC is one of the most effective. Instead of attempting to inventory every curb at once, it began with its commercial loading zones to better manage delivery trucks and tackle one of the central causes of congestion.
Prior to digitization, the district had a mismatch in loading zone supply and demand that caused delivery trucks to double-park in car spots or stop to unload in the middle of the street. It was costing the city an estimated $650 million annually, according to the District Department of Transportation, and the problem was likely to get worse. DDOT projected that truck volumes would grow 70% from 2011 to 2040. But the city didn't know where to place new loading zones.
In January 2015 the district inventoried all 600 of its commercial loading zones, digitally mapping them with their corresponding dimensions, signage, and time restrictions, as well as the corresponding number of businesses and business types they served. Using an existing cellphone payment system that charged commercial vehicles, the city also collected loading zone occupancy data, including truck type, number of deliveries, and average length of stay.
The resulting database helped determine where to place additional loading zones and enabled the city to implement demand-based pricingfor their use. In March 2015, DDOT began charging higher prices for specific loading zones during peak hours. The scheme incentivized trucks to deliver overnight, which in turn helped alleviate daytime congestion in busy commercial districts and keep curbsides available to other users. By visualizing the occupancy of loading zones on a public website, the city also allowed inbound truck drivers to save time searching for a place to pull over.
Imagine applying the same digitization process for loading zones to all other curb assets, says Siemens' Thayne. This would allow cities to dynamically price every vehicle as well as collect data on how often and where each of them uses the curb. Vehicles would know exactly which curb spaces were available—perhaps because that information would be integrated directly into Waze or Google Maps. As a result, the vehicles wouldn't spend time circling the block, leading to less congestion, better air quality, and even less noise pollution.
Vehicle passengers would likely also get closer to their destination. The madness of the street today often causes an Uber, for example, to drop its passengers off a block from their actual destination. That wouldn't have to be the case in the future, which would particularly benefit those with a physical disability, says Thayne. "All of a sudden you'd be able to get better matched with an area where actually there's a ramp up to the sidewalk, where there's the elevator access instead of the stairs access."
And none of these benefits require on any new physical infrastructure. "This is just taking what's already there and digitizing it," Thayne says.
The role of private companies
While DC built its digital inventory using the city's in-house engineering talent, Thayne believes private companies can play a role.
Alphabet's smart cities division Sidewalk Labs envisions creating a tool that combines data from existing platforms such as Google Street View with advances in computer vision and machine learning to increase the speed and lower the cost of digitally mapping curbs.
Sidewalk plans to test this vision through its project to redevelop Toronto's waterfront, reports The Globe and Mail. It is currently developing an app under its initiative called Flow that "will enable [parking] pricing to vary in real time based on transit availability." Sidewalk did not respond to Quartz for comment.
Thayne doesn't think cities should wait to move ahead. Digitizing curbs is "something that has benefit today, benefit in the future, and doesn't require so much investment from cities that they can't do it today."


BRENDAN RODGERS could bring Fernando Torres BACK to Liverpool.
Could Fernando Torres be heading back to Liverpool?
According to the Daily Star, the former Liverpool striker could be in line for a sensation move back to Anfield.
Torres is currently on loan at AC Milan following but the Serie A giants want to cancel his contract after scoring just one goal in 10 appearances for the Italian giants.
Considering Jose Mourinho already has Diego Costa, Loic Remy and Didier Drogba in his high-flying Blues' squad, there isn't much room for Torres.
The Chelsea boss is reluctant to allow the Spaniard to return to Stamford Bridge therefore throwing his future into doubt.
According to reports, Chelsea could move Torres on for free if Milan were to cancel his contract and Rodgers could take advantage of Torres' unclear future and bring him back to Anfield.


text:
Q: nested requests in asp.net mvc Is it possible to call a function inside an action method that will eventually generate a new (aka nested) request to the same server?
This comes up because I am trying to use the evohtmltopdf pdf converter to combine several pdfs into one. The problem: The individual pdfs are also generated by the same server.
The snippet from my action method below creates an error message indicating that the converter can't fetch the /Attachment/Pdf doc while still handling the current request.
    // create pdfDocument with main content retrieved from RenderViewToString output
    // [...]
    // Now add appendixes by handing converter urls and letting it fetch the docs.
    UrlHelper url = new UrlHelper(HttpContext.Request.RequestContext);
    HtmlToPdfElement attachment = new HtmlToPdfElement(0, 500, url.Action("Pdf", "Attachment");
    pdfDocument.Pages[summary.LastPageIndex].AddElement(attachment);

Is this really not possible and if so, how do I get around the restriction?
Duffy

A: Turns out the problem was somewhere else and the snippet above did work in the end.


text:
Catalog > Photo & Video > Portrait > Posing 101: Essentials > Posing For Body Types
Posing 101: Essentials
Posing for Body Types
We are going to talk about body types. And I will tell you, this doesn't mean don't watch this section, but if you just take all of these concepts I already had, and apply it to any person, it all still works. If there's a bigger part, push it away. If there's a smaller part, bring it forward. All those concepts still work, but I'm gonna kinda spell it out and I have found, often, my portrait clients will let me know, right away, their problem areas or what they're concerned with. They will tell me if they think their hips are too wide or their butt's too big. Or they will tell me if they don't like their flabby arms. They kinda, they talk about it, okay? They bring attention to it and they might not say it directly but, for example, I know when I get my picture taken, I tell people right away. I'm like, this is what to watch out for. So anyway, what I'm going to do is I am going to address some body types and I am going to talk a little bit about clothing. And I don't have specific ex...
amples besides just describing it to you guys, so if there is any confusion, please let me know, but things that help you. Alright, so let's start off here with my overall tips, flattering any body type. Alright so these are the top kinda four tips just to keep in mind for any body types. The very first one is emphasize the assets and reduce the flaws and this is where I tell you that it all depends on the person. For example, one of the types of body types we'll talk about is the inverted triangle. What that means, I gotta show this one, what that means is the person's really big up top and really small down here. It could mean that they have broad shoulders or a very large chest and they're very small. Now, by the standards that I would tell you, you know you're trying to even things out and add some curve, maybe you would reduce the appearance of the chest. Unless someone loves the size of their chest and wants to showcase that, and then you let them do that. You know what I mean? So some of the things I'm going to say would be try to attain more traditional forms of what we would say is good posing, but if somebody walks in and they say their best asset is their chest and they're really small, you don't wanna make it look really small. So just kind of keep these into mind. Let me get my overview. Emphasize the assets, reduce the flaws. That is based on, you usually can tell, by how somebody feels, having a conversation with them. We already talked about this, but these are for people that didn't see before. Closer to camera is larger, further from the camera is smaller. Use both posing and camera angles to achieve it. Flattering body types is a combination of posing and your camera angles. We'll talk about those. Number four is using clothing to complement. Very first and foremost, for reporter session, loose clothing is never good, ever. Because as you're trying to pose, loose clothing hides your posing. It's working directly against you. Because if you're trying to show negative space and they have a big loose flowy sleeve, there's no negative space. Or if they have big flowy clothing. So I find that a lot of heavier women in particular will wear clothes that are bigger 'cause they're trying to hide their form. They're basically just trying to hide behind their clothing. When you try to make them look more slender, the clothing makes them look like a blob and it's so hard to work with. Something that you might actually wanna do and something I always do is I keep the little clamps. The A clamps, I'll keep them in my bag, and if the clothing is not fitting properly, I will clamp it. So that I can see the form and that gives me something to pose with. I think one of the biggest, one of the biggest flaws that people have is not in how they look, it's in how they dress, how they represent their body types. My recommendation is, if you can, if you really want good images, and you wanna take it up a notch, don't leave clothing up to chance. Don't just say, bring whatever you want. Because what also what looks good on the street or what's in style right now does not mean it photographs well. It can be very quickly dated. In general, darker clothing and solid is better. Not always, but in general, darker solids are going to be better. Things that are more traditional cuts are better unless you are going for a cool, funky, fashion shoot, and then totally do that. I'm not saying being boring and I don't mean that everyone needs to match perfectly, but just keep that in mind. I would have a discussion. That's something that I always said, and I also would send a link, so I'm saying in the past tense. I have a wardrobe stylist now. The wardrobe stylist make sure the person, what she actually does, it's pretty cool. To any of my clients, they send out a piece of paper that is, it's called a style guide and the style sheet. The client has to fill out their body measurement. They actually have to measure their body. Not, "I think I wear a size eight," 'cause a lot of times the girl wears a size that actually says six or the other way. She has to actually fill that out, talk about body type, everything, and so when my stylist picks up the clothes, it fits. And it fits that body type. But what I used to do, as I used to direct people to a website to help them determine what body type they were, and actually pay attention to the type of clothing that is more flattering and encourage them to dress and wear those clothing. So we're going to talk about that a little bit. These are the main body types that we have. Inverted triangle means broad shoulders or large chest and small bottom. Again, this could be somebody, it doesn't have anything to do with size, like it could be someone who is larger but they're just extremely larger top and very small in the bottom. It's just kind of proportions. The column and the rectangle are just somebody who just doesn't particularly have shapes. They're just straight lines. I would say that Jen's kind of in that direction. She has a bit more curve than that, but she's pretty straight up and down. The apple would be full around top and full around bottom. It doesn't mean that the person is just round, which I always thought that that's saying. These aren't my names, these are like the traditional name. It means they're large top and bottom. Pear means large bottom. And then hourglass is like Beyonce. That's what I say. (everyone laughs) Everybody knows what she looks like. Let's talk about both posing and clothing and what you can do. The first part I'm going to talk about is clothing. You can honestly basically ignore all this. I will say it, but think, draw attention to opposite of what's big. That's what you do for clothing. Whatever is bigger, emphasize whatever is smaller. You're just kinda emphasize the opposite of it. For example, the person with the broad shoulders or large chest, we're gonna talk really about large chest, to be honest, in this example. What you don't wanna do is have a bright pink shirt with ruffles around the scoop neck. Because that is just saying, "Look here," and then everything else is smaller. What is usually better off is a solid colored shirt, darker, and then a flared skirt, because it evens out their proportions a little bit. They'll still look skinny, they'll still look proportioned, if that's what they were going for, because it'll taper and then flare back out. Most of what we're aiming here for posing, and this is saying, don't judge me, I'm just saying how posing usually is, it's more traditional forms of beauty, meaning we're usually going for the hourglass shape. That's what most of this posing is. Imagine, flared skirt gives you kind of that shape. Things you wanna avoid if somebody has, is larger at top, is to avoid spaghetti straps or really really low cut. 'Cause it's going to draw more attention, and that would be about it. That's what you wanna think of for clothing this person. What do I do opposite, draw attention here. So if we then think about posing the person and shooting the person, I want you guys to kind of think, if you don't mind, in your heads, what would you do. What would be kind of the opposite, so the whole, what's closer to the camera, that kind of thing. What I would do or some things to think about for posing, would be avoiding leaning too far forward towards the camera. If you're putting the weight back, you don't need to lean too far for it. My example, where I was leaning against the wall, the girl could lean kind of against the wall, or slightly forward instead of an intense lean. Because that's going to be a little different. But, if you don't mind, one of things that is beneficial is if I'm leaning against the wall, I don't wanna lean forward, but if I bring my knee up, kind of balanced it out. There's attention here and attention here. Some like, alright, what can I do to pose to even things out? Maybe for example, for somebody in this particular example, they're larger at top, I add motion, or pose on the bottom, right? So I'm balancing out, I'm giving more visual weight here. For someone like this, you don't want to pose with their hands up. Let's say you have a girl and she just have her posing straight like this and hands are up, all the action and movement is here. So might wanna have more in the hips or movement here as well to kinda balance out. All of this is up to interpretation for what you wanna do. If, for example, you are doing, a playboy shoot, like my friend Lou Freeman does, then you might just wanna do this, okay? (everyone laughing) Hey Lindsey, a quick question from the Internet. The Photog wanted to know, how does this stuff relate to guys and people who are sort of chiming in about children as well. For children, less so, for sure. For children, you're just fundamentally trying to get a decent pose and good expression. We'll talk about it, but body type doesn't really pay that much of a difference. The clothing could help. It all depends on how extreme and how important that is. Put it this way, it could apply, but I don't know if I would do clothing consultations specifically for a child, but if you wanted to pose or to shoot an entire family and advise them as a whole, what would work best for them, that's a good way to help out with that. For guys, it actually does apply, but it depends on how stylish a guy is, is if he's going to go out of his way to, for example, if he has really broad shoulders, to wear lighter colors in the bottom, darker color in the top to even it out. It also applies, just with women it's much more extreme. Hmm, great, thank you. Oh, and for the inverted triangle, you wanna shoot eye level. You don't wanna shoot too high up. That's something you might want to be careful of, especially if someone has a really large chest, you shoot to high up, that's all you see. Just about eye level, maybe a little lower. Okay, the pear. Somebody fuller on the bottom. Let's talk clothing. What do you do to go opposite? What would you for clothing? So what you would do is you would draw less attention here, more attention here. Which means, you'd probably wear darker, form fitting bottoms, and then maybe a brighter colored top or maybe a little bit lower cut to draw more attention. For pose, okay? (audience laughing) What about posing? Maybe hands up would be making sense in this situation, 'cause you've got a lot going down around down here, it'll draw a lot less attention if you have your hands up. Here's a couple things, let's take a look. For clothing the pear, brighter colors and details up top, basically. If we're gonna have detail on a shirt, maybe lace, even, 'cause your eyes are attracted to patterns and textures, so you would look there. Darker plainer color on the bottom, more form fitted. It's okay to have bare arms. In portraits for women, I usually stay away from too bare of arms 'cause most women don't really like their arm. I'm saying, older women don't really like their arms, so if they do have bare arms, I make sure they don't put weight on their arms and they're not closer to the camera. I don't know, I find a lot of people like a little bit of cap sleeve or just not a spaghetti strap. It doesn't usually work. If you're going for sexy, then go for a tube top and look sexy and try to go for it, but it's the in between that doesn't usually work. Pear, also avoid hands in pockets, the kind of hands in pocket shots make you look right here, 'cause that's where your eye is leading to. So you'd wanna avoid that. Let's go more to posing, again. We already talked about this, it made sense. Alright, you guys already know. Leaning chest forward, hips back, trying hands higher up on the body, and also considers shooting from a slightly higher angle. If the pose is not kicking hips back, then if you can get a little bit higher angle, that's actually gonna be better for that person. Okay, so next one. Column and rectangle, basically people that just have minimum shape, just straight up and down. What we wanna do is try to introduce shape. For clothing, introducing shape with clothing. Really, if you fake a waist, that's all you need. You need something just to cinch at the middle, have a dress with something like this works great, in the middle, a belt, something like that. You'll often see, like you've seen really skinny girls that have a little belt in the middle, 'cause they're just trying to give some kind of visual weight in the middle to make it look like they have shape. Then, when they kick a hip out to the side, and they have that cinch, now it looks like they have shape. For both of these people, shirts with belts or waist-defining elements. Patterns are okay with these people. I just don't, I don't usually like to photograph patterns in general, but non-solid is actually okay in this example. Then fabric, if you have fabric that can move or have shape, you might not have curve, but at least you can have a flowy dress shape. You'll see that with a lot of pre-teen girls, that have dresses and movement. That adds movement to the photo, 'cause you don't really wanna add shape to a pre-teen girls, but they add movements so it's more interesting. For posing, you're faking a curve. Here's a couple tips for this person. Alright, so in one instance, there's somebody that doesn't have shape, yeah, you can do the leg back, that helps, you can also just do hip off really, really far to one side. You can really emphasize that. But another one is we wanna fake the waist, so you can have a cinch. Instead of having somebody pose with their hands on their hips, you'd have them pose with their hands on their waist, 'cause you can fake a waist. Your hands become that cinch. My recommendation now, is if you look, if I have my hands here, you see this? It actually makes me look wider, 'cause it looked like I'm struggling to wrap around myself. If I rotate my hands forward a little, it makes it look like, wow, she wraps her hands all the way around her waist, she's so skinny. I would do something like that. Kinda lean back, and you're faking a waist. I'm gonna use this technique for another body type as well. If you're trying to work some curve with someone who doesn't have one, that's a really good one. Also consider uneven hands. So if I want a girl with no shape to have shape, let's say that I have this arm up, and now I kick this up, put this arm on the hip, now it's kinda looking like, ooh, this arm's higher, there's more hip here, and this is lower, there's more curve, you're faking it by where you're putting your hands. Just couple of tips for those people. Okay. The apple. Large on top, large on the bottom. For clothing. These people tend to wear loose clothing when they absolutely should not. Definitely should wear form fitting clothing so that is a big one. Also, they'll have, they will have a waist, but the more waist you can introduce, the more curvy they'll look, so if it can be cinched, or if it's kinda gathered in the middle like this in the clothing, that will help, but also avoid high necklines, like a really high neckline, 'cause what happens is if you have a high neckline, it makes everything looks rounder. First is if you have a lower neckline, it kinda breaks up that shape, so it's not just round, it's broken up. If you can do that, that helps. Also feel free for all this information, you can send it to your client and just say whatever body type you feel you are, here's some tips. People that have actual studios that are geared towards clothing, they'll have a wide range of clothing available that they'll pull from. I know in my, when I had my portraits studio, I had every size regular black shirt available for men and women. I got them for like, I don't know, probably Walmart, but if someone showed up with a loud, awful colored shirt with words on it, then I could switch them out, and it'll be much more flattering. Or for woman which is wearing really flowy clothing and she shouldn't be, I could grab that. Just a plain black flattering shirt. It usually worked out pretty well. For posing, so a couple things for the apple. This is another example where you'd try to put the hands on the waist if you can, it can make the person look a little narrower than they actually are by faking with the hands in the front. Somebody that I've seen, if anybody wants to watch, I know that Sue Bryce has done a couple tutorials where she talks about posing curvy girls, and that's something that you'll see her do all the time. It's kind of faking that as well. So yeah, definitely check hers out. I think it was, I actually think she's done a couple times. Notice, I said, turn knee in to introduce curve. Did you see how I did that? I kept doing that? The reason I'm saying turn the knee in is because there might be large and large, and this at least gives another elements to curve this way versus just curved out. It's kind of curved to the side. One other thing you might consider is if you are sitting the person on a chaise, when they're straight up and down, that's what gives you round look, and you wanna try to break that up and give it more curve. Let's say that there's a chaise couch. You can have them lean. It's taking things off center, so you're not looking at circular body type. Instead, you're looking at the line of their body, even if it's not a slender line, it's still a line. We have a couch over there and that would be something that I might do for an apple body type to have them lean out on one arm of the couch and extend the leg, and then your eye would follow that curve, even if it's not following this curve. For hourglass, wear fitted clothing. Kind of the, kind of the easy one. Wear fitted clothing. I still don't really like patterns, but they can get away with them. Distribute the weight, don't stand even on flat foot, and curve like that, this is, that's the easy body type that already kind of looks like what you wanted to look like. Alright, so let's talk about photographing and shooting flaws, and I would love questions on this. Any, 'cause this is the thing I'd love to just answer people's questions. I would have had to do a, literally had to do a lot of casting if we brought in every flaw, but I'm happy to answer these. I'm gonna talk about a couple key ones. Did you have a question off the bat? (mumbles) when you were just like showing it on just to define waist for apple body and all those kind of type, I love to shoot curvy women. The problem that I face when soothing, when they're just like, they try to grab themselves here, it doesn't really work, because larger chest, everything is going further, when you're just trying to bring in, they just feel more awkward, and it's kind of just, you have to kind of position their half of their body. I try to point their thumbs out, or how to do that? So yeah, no totally. That's completely true. This, if anyone try this at home, this doesn't feel normal. Especially if you're wider, it looks like you're just putting your hands on your stomach which makes it, like it feels like maybe putting your hands on your stomach. What I do is I usually do like these kind of hands, put in on the side, and then just kind of shift it in, and I try to pop out the hip. That's really what do. I go, no, trust me, it looks great. Oh, I love that. That's usually what I try to do, does it work? Another thing is after they does a pose process, I had a problem with cropping it. How do you crop? Because I had a model that just like, her thumbs, you can see that there is more of her there but the thumb is in the middle of her, it felt kind of awkward, it looked good from my perspective, it gave her all like a beautiful shape, but how to crop it? It depends on, okay, so you can, in that case, if you need to crop in as well, you can crop into the elbows, just don't crop the tips of it. I would maybe even crop like a little tighter than you normally would in that case, because then you can't quite see everything, buy you can see the hands. I'd crop tighter than you might be doing instinctually. I will say, for somebody that's really plus size, it won't work, 'cause it would be, they hands would be here. Yeah, that was just like, I was stretching that point. If they're really plus size and it doesn't work, it's like in between. Thank you so much. Absolutely. Let's start with, let's start with Luna Star who wants to know about pregnant women with smaller chests. So it's kind of an extreme of the pear shape, basically. That's okay, 'cause they're pregnant, in maternity, so you don't need to crack the, for any way. It doesn't particularly, no matter what you're doing, they're still going to have their stomach pronounced, so if you want to and need to, lean them forward a bit. It's still going to be there, so my suggestion would be, if you want them to look a little heavier up top or a little fuller up top, turn to the side, because now you see their stomach, and do the lean, the stomach isn't going away, and then you can shoot from a little bit higher angle and that's going, it's all those things we're talking about. A little bit higher angle makes the chest look closer. To the side, make sure you can still see their belly. And I'm assuming that you want to show that they're pregnant, that was my assumption. Yeah, just the normal stuff. Cool, and from Eichsheissen Image, how about the men with the beer bellies? Because right, they have, they're really thin up top, and their legs are really thin, but they have that basketball. I have people in mind. And I have photographs, that's for sure. Some of that's clothing, for sure. I find that if you can have a suit jacket or something over, so that their combination full up top and the jacket will kind of cover that. So it's less of a problem. There's not too much you can do for posing, really. I would have them lean their shoulders a little bit more, and if they had a pocket, put it a little bit more aggressively towards the camera, it will hide a little bit. None of the hips talking, that's girls. Guys are a little bit of a lean. Maybe a little bit of the head away. The furious ones. (audience laughing) I like it. We have Lupo Photo. How about what's proper angle to shoot from for someone with a larger nose? That's coming up. Perfect. Just do it. Okay, so I'll give you more about bodily flaws than facial ones. At this one, I wouldn't know. I'm not saying that there's one particular form of beauty. I just have to make this comment. 'Cause I'm super snotty. I'm just gonna say it. Everyone I hope still love me. I photograph really, really, really tall, incredibly skinny women, and like, I don't think that that's the standard of beauty. A lot of them are aliens and it's awesome 'cause I get to photograph surreally tall, skinny women. But not by any means do I think everyone should look like that. If you notice, we're actually trying to get everyone curved and those women have no curves. When we say flaws, we're helping people look like what they want to look like, and so if they don't wanna look like that, no problem. But this is traditionally what people are aiming for. Perfect. And actually, perfectly right along those lines. Purple Thistle Images says so shoot from below for a short girl, but what do you do for a very tall girl? I am six foot two, and die in pictures because I always look like an Amazon. Exactly like you said. Rocket, six foot two is awesome. That's so cool. Well it's fun, this is side note, but I photograph professional women's athlete, and some of them are six foot three, and then we photograph them. It is actually better to photograph women in heels in general, 'cause they elongate more and it tightens everything, and so everything firms up, and they by instinct have better posture because they have to be balanced. She's six three and then three inch heels. Now imagine, I photograph her the first time in an eight and half foot tall room. Photoshop. No, I'm serious, I add Photoshop in on top of that. The answer for that really is apple boxes or small sub-stools. You don't need to be high up on it. Just even like chest or eye level would be great for that person, for sure. So basically raise the height of the camera. Raise the height of the camera. For this person, if we're just saying if she's in a group, we're actually going to talk about what to do to make yourself look shorter or to be more even in height without slouching or when people look really awkward 'cause they're like, you see that all the time, but there are couple really good ways to actually make yourself look a little shorter. Cool, and people wanting to know, do you work with hair and makeup artist, especially hair? Yeah. Who's in big hair. I don't do, for me, no it's all natural. (everyone laughing) In other words, this is all it does. But I don't do any shoots anymore with that don't have hair and makeup ever. But that's good, 'cause that's where I was working too, and so people look so much better sometimes with hair and makeup. And sometimes I don't even need to do anything on the photo side, they just look that much better. So yeah, always hair and makeup.
Posing doesn't have to be complicated. In Posing 101: The Essentials, fashion photographer and CreativeLive instructor Lindsay Adler gives you an introduction to essential posing techniques you need to start building the posing repertoire every photographer needs.
In this class, Lindsay will lay a foundation of posing basics to get you started on mastering posing. You'll learn tips on interacting with your subject and how to coach expressions. Lindsay will show you how your lens and camera angle work with different poses. Additionally, she covers best practices for posing each body part, what to look for in posture and how to pose and shoot through flaws.
Whether you're starting from scratch or have some posing experience under your belt, this course will build a solid foundation that will allow you to expand your posing knowledge and start getting creative.
Introduction to Posing
Expression and Interaction Tips
Posing Guidelines: Lenses & Camera Angles
Posing Guidelines: Posture & Directing
Basic Posing Demo
Posing Parts: Shoulders, Chin, Eyes & Hands
Posing Parts: Men, Feet, Elbows and Nose
Posing Contact Sheet Examples
Posing and Shooting Flaws
Amazing course, Lindsay presents a ton of great content in a relatively short amount of time. She's got a great lively personality and keeps it fun and interesting. Great job fielding all kinds of questions on the spot - she really knows her stuff!
First off, I absolutely love the way Lindsay teaches. She shares a LOT of useful information and brings it in a light and cheerful way. There are plenty of examples and photos along with her descriptions. It's a pleasure to watch! This was my first course on posing and I learned a lot. Would definitely recommend this course!
fantastic, very useful course with in depth explanations, no sec was wasted on irrelevant matters, i am a great fun of her courses and must admit that she is a very good teacher


Avène is an unique French Skincare brand that has created a line of skincare for sensitive, intolerant and allergic skins and this serum is simple and soothing. I have been using Avène's Soothing Hydrating Serum* near enough every morning and evening for just over a week and it has become a welcomed addition to my skincare routine. Serums have high concentration of certain products and are formulated to penetrate deeply into the skin to deliver these key ingredients. In the case of this serum, that key ingredient is Avène Thermal Spring Water which contains a unique active ingredient, renowned by dermatologists for its soothing properties.
This serum comes in a lovely frosted glass bottle with a pump, which I really like as it is far more hygienic than a tub. This serum is extremely cooling and soothing on the skin when applied, it is non irritating, reduces redness and leaves my skin soft and plump. I like to apply this serum after cleansing and toning and before moisturising and it gives my moisturiser that much needed boost, leaving my skin far more hydrated, than if I had used the moisturiser alone. It also has a very, very, subtle scent which I really like and a little goes a long way - so dont be put off by the 30ml measure. And don't over do it otherwise you'll be left looking greasy! It isn't as tacky as other serums I have tried and I haven't broken out since using this product.
If you feel your current products are quite doing their job, it might be time to add a serum to your skincare routine and I highly recommend this serum especially if you suffer from dehydrated, sensitive, stressed or irritated skin. This serum is a great alternative to Hydraluron Moisture Booster from Indeed Labs, not only is Avène's serum far cheaper, I much prefer it! You can buy it online here at Escentual who are currently offering 25% off this serum making it just £12.75 = winner!
What are your top French skincare picks?


"A homeless man who'd been living in a tent behind the Malibu Library for the past two years, Rigo Veloso, 47, finally has a roof over his head and is living his dream of staying in the Malibu area. His new landlord, longtime local resident Colin Dangaard, owns a small horse ranch off Kanan Dume Road. Dangaard remodeled a portion of an existing two-story building with horse stables below and rooms above into an efficiency apartment. Veloso moved in on December 1, and pays rent with $1,100 per month in government housing vouchers.
Alex Gittinger, one of Malibu's two homeless outreach workers with The People Concern, signed Veloso up for various homeless services, including the housing voucher program, which can be a lengthy and bureaucratic process. But having the housing vouchers doesn't mean that just any landlord will take them—it's still not easy to find a rental in LA County for $1,100/month.