<commit_before>package gorma

const modelTmpl = `// {{if .Description}}{{.Description}}{{else}}app.{{gotypename . 0}} storage type{{end}}
// Identifier: {{ $typeName :=  gotypename . 0}}{{$typeName := demodel $typeName}}
{{$td := gotypedef . 0 true false}}type {{$typeName}} {{modeldef $td .}}
{{ $belongsto := index .Metadata "github.com/bketelsen/gorma#belongsto" }}
{{ $m2m := index .Metadata "github.com/bketelsen/gorma#many2many" }}
func {{$typeName}}FromCreatePayload(ctx *app.Create{{demodel $typeName}}Context) {{$typeName}} {
	payload := ctx.Payload
	m := {{$typeName}}{}
	copier.Copy(&m, payload)
{{ if ne $belongsto "" }}{{$barray := split $belongsto ","}}{{ range $idx, $bt := $barray}}
	m.{{ $bt}}ID=int(ctx.{{ demodel $bt}}ID){{end}}{{end}}
	return m
}

func {{$typeName}}FromUpdatePayload(ctx *app.Update{{demodel $typeName}}Context) {{$typeName}} {
	payload := ctx.Payload
	m := {{$typeName}}{}
	copier.Copy(&m, payload)
	return m
}

func (m {{$typeName}}) ToApp() *app.{{demodel $typeName}} {
	target := app.{{demodel $typeName}}{}
	copier.Copy(&target, &m)
	return &target
}
{{ $tablename := index .Metadata "github.com/bketelsen/gorma#tablename" }}
{{ if ne $tablename "" }}
func (m {{$typeName}}) TableName() string {
	return "{{ $tablename }}"
}
{{ end }}
{{ $roler := index .Metadata "github.com/bketelsen/gorma#roler" }}
{{ if ne $roler "" }}
func (m {{$typeName}}) GetRole() string {
	return m.Role
}
{{end}}

type {{$typeName}}Storage interface {
	List(ctx context.Context) []{{$typeName}}
	One(ctx context.Context, id int) ({{$typeName}}, error)
	Add(ctx context.Context, o {{$typeName}}) ({{$typeName}}, error)
	Update(ctx context.Context, o {{$typeName}}) (error)
	Delete(ctx context.Context, id int) (error)
	{{ storagedef . }}
}
{{ $cached := index .Metadata "github.com/bketelsen/gorma#cached" }}
type {{$typeName}}DB struct {
	DB gorm.DB
	{{ if ne $cached "" }}cache *cache.Cache{{end}}
}
{{ if ne $belongsto "" }}{{$barray := split $belongsto ","}}{{ range $idx, $bt := $barray}}
// would prefer to just pass a context in here, but they're all different, so can't
func {{$typeName}}FilterBy{{$bt}}(parentid int, originaldb *gorm.DB) func(db *gorm.DB) *gorm.DB {
	if parentid > 0 {
		return func(db *gorm.DB) *gorm.DB {
			return db.Where("{{ snake $bt }}_id = ?", parentid)
		}
	} else {
		return func(db *gorm.DB) *gorm.DB {
			return db
		}
	}
}{{end}}{{end}}

func New{{$typeName}}DB(db gorm.DB) *{{$typeName}}DB {
	{{ if ne $cached "" }}
	return &{{$typeName}}DB{
		DB: db,
		cache: cache.New(5*time.Minute, 30*time.Second),
	}
	{{ else  }}
	return &{{$typeName}}DB{DB: db}

	{{ end  }}
}

func (m *{{$typeName}}DB) List(ctx context.Context) []{{$typeName}} {

	var objs []{{$typeName}}
    m.DB.Find(&objs)
	return objs
}

func (m *{{$typeName}}DB) One(ctx context.Context, id int) ({{$typeName}}, error) {
	{{ if ne $cached "" }}//first attempt to retrieve from cache
	o,found := m.cache.Get(strconv.Itoa(id))
	if found {
		return o.({{$typeName}}), nil
	}
	// fallback to database if not found{{ end }}
	var obj {{$typeName}}

	err := m.DB.Find(&obj, id).Error
	{{ if ne $cached "" }} go m.cache.Set(strconv.Itoa(id), obj, cache.DefaultExpiration) {{ end }}
	return obj, err
}

func (m *{{$typeName}}DB) Add(ctx context.Context, model {{$typeName}}) ({{$typeName}}, error) {
	err := m.DB.Create(&model).Error
	{{ if ne $cached "" }} go m.cache.Set(strconv.Itoa(id), model, cache.DefaultExpiration) {{ end }}
	return model, err
}

func (m *{{$typeName}}DB) Update(ctx context.Context, model {{$typeName}}) error {
	obj, err := m.One(ctx, model.ID)
	if err != nil {
		return  err
	}
	err = m.DB.Model(&obj).Updates(model).Error
	{{ if ne $cached "" }}
	go func(){
	obj, err := m.One(ctx, model.ID)
	if err == nil {
		m.cache.Set(strconv.Itoa(model.ID), obj, cache.DefaultExpiration)
	}
	}()
	{{ end }}

	return err
}

func (m *{{$typeName}}DB) Delete(ctx context.Context, id int)  error {
	var obj {{$typeName}}
	err := m.DB.Delete(&obj, id).Error
	if err != nil {
		return  err
	}
	{{ if ne $cached "" }} go m.cache.Delete(strconv.Itoa(id)) {{ end }}
	return  nil
}

{{ if ne $m2m "" }}{{$barray := split $m2m ","}}{{ range $idx, $bt := $barray}}
{{ $pieces := split $bt ":" }} {{ $lowertype := index $pieces 1  }} {{ $lower := lower $lowertype }}  {{ $lowerplural := index $pieces 0  }} {{ $lowerplural := lower $lowerplural}}
func (m *{{$typeName}}DB) Delete{{index $pieces 1}}(ctx context.Context,{{lower $typeName}}ID,  {{$lower}}ID int)  error {
	var obj {{$typeName}}
	obj.ID = {{lower $typeName}}ID
	var assoc {{index $pieces 1}}
	var err error
	assoc.ID = {{$lower}}ID
	if err != nil {
		return err
	}
	err = m.DB.Model(&obj).Association("{{index $pieces 0}}").Delete(assoc).Error
	if err != nil {
		return  err
	}
	return  nil
}
func (m *{{$typeName}}DB) Add{{index $pieces 1}}(ctx context.Context, {{lower $typeName}}ID, {{$lower}}ID int) error {
	var {{lower $typeName}} {{$typeName}}
	{{lower $typeName}}.ID = {{lower $typeName}}ID
	var assoc {{index $pieces 1}}
	assoc.ID = {{$lower}}ID
	err := m.DB.Model(&{{lower $typeName}}).Association("{{index $pieces 0}}").Append(assoc).Error
	if err != nil {
		return  err
	}
	return  nil
}
func (m *{{$typeName}}DB) List{{index $pieces 0}}(ctx context.Context, {{lower $typeName}}ID int)  []{{index $pieces 1}} {
	list := make([]{{index $pieces 1}}, 0)
	var obj {{$typeName}}
	obj.ID = {{lower $typeName}}ID
	m.DB.Model(&obj).Association("{{index $pieces 0}}").Find(&list)
	return  nil
}
{{end}}{{end}}
{{if ne $belongsto ""}}{{$barray := split $belongsto ","}}{{ range $idx, $bt := $barray}}
func Filter{{$typeName}}By{{$bt}}(parent int, list []{{$typeName}}) []{{$typeName}} {
	filtered := make([]{{$typeName}},0)
	for _,o := range list {
		if o.{{$bt}}ID == int(parent) {
			filtered = append(filtered,o)
		}
	}
	return filtered
}
{{end}}{{end}}
`
<commit_msg>more cache<commit_after>package gorma

const modelTmpl = `// {{if .Description}}{{.Description}}{{else}}app.{{gotypename . 0}} storage type{{end}}
// Identifier: {{ $typeName :=  gotypename . 0}}{{$typeName := demodel $typeName}}
{{$td := gotypedef . 0 true false}}type {{$typeName}} {{modeldef $td .}}
{{ $belongsto := index .Metadata "github.com/bketelsen/gorma#belongsto" }}
{{ $m2m := index .Metadata "github.com/bketelsen/gorma#many2many" }}
func {{$typeName}}FromCreatePayload(ctx *app.Create{{demodel $typeName}}Context) {{$typeName}} {
	payload := ctx.Payload
	m := {{$typeName}}{}
	copier.Copy(&m, payload)
{{ if ne $belongsto "" }}{{$barray := split $belongsto ","}}{{ range $idx, $bt := $barray}}
	m.{{ $bt}}ID=int(ctx.{{ demodel $bt}}ID){{end}}{{end}}
	return m
}

func {{$typeName}}FromUpdatePayload(ctx *app.Update{{demodel $typeName}}Context) {{$typeName}} {
	payload := ctx.Payload
	m := {{$typeName}}{}
	copier.Copy(&m, payload)
	return m
}

func (m {{$typeName}}) ToApp() *app.{{demodel $typeName}} {
	target := app.{{demodel $typeName}}{}
	copier.Copy(&target, &m)
	return &target
}
{{ $tablename := index .Metadata "github.com/bketelsen/gorma#tablename" }}
{{ if ne $tablename "" }}
func (m {{$typeName}}) TableName() string {
	return "{{ $tablename }}"
}
{{ end }}
{{ $roler := index .Metadata "github.com/bketelsen/gorma#roler" }}
{{ if ne $roler "" }}
func (m {{$typeName}}) GetRole() string {
	return m.Role
}
{{end}}

type {{$typeName}}Storage interface {
	List(ctx context.Context) []{{$typeName}}
	One(ctx context.Context, id int) ({{$typeName}}, error)
	Add(ctx context.Context, o {{$typeName}}) ({{$typeName}}, error)
	Update(ctx context.Context, o {{$typeName}}) (error)
	Delete(ctx context.Context, id int) (error)
	{{ storagedef . }}
}
{{ $cached := index .Metadata "github.com/bketelsen/gorma#cached" }}
type {{$typeName}}DB struct {
	DB gorm.DB
	{{ if ne $cached "" }}cache *cache.Cache{{end}}
}
{{ if ne $belongsto "" }}{{$barray := split $belongsto ","}}{{ range $idx, $bt := $barray}}
// would prefer to just pass a context in here, but they're all different, so can't
func {{$typeName}}FilterBy{{$bt}}(parentid int, originaldb *gorm.DB) func(db *gorm.DB) *gorm.DB {
	if parentid > 0 {
		return func(db *gorm.DB) *gorm.DB {
			return db.Where("{{ snake $bt }}_id = ?", parentid)
		}
	} else {
		return func(db *gorm.DB) *gorm.DB {
			return db
		}
	}
}{{end}}{{end}}

func New{{$typeName}}DB(db gorm.DB) *{{$typeName}}DB {
	{{ if ne $cached "" }}
	return &{{$typeName}}DB{
		DB: db,
		cache: cache.New(5*time.Minute, 30*time.Second),
	}
	{{ else  }}
	return &{{$typeName}}DB{DB: db}

	{{ end  }}
}

func (m *{{$typeName}}DB) List(ctx context.Context) []{{$typeName}} {

	var objs []{{$typeName}}
    m.DB.Find(&objs)
	return objs
}

func (m *{{$typeName}}DB) One(ctx context.Context, id int) ({{$typeName}}, error) {
	{{ if ne $cached "" }}//first attempt to retrieve from cache
	o,found := m.cache.Get(strconv.Itoa(id))
	if found {
		return o.({{$typeName}}), nil
	}
	// fallback to database if not found{{ end }}
	var obj {{$typeName}}

	err := m.DB.Find(&obj, id).Error
	{{ if ne $cached "" }} go m.cache.Set(strconv.Itoa(id), obj, cache.DefaultExpiration) {{ end }}
	return obj, err
}

func (m *{{$typeName}}DB) Add(ctx context.Context, model {{$typeName}}) ({{$typeName}}, error) {
	err := m.DB.Create(&model).Error
	{{ if ne $cached "" }} go m.cache.Set(strconv.Itoa(model.ID), model, cache.DefaultExpiration) {{ end }}
	return model, err
}

func (m *{{$typeName}}DB) Update(ctx context.Context, model {{$typeName}}) error {
	obj, err := m.One(ctx, model.ID)
	if err != nil {
		return  err
	}
	err = m.DB.Model(&obj).Updates(model).Error
	{{ if ne $cached "" }}
	go func(){
	obj, err := m.One(ctx, model.ID)
	if err == nil {
		m.cache.Set(strconv.Itoa(model.ID), obj, cache.DefaultExpiration)
	}
	}()
	{{ end }}

	return err
}

func (m *{{$typeName}}DB) Delete(ctx context.Context, id int)  error {
	var obj {{$typeName}}
	err := m.DB.Delete(&obj, id).Error
	if err != nil {
		return  err
	}
	{{ if ne $cached "" }} go m.cache.Delete(strconv.Itoa(id)) {{ end }}
	return  nil
}

{{ if ne $m2m "" }}{{$barray := split $m2m ","}}{{ range $idx, $bt := $barray}}
{{ $pieces := split $bt ":" }} {{ $lowertype := index $pieces 1  }} {{ $lower := lower $lowertype }}  {{ $lowerplural := index $pieces 0  }} {{ $lowerplural := lower $lowerplural}}
func (m *{{$typeName}}DB) Delete{{index $pieces 1}}(ctx context.Context,{{lower $typeName}}ID,  {{$lower}}ID int)  error {
	var obj {{$typeName}}
	obj.ID = {{lower $typeName}}ID
	var assoc {{index $pieces 1}}
	var err error
	assoc.ID = {{$lower}}ID
	if err != nil {
		return err
	}
	err = m.DB.Model(&obj).Association("{{index $pieces 0}}").Delete(assoc).Error
	if err != nil {
		return  err
	}
	return  nil
}
func (m *{{$typeName}}DB) Add{{index $pieces 1}}(ctx context.Context, {{lower $typeName}}ID, {{$lower}}ID int) error {
	var {{lower $typeName}} {{$typeName}}
	{{lower $typeName}}.ID = {{lower $typeName}}ID
	var assoc {{index $pieces 1}}
	assoc.ID = {{$lower}}ID
	err := m.DB.Model(&{{lower $typeName}}).Association("{{index $pieces 0}}").Append(assoc).Error
	if err != nil {
		return  err
	}
	return  nil
}
func (m *{{$typeName}}DB) List{{index $pieces 0}}(ctx context.Context, {{lower $typeName}}ID int)  []{{index $pieces 1}} {
	list := make([]{{index $pieces 1}}, 0)
	var obj {{$typeName}}
	obj.ID = {{lower $typeName}}ID
	m.DB.Model(&obj).Association("{{index $pieces 0}}").Find(&list)
	return  nil
}
{{end}}{{end}}
{{if ne $belongsto ""}}{{$barray := split $belongsto ","}}{{ range $idx, $bt := $barray}}
func Filter{{$typeName}}By{{$bt}}(parent int, list []{{$typeName}}) []{{$typeName}} {
	filtered := make([]{{$typeName}},0)
	for _,o := range list {
		if o.{{$bt}}ID == int(parent) {
			filtered = append(filtered,o)
		}
	}
	return filtered
}
{{end}}{{end}}
`
<|endoftext|>


<commit_before>// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package helmreconciler

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

	errors2 "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/util/retry"
	util2 "k8s.io/kubectl/pkg/util"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"istio.io/istio/istioctl/pkg/install/k8sversion"
	"istio.io/istio/operator/pkg/cache"
	"istio.io/istio/operator/pkg/metrics"
	"istio.io/istio/operator/pkg/name"
	"istio.io/istio/operator/pkg/object"
	"istio.io/istio/operator/pkg/util"
	"istio.io/istio/operator/pkg/util/progress"
)

const fieldOwnerOperator = "istio-operator"

// ApplyManifest applies the manifest to create or update resources. It returns the processed (created or updated)
// objects and the number of objects in the manifests.
func (h *HelmReconciler) ApplyManifest(manifest name.Manifest) (object.K8sObjects, int, error) {
	var processedObjects object.K8sObjects
	var deployedObjects int
	var errs util.Errors
	cname := string(manifest.Name)
	crHash, err := h.getCRHash(cname)
	if err != nil {
		return nil, 0, err
	}

	scope.Infof("Processing resources from manifest: %s for CR %s", cname, crHash)
	allObjects, err := object.ParseK8sObjectsFromYAMLManifest(manifest.Content)
	if err != nil {
		return nil, 0, err
	}

	objectCache := cache.GetCache(crHash)

	// Ensure that for a given CR crHash only one control loop uses the per-crHash cache at any time.
	objectCache.Mu.Lock()
	defer objectCache.Mu.Unlock()

	// No further locking required beyond this point, since we have a ptr to a cache corresponding to a CR crHash and no
	// other controller is allowed to work on at the same time.
	var changedObjects object.K8sObjects
	var changedObjectKeys []string
	allObjectsMap := make(map[string]bool)

	// Check which objects in the manifest have changed from those in the cache.
	for _, obj := range allObjects {
		oh := obj.Hash()
		allObjectsMap[oh] = true
		if co, ok := objectCache.Cache[oh]; ok && obj.Equal(co) {
			// Object is in the cache and unchanged.
			metrics.AddResource(obj.FullName(), obj.GroupVersionKind().GroupKind())
			deployedObjects++
			continue
		}
		changedObjects = append(changedObjects, obj)
		changedObjectKeys = append(changedObjectKeys, oh)
	}

	var plog *progress.ManifestLog
	if len(changedObjectKeys) > 0 {
		plog = h.opts.ProgressLog.NewComponent(cname)
		scope.Infof("The following objects differ between generated manifest and cache: \n - %s", strings.Join(changedObjectKeys, "\n - "))
	} else {
		scope.Infof("Generated manifest objects are the same as cached for component %s.", cname)
	}

	// check minor version only
	serverSideApply := false
	if h.restConfig != nil {
		k8sVer, err := k8sversion.GetKubernetesVersion(h.restConfig)
		if err != nil {
			scope.Errorf("failed to get k8s version: %s", err)
		}
		if k8sVer >= 16 {
			serverSideApply = true
		}
	}

	// Objects are applied in groups: namespaces, CRDs, everything else, with wait for ready in between.
	nsObjs := object.KindObjects(changedObjects, name.NamespaceStr)
	crdObjs := object.KindObjects(changedObjects, name.CRDStr)
	otherObjs := object.ObjectsNotInLists(changedObjects, nsObjs, crdObjs)
	for _, objList := range []object.K8sObjects{nsObjs, crdObjs, otherObjs} {
		// For a given group of objects, apply in sorted order of priority with no wait in between.
		objList.Sort(object.DefaultObjectOrder())
		for _, obj := range objList {
			obju := obj.UnstructuredObject()
			if err := h.applyLabelsAndAnnotations(obju, cname); err != nil {
				return nil, 0, err
			}
			if err := h.ApplyObject(obj.UnstructuredObject(), serverSideApply); err != nil {
				scope.Error(err.Error())
				errs = util.AppendErr(errs, err)
				continue
			}
			plog.ReportProgress()
			metrics.AddResource(obj.FullName(), obj.GroupVersionKind().GroupKind())
			processedObjects = append(processedObjects, obj)
			// Update the cache with the latest object.
			objectCache.Cache[obj.Hash()] = obj
		}
	}

	// Prune anything not in the manifest out of the cache.
	var removeKeys []string
	for k := range objectCache.Cache {
		if !allObjectsMap[k] {
			removeKeys = append(removeKeys, k)
		}
	}
	for _, k := range removeKeys {
		scope.Infof("Pruning object %s from cache.", k)
		delete(objectCache.Cache, k)
	}

	if len(changedObjectKeys) > 0 {
		if len(errs) != 0 {
			plog.ReportError(util.ToString(errs.Dedup(), "\n"))
			return processedObjects, 0, errs.ToError()
		}

		err := WaitForResources(processedObjects, h.restConfig, h.clientSet,
			h.opts.WaitTimeout, h.opts.DryRun, plog)
		if err != nil {
			werr := fmt.Errorf("failed to wait for resource: %v", err)
			plog.ReportError(werr.Error())
			return processedObjects, 0, werr
		}
		plog.ReportFinished()

	}
	return processedObjects, deployedObjects, nil
}

// ApplyObject creates or updates an object in the API server depending on whether it already exists.
// It mutates obj.
func (h *HelmReconciler) ApplyObject(obj *unstructured.Unstructured, serverSideApply bool) error {
	if obj.GetKind() == "List" {
		var errs util.Errors
		list, err := obj.ToList()
		if err != nil {
			scope.Errorf("error converting List object: %s", err)
			return err
		}
		for _, item := range list.Items {
			err = h.ApplyObject(&item, serverSideApply)
			if err != nil {
				errs = util.AppendErr(errs, err)
			}
		}
		return errs.ToError()
	}

	if err := util2.CreateApplyAnnotation(obj, unstructured.UnstructuredJSONScheme); err != nil {
		scope.Errorf("unexpected error adding apply annotation to object: %s", err)
	}

	receiver := &unstructured.Unstructured{}
	receiver.SetGroupVersionKind(obj.GroupVersionKind())
	objectKey, _ := client.ObjectKeyFromObject(obj)
	objectStr := fmt.Sprintf("%s/%s/%s", obj.GetKind(), obj.GetNamespace(), obj.GetName())

	scope.Debugf("Processing object:\n%s\n\n", util.ToYAML(obj))
	if h.opts.DryRun {
		scope.Infof("Not applying object %s because of dry run.", objectStr)
		return nil
	}

	gvk := obj.GetObjectKind().GroupVersionKind()

	if serverSideApply {
		return h.serverSideApply(obj)
	}

	// for k8s version before 1.16
	backoff := wait.Backoff{Duration: time.Millisecond * 10, Factor: 2, Steps: 3}
	return retry.RetryOnConflict(backoff, func() error {
		err := h.client.Get(context.TODO(), objectKey, receiver)

		switch {
		case errors2.IsNotFound(err):
			scope.Infof("Creating %s (%s/%s)", objectStr, h.iop.Name, h.iop.Spec.Revision)
			err = h.client.Create(context.TODO(), obj)
			if err != nil {
				return fmt.Errorf("failed to create %q: %w", objectStr, err)
			}
			metrics.ResourceCreationTotal.
				With(metrics.ResourceKindLabel.Value(util.GKString(gvk.GroupKind()))).
				Increment()
			return nil
		case err == nil:
			scope.Infof("Updating %s (%s/%s)", objectStr, h.iop.Name, h.iop.Spec.Revision)
			// The correct way to do this is with a server-side apply. However, this requires users to be running Kube 1.16.
			// When we no longer support < 1.16 use the code described in the linked issue.
			// https://github.com/kubernetes-sigs/controller-runtime/issues/347
			if err := applyOverlay(receiver, obj); err != nil {
				return err
			}
			if err := h.client.Update(context.TODO(), receiver); err != nil {
				return err
			}
			metrics.ResourceUpdateTotal.
				With(metrics.ResourceKindLabel.Value(util.GKString(gvk.GroupKind()))).
				Increment()
			return nil
		}
		return nil
	})

}

// use server-side apply, require kubernetes 1.16+
func (h *HelmReconciler) serverSideApply(obj *unstructured.Unstructured) error {
	objectStr := fmt.Sprintf("%s/%s/%s", obj.GetKind(), obj.GetNamespace(), obj.GetName())
	scope.Infof("using server side apply to update obj: %v", objectStr)
	opts := []client.PatchOption{client.ForceOwnership, client.FieldOwner(fieldOwnerOperator)}
	if err := h.client.Patch(context.TODO(), obj, client.Apply, opts...); err != nil {
		return fmt.Errorf("failed to update resource with server-side apply for obj %v: %v", objectStr, err)
	}
	return nil
}
<commit_msg>do not use server side apply for CRD (#28421)<commit_after>// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package helmreconciler

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

	errors2 "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/util/retry"
	util2 "k8s.io/kubectl/pkg/util"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"istio.io/istio/istioctl/pkg/install/k8sversion"
	"istio.io/istio/operator/pkg/cache"
	"istio.io/istio/operator/pkg/metrics"
	"istio.io/istio/operator/pkg/name"
	"istio.io/istio/operator/pkg/object"
	"istio.io/istio/operator/pkg/util"
	"istio.io/istio/operator/pkg/util/progress"
)

const fieldOwnerOperator = "istio-operator"

// ApplyManifest applies the manifest to create or update resources. It returns the processed (created or updated)
// objects and the number of objects in the manifests.
func (h *HelmReconciler) ApplyManifest(manifest name.Manifest) (object.K8sObjects, int, error) {
	var processedObjects object.K8sObjects
	var deployedObjects int
	var errs util.Errors
	cname := string(manifest.Name)
	crHash, err := h.getCRHash(cname)
	if err != nil {
		return nil, 0, err
	}

	scope.Infof("Processing resources from manifest: %s for CR %s", cname, crHash)
	allObjects, err := object.ParseK8sObjectsFromYAMLManifest(manifest.Content)
	if err != nil {
		return nil, 0, err
	}

	objectCache := cache.GetCache(crHash)

	// Ensure that for a given CR crHash only one control loop uses the per-crHash cache at any time.
	objectCache.Mu.Lock()
	defer objectCache.Mu.Unlock()

	// No further locking required beyond this point, since we have a ptr to a cache corresponding to a CR crHash and no
	// other controller is allowed to work on at the same time.
	var changedObjects object.K8sObjects
	var changedObjectKeys []string
	allObjectsMap := make(map[string]bool)

	// Check which objects in the manifest have changed from those in the cache.
	for _, obj := range allObjects {
		oh := obj.Hash()
		allObjectsMap[oh] = true
		if co, ok := objectCache.Cache[oh]; ok && obj.Equal(co) {
			// Object is in the cache and unchanged.
			metrics.AddResource(obj.FullName(), obj.GroupVersionKind().GroupKind())
			deployedObjects++
			continue
		}
		changedObjects = append(changedObjects, obj)
		changedObjectKeys = append(changedObjectKeys, oh)
	}

	var plog *progress.ManifestLog
	if len(changedObjectKeys) > 0 {
		plog = h.opts.ProgressLog.NewComponent(cname)
		scope.Infof("The following objects differ between generated manifest and cache: \n - %s", strings.Join(changedObjectKeys, "\n - "))
	} else {
		scope.Infof("Generated manifest objects are the same as cached for component %s.", cname)
	}

	// check minor version only
	serverSideApply := false
	if h.restConfig != nil {
		k8sVer, err := k8sversion.GetKubernetesVersion(h.restConfig)
		if err != nil {
			scope.Errorf("failed to get k8s version: %s", err)
		}
		if k8sVer >= 16 {
			serverSideApply = true
		}
	}

	// Objects are applied in groups: namespaces, CRDs, everything else, with wait for ready in between.
	nsObjs := object.KindObjects(changedObjects, name.NamespaceStr)
	crdObjs := object.KindObjects(changedObjects, name.CRDStr)
	otherObjs := object.ObjectsNotInLists(changedObjects, nsObjs, crdObjs)
	for _, objList := range []object.K8sObjects{nsObjs, crdObjs, otherObjs} {
		// For a given group of objects, apply in sorted order of priority with no wait in between.
		objList.Sort(object.DefaultObjectOrder())
		for _, obj := range objList {
			obju := obj.UnstructuredObject()
			if err := h.applyLabelsAndAnnotations(obju, cname); err != nil {
				return nil, 0, err
			}
			if err := h.ApplyObject(obj.UnstructuredObject(), serverSideApply); err != nil {
				scope.Error(err.Error())
				errs = util.AppendErr(errs, err)
				continue
			}
			plog.ReportProgress()
			metrics.AddResource(obj.FullName(), obj.GroupVersionKind().GroupKind())
			processedObjects = append(processedObjects, obj)
			// Update the cache with the latest object.
			objectCache.Cache[obj.Hash()] = obj
		}
	}

	// Prune anything not in the manifest out of the cache.
	var removeKeys []string
	for k := range objectCache.Cache {
		if !allObjectsMap[k] {
			removeKeys = append(removeKeys, k)
		}
	}
	for _, k := range removeKeys {
		scope.Infof("Pruning object %s from cache.", k)
		delete(objectCache.Cache, k)
	}

	if len(changedObjectKeys) > 0 {
		if len(errs) != 0 {
			plog.ReportError(util.ToString(errs.Dedup(), "\n"))
			return processedObjects, 0, errs.ToError()
		}

		err := WaitForResources(processedObjects, h.restConfig, h.clientSet,
			h.opts.WaitTimeout, h.opts.DryRun, plog)
		if err != nil {
			werr := fmt.Errorf("failed to wait for resource: %v", err)
			plog.ReportError(werr.Error())
			return processedObjects, 0, werr
		}
		plog.ReportFinished()

	}
	return processedObjects, deployedObjects, nil
}

// ApplyObject creates or updates an object in the API server depending on whether it already exists.
// It mutates obj.
func (h *HelmReconciler) ApplyObject(obj *unstructured.Unstructured, serverSideApply bool) error {
	if obj.GetKind() == "List" {
		var errs util.Errors
		list, err := obj.ToList()
		if err != nil {
			scope.Errorf("error converting List object: %s", err)
			return err
		}
		for _, item := range list.Items {
			err = h.ApplyObject(&item, serverSideApply)
			if err != nil {
				errs = util.AppendErr(errs, err)
			}
		}
		return errs.ToError()
	}

	if err := util2.CreateApplyAnnotation(obj, unstructured.UnstructuredJSONScheme); err != nil {
		scope.Errorf("unexpected error adding apply annotation to object: %s", err)
	}

	receiver := &unstructured.Unstructured{}
	receiver.SetGroupVersionKind(obj.GroupVersionKind())
	objectKey, _ := client.ObjectKeyFromObject(obj)
	objectStr := fmt.Sprintf("%s/%s/%s", obj.GetKind(), obj.GetNamespace(), obj.GetName())

	scope.Debugf("Processing object:\n%s\n\n", util.ToYAML(obj))
	if h.opts.DryRun {
		scope.Infof("Not applying object %s because of dry run.", objectStr)
		return nil
	}

	gvk := obj.GetObjectKind().GroupVersionKind()
	// Skip CRD for SSA because of: https://github.com/kubernetes/kubernetes/issues/96060
	if serverSideApply && obj.GetKind() != name.CRDStr {
		return h.serverSideApply(obj)
	}

	// for k8s version before 1.16
	backoff := wait.Backoff{Duration: time.Millisecond * 10, Factor: 2, Steps: 3}
	return retry.RetryOnConflict(backoff, func() error {
		err := h.client.Get(context.TODO(), objectKey, receiver)

		switch {
		case errors2.IsNotFound(err):
			scope.Infof("Creating %s (%s/%s)", objectStr, h.iop.Name, h.iop.Spec.Revision)
			err = h.client.Create(context.TODO(), obj)
			if err != nil {
				return fmt.Errorf("failed to create %q: %w", objectStr, err)
			}
			metrics.ResourceCreationTotal.
				With(metrics.ResourceKindLabel.Value(util.GKString(gvk.GroupKind()))).
				Increment()
			return nil
		case err == nil:
			scope.Infof("Updating %s (%s/%s)", objectStr, h.iop.Name, h.iop.Spec.Revision)
			// The correct way to do this is with a server-side apply. However, this requires users to be running Kube 1.16.
			// When we no longer support < 1.16 use the code described in the linked issue.
			// https://github.com/kubernetes-sigs/controller-runtime/issues/347
			if err := applyOverlay(receiver, obj); err != nil {
				return err
			}
			if err := h.client.Update(context.TODO(), receiver); err != nil {
				return err
			}
			metrics.ResourceUpdateTotal.
				With(metrics.ResourceKindLabel.Value(util.GKString(gvk.GroupKind()))).
				Increment()
			return nil
		}
		return nil
	})

}

// use server-side apply, require kubernetes 1.16+
func (h *HelmReconciler) serverSideApply(obj *unstructured.Unstructured) error {
	objectStr := fmt.Sprintf("%s/%s/%s", obj.GetKind(), obj.GetNamespace(), obj.GetName())
	scope.Infof("using server side apply to update obj: %v", objectStr)
	opts := []client.PatchOption{client.ForceOwnership, client.FieldOwner(fieldOwnerOperator)}
	if err := h.client.Patch(context.TODO(), obj, client.Apply, opts...); err != nil {
		return fmt.Errorf("failed to update resource with server-side apply for obj %v: %v", objectStr, err)
	}
	return nil
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014 @ S1N1 Team.
 * name :
 * author : jarryliu
 * date : 2014-02-05 21:53
 * description :
 * history :
 */
package api

import (
	"github.com/atnet/gof/web"
	"github.com/atnet/gof/web/mvc"
)

var (
	Routes web.Route = new(web.RouteMap)
	PathPrefix = "/go2o_api_v1"
)

//处理请求
func Handle(ctx *web.Context) {
	Routes.Handle(ctx)
}

// 处理请求
func handleUrl(v interface{})func(*web.Context){
	return func(ctx *web.Context){
		mvc.HandlePath(v,ctx,splitPath(ctx),false)
	}
}

func splitPath(ctx *web.Context)string{
	return ctx.Request.URL.Path[len(PathPrefix):]
}

func init() {
	bc := new(BaseC)
	pc := &partnerC{bc}
	mc := &MemberC{bc}
	gc := &getC{bc}

	Routes.Add("/", ApiTest)
	Routes.Add(PathPrefix+"/mm_login", mc.Login)       // 会员登陆接口
	Routes.Add(PathPrefix+"/mm_register", mc.Register) // 会员登陆接口
	Routes.Add(PathPrefix+"/member/*", handleUrl(mc))      // 会员接口
	Routes.Add(PathPrefix+"/partner/*",handleUrl(pc))     // 会员接口

	// 会员接口
	Routes.Add("/go2o_api_v1/get/*",handleUrl(gc))
}
<commit_msg>commit<commit_after>/**
 * Copyright 2014 @ S1N1 Team.
 * name :
 * author : jarryliu
 * date : 2014-02-05 21:53
 * description :
 * history :
 */
package api

import (
	"github.com/atnet/gof/web"
	"github.com/atnet/gof/web/mvc"
)

var (
	Routes web.Route = new(web.RouteMap)
	PathPrefix = "/go2o_api_v1"
)

//处理请求
func Handle(ctx *web.Context) {
	Routes.Handle(ctx)
}

// 处理请求
func HandleUrlFunc(v interface{})func(*web.Context){
	return func(ctx *web.Context){
		mvc.HandlePath(v,ctx,splitPath(ctx),false)
	}
}

func splitPath(ctx *web.Context)string{
	return ctx.Request.URL.Path[len(PathPrefix):]
}

func init() {
	bc := new(BaseC)
	pc := &partnerC{bc}
	mc := &MemberC{bc}
	gc := &getC{bc}

	Routes.Add("/", ApiTest)
	Routes.Add(PathPrefix+"/mm_login", mc.Login)       // 会员登陆接口
	Routes.Add(PathPrefix+"/mm_register", mc.Register) // 会员登陆接口
	Routes.Add(PathPrefix+"/member/*", HandleUrlFunc(mc))      // 会员接口
	Routes.Add(PathPrefix+"/partner/*", HandleUrlFunc(pc))     // 会员接口

	// 会员接口
	Routes.Add("/go2o_api_v1/get/*", HandleUrlFunc(gc))
}
<|endoftext|>


<commit_before>package main

import . "./godray"

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"math"
	"os"
	"sync"
)

var i *Vector = &Vector{1, 0, 0}
var j *Vector = &Vector{0, 1, 0}
var k *Vector = &Vector{0, 0, 1}
var o *Point = &Point{0, 0, 0}

func getClosestIntersection(ray *Ray,
	objects []Object) (*Intersection, Object) {
	intersections := make([]*Intersection, len(objects))

	for i, object := range objects {
		point, dist, n := object.Intersect(ray)
		intersections[i] = &Intersection{point, dist, n}
	}

	var closestIntersection *Intersection
	var closestObject Object
	for i, intersection := range intersections {
		if closestIntersection == nil ||
			intersection.Distance < closestIntersection.Distance {
			closestIntersection = intersection
			closestObject = objects[i]
		}
	}

	return closestIntersection, closestObject
}

func main() {
	eye := o
	camera := NewCamera(eye.Add(k.Scale(10)), k.Scale(-1), j)
	screen := &Screen{800, 600, 45}

	// colors
	red := &Color{color.RGBA{255, 0, 0, 255}}
	//green := &Color{color.RGBA{0, 0, 255, 255}}
	blue := &Color{color.RGBA{0, 0, 255, 255}}
	white := &Color{color.RGBA{255, 255, 255, 255}}
	black := &Color{color.RGBA{0, 0, 0, 255}}

	// lights
	lights := [...]*Light{
		&Light{
			&Point{0, 4, -4},
			white.Scale(0.1),
			white,
			white,
		},
		&Light{
			&Point{-4, 0, -2},
			white.Scale(0.1),
			white,
			white,
		},
	}

	// objects
	objects := []Object{
		NewSphere(&Point{0, -4.5, -4}, 3, &Material{
			blue,
			blue,
			white,
			10,
		}),

		NewSphere(&Point{0, 0, -4}, 1, &Material{
			red,
			red,
			white,
			10,
		}),
	}

	//hit := &Ray{&Point{0, 0, 0}, &Vector{-0.01, 0.01, -1}}
	//miss := &Ray{&Point{0, 5, 0}, &Vector{0, 0, -4}}
	//_, _, n := sphere.Intersect(hit)
	//intersection, t := sphere.Intersect(miss)
	//fmt.Println(n)

	out, err := os.Create("./output.png")
	if err != nil {
		os.Exit(1)
	}

	imgRect := image.Rect(0, 0, screen.Width, screen.Height)
	img := image.NewRGBA(imgRect)
	draw.Draw(img, img.Bounds(), &image.Uniform{color.Black}, image.ZP, draw.Src)

	//runtime.GOMAXPROCS(1)
	wg := sync.WaitGroup{}

	for u := 0; u < screen.Width; u++ {
		for v := 0; v < screen.Height; v++ {
			wg.Add(1)
			go func(u, v int) {
				ray := camera.GetRayTo(screen, u, v)

				closestIntersection, closestObject := getClosestIntersection(ray,
					objects)
				intersection := closestIntersection.Point
				n := closestIntersection.Normal

				if intersection != nil {
					var illumination *Color = black

					for _, light := range lights {
						illumination = illumination.Add(closestObject.Material().Ambient.
							Multiply(light.Ambient))

						l := light.Position.Subtract(intersection).Normalize()

						rayToLight := &Ray{
							intersection,
							l,
						}

						obstruction, _ := getClosestIntersection(rayToLight, objects)
						if obstruction.Point != nil {
							continue
						}

						r := n.Scale(2 * l.Dot(n)).Subtract(l)
						vv := ray.V.Normalize().Scale(-1)

						diffuseTerm := light.Diffuse.Scale(l.Dot(n)).
							Multiply(closestObject.Material().Diffuse)
						specularTerm := light.Specular.
							Scale(math.Pow(r.Dot(vv), closestObject.Material().Shininess)).
							Multiply(closestObject.Material().Specular)

						if l.Dot(n) > 0 {
							illumination = illumination.Add(diffuseTerm)
						}

						if r.Dot(vv) > 0 {
							illumination = illumination.Add(specularTerm)
						}

					}

					fill := &image.Uniform{color.RGBA{
						illumination.R,
						illumination.G,
						illumination.B,
						illumination.A,
					}}

					draw.Draw(img, image.Rect(u, v, u+1, v+1), fill, image.ZP, draw.Src)
				}
				wg.Done()
			}(u, v)
		}
	}

	wg.Wait()

	err = png.Encode(out, img)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

}
<commit_msg>tweak scene<commit_after>package main

import . "./godray"

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"math"
	"os"
	"sync"
)

var i *Vector = &Vector{1, 0, 0}
var j *Vector = &Vector{0, 1, 0}
var k *Vector = &Vector{0, 0, 1}
var o *Point = &Point{0, 0, 0}

func getClosestIntersection(ray *Ray,
	objects []Object) (*Intersection, Object) {
	intersections := make([]*Intersection, len(objects))

	for i, object := range objects {
		point, dist, n := object.Intersect(ray)
		intersections[i] = &Intersection{point, dist, n}
	}

	var closestIntersection *Intersection
	var closestObject Object
	for i, intersection := range intersections {
		if closestIntersection == nil ||
			intersection.Distance < closestIntersection.Distance {
			closestIntersection = intersection
			closestObject = objects[i]
		}
	}

	return closestIntersection, closestObject
}

func main() {
	eye := o
	camera := NewCamera(eye.Add(k.Scale(10)), k.Scale(-1), j)
	screen := &Screen{800, 600, 45}

	// colors
	red := &Color{color.RGBA{255, 0, 0, 255}}
	green := &Color{color.RGBA{0, 255, 0, 255}}
	blue := &Color{color.RGBA{0, 0, 255, 255}}
	white := &Color{color.RGBA{255, 255, 255, 255}}
	black := &Color{color.RGBA{0, 0, 0, 255}}

	// lights
	lights := [...]*Light{
		&Light{
			&Point{0, 4, -4},
			white.Scale(0.1),
			white,
			white,
		},
		&Light{
			&Point{10, 4, 2},
			white.Scale(0.1),
			white,
			white,
		},
	}

	// objects
	objects := []Object{
		NewSphere(&Point{0, 0, -4}, 1, &Material{
			red,
			red,
			white,
			20,
		}),
		NewSphere(&Point{-2, 2, -4}, 1, &Material{
			green,
			green,
			white,
			20,
		}),
		NewSphere(&Point{2, -4.5, -4}, 3, &Material{
			blue,
			blue,
			white,
			20,
		}),
	}

	//hit := &Ray{&Point{0, 0, 0}, &Vector{-0.01, 0.01, -1}}
	//miss := &Ray{&Point{0, 5, 0}, &Vector{0, 0, -4}}
	//_, _, n := sphere.Intersect(hit)
	//intersection, t := sphere.Intersect(miss)
	//fmt.Println(n)

	out, err := os.Create("./output.png")
	if err != nil {
		os.Exit(1)
	}

	imgRect := image.Rect(0, 0, screen.Width, screen.Height)
	img := image.NewRGBA(imgRect)
	draw.Draw(img, img.Bounds(), &image.Uniform{color.Black}, image.ZP, draw.Src)

	//runtime.GOMAXPROCS(1)
	wg := sync.WaitGroup{}

	for u := 0; u < screen.Width; u++ {
		for v := 0; v < screen.Height; v++ {
			wg.Add(1)
			go func(u, v int) {
				ray := camera.GetRayTo(screen, u, v)

				closestIntersection, closestObject := getClosestIntersection(ray,
					objects)
				intersection := closestIntersection.Point
				n := closestIntersection.Normal

				if intersection != nil {
					var illumination *Color = black

					for _, light := range lights {
						illumination = illumination.Add(closestObject.Material().Ambient.
							Multiply(light.Ambient))

						l := light.Position.Subtract(intersection).Normalize()

						rayToLight := &Ray{
							intersection,
							l,
						}

						obstruction, _ := getClosestIntersection(rayToLight, objects)
						if obstruction.Point != nil {
							continue
						}

						r := n.Scale(2 * l.Dot(n)).Subtract(l)
						vv := ray.V.Normalize().Scale(-1)

						diffuseTerm := light.Diffuse.Scale(l.Dot(n)).
							Multiply(closestObject.Material().Diffuse)
						specularTerm := light.Specular.
							Scale(math.Pow(r.Dot(vv), closestObject.Material().Shininess)).
							Multiply(closestObject.Material().Specular)

						if l.Dot(n) > 0 {
							illumination = illumination.Add(diffuseTerm)
						}

						if r.Dot(vv) > 0 {
							illumination = illumination.Add(specularTerm)
						}

					}

					fill := &image.Uniform{color.RGBA{
						illumination.R,
						illumination.G,
						illumination.B,
						illumination.A,
					}}

					draw.Draw(img, image.Rect(u, v, u+1, v+1), fill, image.ZP, draw.Src)
				}
				wg.Done()
			}(u, v)
		}
	}

	wg.Wait()

	err = png.Encode(out, img)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/handler"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/models/configs"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/server"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/utils"
	"log"
	"runtime"
)

const (
	SERVER_CONFIG = "configs/server.json"
	MAX_PROCS     = 1
)

func main() {
	serverConfig := new(configs.Config)

	err := utils.FromFile(SERVER_CONFIG, &serverConfig)
	if err != nil {
		log.Panicf("can not init server config: %v", err)
	}

	serverConfig.Dir.SetDir()

	fmt.Printf("cpu: %v\n", MAX_PROCS)
	runtime.GOMAXPROCS(MAX_PROCS)

	httpServer := server.CreateServer(*serverConfig.GetServer())
	httpServer.Start(handler.CreateHandler(serverConfig.Dir.Path))
}
<commit_msg>change fmt to log<commit_after>package main

import (
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/handler"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/models/configs"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/server"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/utils"
	"log"
	"runtime"
)

const (
	SERVER_CONFIG = "configs/server.json"
	MAX_PROCS     = 1
)

func main() {
	serverConfig := new(configs.Config)

	err := utils.FromFile(SERVER_CONFIG, &serverConfig)
	if err != nil {
		log.Panicf("can not init server config: %v", err)
	}

	serverConfig.Dir.SetDir()

	log.Printf("cpu: %v\n", MAX_PROCS)
	runtime.GOMAXPROCS(MAX_PROCS)

	httpServer := server.CreateServer(*serverConfig.GetServer())
	httpServer.Start(handler.CreateHandler(serverConfig.Dir.Path))
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"time"
	"randomkeyword"
	"amazon"
	"products"
	"downloader"
	"ranker"
)

type Ranker func (*products.Product) *products.RankedProduct

var boughtProducts []string = nil

func main() {
	start := time.Now()
	for {
		log.Println("==================== SEARCHING FOR PURPLES ====================")

		/* Make a random search on amazon.com and read the image and product details urls from the html
		 * e.g.
                 *   {
		 *	imageUrl: "https://images-na.ssl-images-amazon.com/images/I/5188yugyWZL._AC_US160_.jpg",
		 *	productUrl: "https://www.amazon.com/Dealzip-Fashion-Octopus-Cthulhu-Knitting/dp/B00VFX2NTW/ref=sr_1_1?ie=UTF8&qid=1476899795&sr=8-1&keywords=random"
		 *   }
		 */
		productUrls := amazon.FindProducts();

		// Download the image referenced by the imageUrl above
		downloadedImages := downloadImages(productUrls)

		// Give the image a score based on how purple it is. Between 0 and 441 :)
		rankedProducts := rankProducts(ranker.RankProductBasedOnAmountOfPurpleInImage, downloadedImages)

		// Throw away any products that don't ship to Sweden
		buyableProducts := filterNonBuyableProducts(rankedProducts)

		// Throw away any products we've already bought
		unboughtBuyableProducts := filter(buyableProducts, productHasBeenBoughtBefore)

		// Find the unbought and buyable product with the highest purple-score
		highestRankedProduct := findHighestRankedProduct(unboughtBuyableProducts)

		if highestRankedProduct == nil {
			log.Println("Did not find a good enough product :( Will try again!")
		} else {
			// Buy the product!
			amazon.BuyProducts(highestRankedProduct)
			os.Exit(0)
		}
	}
	elapsed := time.Since(start)
	log.Printf("Running time %s", elapsed)
}

func downloadImages(toDownloadChannel <-chan *products.ProductUrls) <-chan *products.Product {
	outchan := make(chan *products.Product)
	go func() {
		for toDownload := range toDownloadChannel {
			imageFile, error := downloader.DownloadImage(toDownload.ImageUrl)
			if error == nil {
				product := &products.Product{toDownload, imageFile}
				outchan <- product
			} else {
				log.Printf("Unable to download image: %v\n", error)
			}
		}
		close(outchan)
		log.Println("Finished downloading images")
	}()
	return outchan;
}

func filter(c <-chan *products.ProductUrls, filter func(*products.ProductUrls)bool) <-chan *products.ProductUrls {
	output := make(chan *products.ProductUrls);
	go func() {
		for candidate := range c {
			if (filter(candidate)) {
				output <- candidate;
			}
		}
		close(output);
	}()
	return output;
}

func productHasBeenBoughtBefore(urls *products.ProductUrls) bool {
	if boughtProducts == nil {
		lines, error := randomkeyword.ReadLines("bought-products.txt")
		if error == nil {
			boughtProducts = lines
		} else {
			log.Fatalf("Unable to open bought products log: %v\n", error)
		}
	}

	return !stringInSlice(urls.Url.String(), boughtProducts);
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func rankProducts(ranker Ranker, toAnalyzeChannel <-chan *products.Product) <-chan *products.RankedProduct {
	outchan := make(chan *products.RankedProduct)
	go func() {
		for toAnalyze := range toAnalyzeChannel {
			rankedProduct := ranker(toAnalyze)
			//log.Printf("Ranking %s got me %v \n", toAnalyze.Urls.Url, rankedProduct)
			if rankedProduct != nil {
				log.Printf("Found a purple product! %s\n", rankedProduct.Product.Urls.Url)
				outchan <- rankedProduct
			}
		}

		close(outchan)
		log.Println("Finised ranking all products")
	}()
	return outchan;
}

func filterNonBuyableProducts(analyzedChannel <-chan *products.RankedProduct) <-chan *products.RankedProduct {
	outchan := make(chan *products.RankedProduct)
	go func() {
		var buffer []*products.RankedProduct

		for toCheckForBuyability := range analyzedChannel {
			log.Printf("Added %s to buyability queue\n", toCheckForBuyability.Product.Urls.Url)
			buffer = append(buffer, toCheckForBuyability)

			if len(buffer) >= 40 {
				log.Printf("Checking buyability of %d products\n", len(buffer))
				numberOfBuyableProducts := amazon.PutBuyableProductsOnChannel(buffer, outchan)
				log.Printf("Found %d buyable products\n", numberOfBuyableProducts)
				buffer = buffer[:0]
			}
		}

		if len(buffer) > 0 {
			log.Printf("Checking buyability of %d products\n", len(buffer))
			numberOfBuyableProducts := amazon.PutBuyableProductsOnChannel(buffer, outchan)
			log.Printf("Found %d buyable products\n", numberOfBuyableProducts)
		}

		close(outchan)
		log.Println("Finised filtering non-buyable products")
	}()

	return outchan;
}

func findHighestRankedProduct(buyableChannel <-chan *products.RankedProduct) *products.Product {
	highestRank := 0
	var highestRankedProduct *products.Product = nil

	for buyableRankedProduct := range buyableChannel {
		if buyableRankedProduct.Rank > highestRank {
			highestRank = buyableRankedProduct.Rank
			highestRankedProduct = buyableRankedProduct.Product

			log.Printf("Found new top product! %v ranked at %d\n", highestRankedProduct.Urls.Url, highestRank)
		}
	}
	log.Println("No more rankings to process")

	if highestRankedProduct != nil {
		log.Printf("I found %v which ranked at %d!", highestRankedProduct.Urls.Url, highestRank)
	}

	return highestRankedProduct
}

func cleanUp(products []*products.Product) {
	for _, product := range products {
		os.Remove(product.Image)
	}
	log.Printf("Removed %d images\n", len(products))
}
<commit_msg>More presentational cleanup<commit_after>package main

import (
	"log"
	"os"
	"time"
	"randomkeyword"
	"amazon"
	"products"
	"downloader"
	"ranker"
)

type Ranker func (*products.Product) *products.RankedProduct
var boughtProducts []string = nil

func main() {
	start := time.Now()
	for {
		log.Println("==================== SEARCHING FOR PURPLES ====================")

		/* Make a random search on amazon.com and read the image and product details urls from the html
		 * e.g.
                 *   {
		 *	imageUrl: "https://images-na.ssl-images-amazon.com/images/I/5188yugyWZL._AC_US160_.jpg",
		 *	productUrl: "https://www.amazon.com/Dealzip-Fashion-Octopus-Cthulhu-Knitting/dp/B00VFX2NTW/ref=sr_1_1?ie=UTF8&qid=1476899795&sr=8-1&keywords=random"
		 *   }
		 */
		productUrls := amazon.FindProducts();

		// Download the image referenced by the imageUrl above
		downloadedImages := downloadImages(productUrls)

		/* Give the image a score based on how purple it is. Between 0 and 441 :)
		 * The object above is extended with the rank:
		 *  {
		 *      imageUrl: ...,
		 *	productUrl: ...,
		 *	rank: 410
		 *  }
		 */
		rankedProducts := rankProducts(
			ranker.RankProductBasedOnAmountOfPurpleInImage,
			downloadedImages,
		)

		// Throw away any products that don't ship to Sweden
		buyableProducts := filterNonBuyableProducts(rankedProducts)

		// Throw away any products we've already bought
		unboughtBuyableProducts := filter(buyableProducts, productHasBeenBoughtBefore)

		// Find the unbought and buyable product with the highest purple-score
		highestRankedProduct := findHighestRankedProduct(unboughtBuyableProducts)

		if highestRankedProduct == nil {
			log.Println("Did not find a good enough product :( Will try again!")
		} else {
			// Buy the product!
			amazon.BuyProducts(highestRankedProduct)
			os.Exit(0)
		}
	}
	elapsed := time.Since(start)
	log.Printf("Running time %s", elapsed)
}

func downloadImages(toDownloadChannel <-chan *products.ProductUrls) <-chan *products.Product {
	outchan := make(chan *products.Product)
	go func() {
		for toDownload := range toDownloadChannel {
			imageFile, error := downloader.DownloadImage(toDownload.ImageUrl)
			if error == nil {
				product := &products.Product{toDownload, imageFile}
				outchan <- product
			} else {
				log.Printf("Unable to download image: %v\n", error)
			}
		}
		close(outchan)
		log.Println("Finished downloading images")
	}()
	return outchan;
}

func filter(c <-chan *products.ProductUrls, filter func(*products.ProductUrls)bool) <-chan *products.ProductUrls {
	output := make(chan *products.ProductUrls);
	go func() {
		for candidate := range c {
			if (filter(candidate)) {
				output <- candidate;
			}
		}
		close(output);
	}()
	return output;
}

func productHasBeenBoughtBefore(urls *products.ProductUrls) bool {
	if boughtProducts == nil {
		lines, error := randomkeyword.ReadLines("bought-products.txt")
		if error == nil {
			boughtProducts = lines
		} else {
			log.Fatalf("Unable to open bought products log: %v\n", error)
		}
	}

	return !stringInSlice(urls.Url.String(), boughtProducts);
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func rankProducts(ranker Ranker, toAnalyzeChannel <-chan *products.Product) <-chan *products.RankedProduct {
	outchan := make(chan *products.RankedProduct)
	go func() {
		for toAnalyze := range toAnalyzeChannel {
			rankedProduct := ranker(toAnalyze)
			//log.Printf("Ranking %s got me %v \n", toAnalyze.Urls.Url, rankedProduct)
			if rankedProduct != nil {
				log.Printf("Found a purple product! %s\n", rankedProduct.Product.Urls.Url)
				outchan <- rankedProduct
			}
		}

		close(outchan)
		log.Println("Finised ranking all products")
	}()
	return outchan;
}

func filterNonBuyableProducts(analyzedChannel <-chan *products.RankedProduct) <-chan *products.RankedProduct {
	outchan := make(chan *products.RankedProduct)
	go func() {
		var buffer []*products.RankedProduct

		for toCheckForBuyability := range analyzedChannel {
			log.Printf("Added %s to buyability queue\n", toCheckForBuyability.Product.Urls.Url)
			buffer = append(buffer, toCheckForBuyability)

			if len(buffer) >= 40 {
				log.Printf("Checking buyability of %d products\n", len(buffer))
				numberOfBuyableProducts := amazon.PutBuyableProductsOnChannel(buffer, outchan)
				log.Printf("Found %d buyable products\n", numberOfBuyableProducts)
				buffer = buffer[:0]
			}
		}

		if len(buffer) > 0 {
			log.Printf("Checking buyability of %d products\n", len(buffer))
			numberOfBuyableProducts := amazon.PutBuyableProductsOnChannel(buffer, outchan)
			log.Printf("Found %d buyable products\n", numberOfBuyableProducts)
		}

		close(outchan)
		log.Println("Finised filtering non-buyable products")
	}()

	return outchan;
}

func findHighestRankedProduct(buyableChannel <-chan *products.RankedProduct) *products.Product {
	highestRank := 0
	var highestRankedProduct *products.Product = nil

	for buyableRankedProduct := range buyableChannel {
		if buyableRankedProduct.Rank > highestRank {
			highestRank = buyableRankedProduct.Rank
			highestRankedProduct = buyableRankedProduct.Product

			log.Printf("Found new top product! %v ranked at %d\n", highestRankedProduct.Urls.Url, highestRank)
		}
	}
	log.Println("No more rankings to process")

	if highestRankedProduct != nil {
		log.Printf("I found %v which ranked at %d!", highestRankedProduct.Urls.Url, highestRank)
	}

	return highestRankedProduct
}

func cleanUp(products []*products.Product) {
	for _, product := range products {
		os.Remove(product.Image)
	}
	log.Printf("Removed %d images\n", len(products))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/siravan/fits"
	// "github.com/skelterjohn/go.matrix"
	"math"
	"os"
	"strconv"
)

type Position struct {
	x int
	y int
}

var datasets = []string{
	"../data/DTEEC_011417_1755_011562_1755_U01.fits",
	"../data/DTEEC_011844_1855_002812_1855_A01.fits",
	"../data/DTEEC_015985_2040_016262_2040_U01.fits",
	"../data/DTEEC_018854_1755_018920_1755_U01.fits",
	"../data/DTEEC_019045_1530_019322_1530_U01.fits",
	"../data/DTEEC_019612_1535_019678_1535_U01.fits",
	"../data/DTEEC_019757_1560_020034_1560_U01.fits",
	"../data/DTEEC_019823_1530_019889_1530_U01.fits",
	"../data/DTEEC_020324_1555_020390_1555_U01.fits",
	"../data/DTEEC_023957_1755_024023_1755_U01.fits",
	"../data/DTEEC_024234_1755_024300_1755_U01.fits",
	"../data/DTEEC_028011_2055_028288_2055_A01.fits",
	"../data/DTEEC_041277_2115_040776_2115_A01.fits",
}

var minval = -10000.0

func main() {
	cut := 1

	// fmt.Println(strconv.FormatFloat(3.1415, 'E', -1, 64))

	var dataset string
	if len(os.Args) == 2 {
		i, _ := strconv.Atoi(os.Args[1])
		dataset = datasets[i]
	} else {
		dataset = datasets[len(datasets)-1]
	}
	fmt.Println(dataset)

	reader, _ := os.Open(dataset)
	units, _ := fits.Open(reader)

	var shape [2]int
	shape[0] = units[0].Naxis[0] / cut
	shape[1] = units[0].Naxis[1] / cut
	startpos := Position{shape[0] / 2, shape[1] / 2}
	fmt.Println(shape, startpos)

	dtm := make([][]float64, shape[0])
	max_angles := make([][]float64, shape[0])

	good_pixels := 0

	for x := 0; x < shape[0]; x++ {
		dtm[x] = make([]float64, shape[1])
		max_angles[x] = make([]float64, shape[1])
		for y := 0; y < shape[1]; y++ {
			if val := units[0].FloatAt(y, x); val > minval {
				good_pixels++
				dtm[x][y] = val
				max_angles[x][y] = math.Inf(1)
			} else {
				dtm[x][y] = math.NaN()
				max_angles[x][y] = math.NaN()
			}
		}
	}
	fmt.Println(good_pixels)

	dijkstra(shape, &dtm, &max_angles, startpos)

	WriteArray(&max_angles, "zerp.csv")

}
<commit_msg>Go should work<commit_after>package main

import (
	"fmt"
	"github.com/siravan/fits"
	// "github.com/skelterjohn/go.matrix"
	"math"
	"os"
	"strconv"
	"strings"
)

type Position struct {
	x int
	y int
}

var datasets = []string{
	"../data/DTEEC_011417_1755_011562_1755_U01.fits",
	"../data/DTEEC_011844_1855_002812_1855_A01.fits",
	"../data/DTEEC_015985_2040_016262_2040_U01.fits",
	"../data/DTEEC_018854_1755_018920_1755_U01.fits",
	"../data/DTEEC_019045_1530_019322_1530_U01.fits",
	"../data/DTEEC_019612_1535_019678_1535_U01.fits",
	"../data/DTEEC_019757_1560_020034_1560_U01.fits",
	"../data/DTEEC_019823_1530_019889_1530_U01.fits",
	"../data/DTEEC_020324_1555_020390_1555_U01.fits",
	"../data/DTEEC_023957_1755_024023_1755_U01.fits",
	"../data/DTEEC_024234_1755_024300_1755_U01.fits",
	"../data/DTEEC_028011_2055_028288_2055_A01.fits",
	"../data/DTEEC_041277_2115_040776_2115_A01.fits",
}

var minval = -10000.0

func main() {
	cut := 1

	// fmt.Println(strconv.FormatFloat(3.1415, 'E', -1, 64))

	var dataset string
	if len(os.Args) == 2 {
		i, _ := strconv.Atoi(os.Args[1])
		dataset = datasets[i]
	} else {
		dataset = datasets[len(datasets)-1]
	}
	fmt.Println(dataset)

	reader, _ := os.Open(dataset)
	units, _ := fits.Open(reader)

	var shape [2]int
	shape[0] = units[0].Naxis[0] / cut
	shape[1] = units[0].Naxis[1] / cut
	startpos := Position{shape[0] / 2, shape[1] / 2}
	fmt.Println(shape, startpos)

	dtm := make([][]float64, shape[0])
	max_angles := make([][]float64, shape[0])

	good_pixels := 0

	for x := 0; x < shape[0]; x++ {
		dtm[x] = make([]float64, shape[1])
		max_angles[x] = make([]float64, shape[1])
		for y := 0; y < shape[1]; y++ {
			if val := units[0].FloatAt(y, x); val > minval {
				good_pixels++
				dtm[x][y] = val
				max_angles[x][y] = math.Inf(1)
			} else {
				dtm[x][y] = math.NaN()
				max_angles[x][y] = math.NaN()
			}
		}
	}
	fmt.Println(good_pixels)

	dijkstra(shape, &dtm, &max_angles, startpos)

	WriteArray(&max_angles, strings.Replace(dataset, ".fits", ".csv", 1))

}
<|endoftext|>


<commit_before><commit_msg>[mmutex] Set the max interval for lock acquisition to one second<commit_after><|endoftext|>


<commit_before>package api

import (
	"github.com/cloudfoundry/cli/cf/errors"
	"github.com/cloudfoundry/cli/cf/models"
	"time"
)

type FakeAppInstancesRepo struct {
	GetInstancesAppGuid    string
	GetInstancesResponses  [][]models.AppInstanceFields
	GetInstancesErrorCodes []string
}

func (repo *FakeAppInstancesRepo) GetInstances(appGuid string) (instances []models.AppInstanceFields, apiErr error) {
	repo.GetInstancesAppGuid = appGuid
	time.Sleep(1 * time.Millisecond) //needed for Windows only, otherwise it thinks error codes are not assigned

	if len(repo.GetInstancesResponses) > 0 {
		instances = repo.GetInstancesResponses[0]
		repo.GetInstancesResponses = repo.GetInstancesResponses[1:]
	}

	if len(repo.GetInstancesErrorCodes) > 0 {
		errorCode := repo.GetInstancesErrorCodes[0]
		repo.GetInstancesErrorCodes = repo.GetInstancesErrorCodes[1:]
		if errorCode != "" {
			apiErr = errors.NewHttpError(400, errorCode, "Error staging app")
		}
	}

	return
}
<commit_msg>FakeAppInstancesRepo should be easier to use<commit_after>package api

import (
	"time"

	"github.com/cloudfoundry/cli/cf/errors"
	"github.com/cloudfoundry/cli/cf/models"
)

type FakeAppInstancesRepo struct {
	GetInstancesAppGuid    string
	GetInstancesResponses  [][]models.AppInstanceFields
	GetInstancesErrorCodes []string
}

func (repo *FakeAppInstancesRepo) GetInstances(appGuid string) (instances []models.AppInstanceFields, apiErr error) {
	repo.GetInstancesAppGuid = appGuid
	time.Sleep(1 * time.Millisecond) //needed for Windows only, otherwise it thinks error codes are not assigned

	if len(repo.GetInstancesResponses) > 0 {
		instances = repo.GetInstancesResponses[0]

		if len(repo.GetInstancesResponses) > 1 {
			repo.GetInstancesResponses = repo.GetInstancesResponses[1:]
		}
	}

	if len(repo.GetInstancesErrorCodes) > 0 {
		errorCode := repo.GetInstancesErrorCodes[0]

		// don't slice away the last one if this is all we have
		if len(repo.GetInstancesErrorCodes) > 1 {
			repo.GetInstancesErrorCodes = repo.GetInstancesErrorCodes[1:]
		}

		if errorCode != "" {
			apiErr = errors.NewHttpError(400, errorCode, "Error staging app")
		}
	}

	return
}
<|endoftext|>


<commit_before>package aqua

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/carbocation/interpose"
	"github.com/gorilla/mux"
	"github.com/tolexo/aero/activity"
	"github.com/tolexo/aero/auth"
	"github.com/tolexo/aero/cache"
	"github.com/tolexo/aero/conf"
	monit "github.com/tolexo/aero/monit"
	"github.com/tolexo/aero/panik"
)

type endPoint struct {
	caller     MethodInvoker
	info       Fixture
	httpMethod string

	isStdHttpHandler bool
	needsJarInput    bool

	muxUrl    string
	muxVars   []string
	modules   []func(http.Handler) http.Handler
	stash     cache.Cacher
	serviceId string
}

func NewEndPoint(inv MethodInvoker, f Fixture, matchUrl string, httpMethod string, mods map[string]func(http.Handler) http.Handler,
	caches map[string]cache.Cacher, serviceId string) endPoint {

	out := endPoint{
		caller:           inv,
		info:             f,
		isStdHttpHandler: false,
		needsJarInput:    false,
		muxUrl:           matchUrl,
		muxVars:          extractRouteVars(matchUrl),
		httpMethod:       httpMethod,
		modules:          make([]func(http.Handler) http.Handler, 0),
		stash:            nil,
		serviceId:        serviceId,
	}

	if f.Stub == "" {
		out.isStdHttpHandler = out.signatureMatchesDefaultHttpHandler()
		out.needsJarInput = out.needsVariableJar()

		out.validateMuxVarsMatchFuncInputs()
		out.validateFuncInputsAreOfRightType()
		out.validateFuncOutputsAreCorrect()
	}

	// Tag modules used by this endpoint
	if mods != nil && f.Modules != "" {
		names := strings.Split(f.Modules, ",")
		out.modules = make([]func(http.Handler) http.Handler, 0)
		for _, name := range names {
			name = strings.TrimSpace(name)
			fn, found := mods[name]
			if !found {
				panic(fmt.Sprintf("Module:%s not found", name))
			}
			out.modules = append(out.modules, fn)
		}
	}

	// Tag the cache
	if c, ok := caches[f.Cache]; ok {
		out.stash = c
	} else if f.Cache != "" {
		panic("Cache not found: " + f.Cache + " for " + matchUrl)
	}

	return out
}

func (me *endPoint) signatureMatchesDefaultHttpHandler() bool {
	return me.caller.outCount == 0 &&
		me.caller.inpCount == 2 &&
		me.caller.inpParams[0] == "i:net/http.ResponseWriter" &&
		me.caller.inpParams[1] == "*st:net/http.Request"
}

func (me *endPoint) needsVariableJar() bool {
	// needs jar input as the last parameter
	for i := 0; i < len(me.caller.inpParams)-1; i++ {
		if me.caller.inpParams[i] == "st:github.com/tolexo/aqua.Jar" {
			panic("Jar parameter should be the last one: " + me.caller.name)
		}
	}
	return me.caller.inpCount > 0 && me.caller.inpParams[me.caller.inpCount-1] == "st:github.com/tolexo/aqua.Jar"
}

func (me *endPoint) validateMuxVarsMatchFuncInputs() {
	// for non-standard http handlers, the mux vars count should match
	// the count of inputs to the user's method
	if !me.isStdHttpHandler {
		inputs := me.caller.inpCount
		if me.needsJarInput {
			inputs += -1
		}
		if len(me.muxVars) != inputs {
			panic(fmt.Sprintf("%s has %d inputs, but the func (%s) has %d",
				me.muxUrl, len(me.muxVars), me.caller.name, inputs))
		}
	}
}

func (me *endPoint) validateFuncInputsAreOfRightType() {
	if !me.isStdHttpHandler {
		for _, s := range me.caller.inpParams {
			switch s {
			case "st:github.com/tolexo/aqua.Jar":
			case "int":
			case "string":
			default:
				panic("Func input params should be 'int' or 'string'. Observed: " + s + " in: " + me.caller.name)
			}
		}
	}
}

func (me *endPoint) validateFuncOutputsAreCorrect() {

	var accepts = make(map[string]bool)
	accepts["string"] = true
	accepts["map"] = true
	accepts["st:github.com/tolexo/aqua.Sac"] = true
	accepts["*st:github.com/tolexo/aqua.Sac"] = true

	if !me.isStdHttpHandler {
		switch me.caller.outCount {
		case 1:
			_, found := accepts[me.caller.outParams[0]]
			if !found && !strings.HasPrefix(me.caller.outParams[0], "st:") {
				fmt.Println(me.caller.outParams[0])
				panic("Incorrect return type found in: " + me.caller.name)
			}
		case 2:
			if me.caller.outParams[0] != "int" {
				panic("When a func returns two params, the first must be an int (http status code) : " + me.caller.name)
			}
			_, found := accepts[me.caller.outParams[1]]
			if !found && !strings.HasPrefix(me.caller.outParams[1], "st:") {
				panic("Incorrect return type for second return param found in: " + me.caller.name)
			}
		default:
			panic("Incorrect number of returns for Func: " + me.caller.name)
		}
	}
}

// func middleman(next http.Handler) http.Handler {
// 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 		fmt.Println("In the middle >>>>")
// 		next.ServeHTTP(w, r)
// 		fmt.Println("And leaving middle <<<<")
// 	})
// }

func (me *endPoint) setupMuxHandlers(mux *mux.Router) {

	fn := handleIncoming(me)

	m := interpose.New()
	for i, _ := range me.modules {
		m.Use(me.modules[i])
		//fmt.Println("using module:", me.modules[i], reflect.TypeOf(me.modules[i]))
	}
	m.UseHandler(http.HandlerFunc(fn))

	if me.info.Version == "*" {
		mux.Handle(me.muxUrl, m).Methods(me.httpMethod)
	} else {
		urlWithVersion := cleanUrl(me.info.Prefix, "v"+me.info.Version, me.muxUrl)
		urlWithoutVersion := cleanUrl(me.info.Prefix, me.muxUrl)

		// versioned url
		mux.Handle(urlWithVersion, m).Methods(me.httpMethod)

		// content type (style1)
		header1 := fmt.Sprintf("application/%s-v%s+json", me.info.Vendor, me.info.Version)
		mux.Handle(urlWithoutVersion, m).Methods(me.httpMethod).Headers("Accept", header1)

		// content type (style2)
		header2 := fmt.Sprintf("application/%s+json;version=%s", me.info.Vendor, me.info.Version)
		mux.Handle(urlWithoutVersion, m).Methods(me.httpMethod).Headers("Accept", header2)
	}
}

//Copy request body
func copyReqBody(reqBody io.ReadCloser) (originalBody io.ReadCloser, copyBody interface{}) {
	bodyByte, _ := ioutil.ReadAll(reqBody)
	copyBody = string(bodyByte)
	originalBody = ioutil.NopCloser(bytes.NewBuffer(bodyByte))
	return
}

func handleIncoming(e *endPoint) func(http.ResponseWriter, *http.Request) {

	// return stub
	if e.info.Stub != "" {
		return func(w http.ResponseWriter, r *http.Request) {
			d, err := getContent(e.info.Stub)
			if err == nil {
				fmt.Fprintf(w, "%s", d)
			} else {
				w.WriteHeader(400)
				fmt.Fprintf(w, "{ message: \"%s\"}", "Stub path not found")
			}
		}
	}

	return func(w http.ResponseWriter, r *http.Request) {

		// cacheHit := false

		// TODO: create less local variables
		// TODO: move vars to closure level

		var out []reflect.Value
		//TODO: capture this using instrumentation handler

		var body interface{}
		logActivity := conf.Bool("log_activity", false)
		if logActivity == true {
			r.Body, body = copyReqBody(r.Body)
		}
		defer func(reqStartTime time.Time) {
			var (
				response     interface{}
				responseCode int64 = 200
			)
			respTime := time.Since(reqStartTime).Seconds() * 1000
			if out != nil && len(out) == 2 && e.caller.outParams[0] == "int" {
				responseCode = out[0].Int()
			}
			/*
				go func() {
					if e.serviceId != "" {
						monitorParams := monit.MonitorParams{
							ServiceId:    e.serviceId,
							RespTime:     respTime,
							ResponseCode: responseCode,
							CacheHit:     cacheHit,
						}
						monit.MonitorMe(monitorParams)
					}
				}()
			*/

			//User Activity logger start
			if logActivity == true {
				if out != nil {
					outLen := len(out)
					if outLen > 1 {
						response = out[1].Interface()
					} else if outLen > 0 {
						response = out[0].Interface()
					}
				}
				activity.LogActivity(r.RequestURI+" "+e.serviceId, body, response,
					int(responseCode), respTime)
			}
			//User Activity logger end

			if reqR := recover(); reqR != nil {
				monit.PanicLogger(reqR, e.serviceId, r.RequestURI, time.Now())
			}
		}(time.Now())

		//check authentication
		if e.info.Auth != "" {
			ok, errMsg := auth.AuthenticateRequest(r, e.info.Auth)
			if !ok { //print authentication error
				w.WriteHeader(401)
				w.Header().Set("Content-Type", "application/json")
				w.Header().Set("Content-Length", strconv.Itoa(len(errMsg)))
				fmt.Fprintf(w, "%s", errMsg)
				return
			}
		}

		var useCache bool = false
		var ttl time.Duration = 0 * time.Second
		var val []byte
		var err error

		if e.info.Ttl != "" {
			ttl, err = time.ParseDuration(e.info.Ttl)
			panik.On(err)
		}
		useCache = r.Method == "GET" && ttl > 0 && e.stash != nil

		muxVals := mux.Vars(r)
		params := make([]string, len(e.muxVars))
		for i, v := range e.muxVars {
			params[i] = muxVals[v]
		}

		if e.isStdHttpHandler {
			//TODO: caching of standard handler
			e.caller.Do([]reflect.Value{reflect.ValueOf(w), reflect.ValueOf(r)})
		} else {
			ref := convertToType(params, e.caller.inpParams)
			if e.needsJarInput {
				ref = append(ref, reflect.ValueOf(NewJar(r)))
			}

			if useCache {
				val, err = e.stash.Get(r.RequestURI)
				if err == nil {
					// cacheHit = true
					// fmt.Print(".")
					out = decomposeCachedValues(val, e.caller.outParams)
				} else {
					out = e.caller.Do(ref)
					if len(out) == 2 && e.caller.outParams[0] == "int" {
						code := out[0].Int()
						if code < 200 || code > 299 {
							useCache = false
						}
					}
					if useCache {
						bytes := prepareForCaching(out, e.caller.outParams)
						e.stash.Set(r.RequestURI, bytes, ttl)
						// fmt.Print(":", len(bytes), r.RequestURI)
					}

				}
			} else {
				out = e.caller.Do(ref)
				// fmt.Print("!")
			}
			writeOutput(w, e.caller.outParams, out, e.info.Pretty)
		}
	}
}

func prepareForCaching(r []reflect.Value, outputParams []string) []byte {

	var err error
	buf := new(bytes.Buffer)
	encd := json.NewEncoder(buf)

	for i, _ := range r {
		switch outputParams[i] {
		case "int":
			err = encd.Encode(r[i].Int())
			panik.On(err)
		case "map":
			err = encd.Encode(r[i].Interface().(map[string]interface{}))
			panik.On(err)
		case "string":
			err = encd.Encode(r[i].String())
			panik.On(err)
		case "*st:github.com/tolexo/aqua.Sac":
			err = encd.Encode(r[i].Elem().Interface().(Sac).Data)
		default:
			panic("Unknown type of output to be sent to endpoint cache: " + outputParams[i])
		}
	}

	return buf.Bytes()
}

func decomposeCachedValues(data []byte, outputParams []string) []reflect.Value {

	var err error
	buf := bytes.NewBuffer(data)
	decd := json.NewDecoder(buf)
	out := make([]reflect.Value, len(outputParams))

	for i, o := range outputParams {
		switch o {
		case "int":
			var j int
			err = decd.Decode(&j)
			panik.On(err)
			out[i] = reflect.ValueOf(j)
		case "map":
			var m map[string]interface{}
			err = decd.Decode(&m)
			panik.On(err)
			out[i] = reflect.ValueOf(m)
		case "string":
			var s string
			err = decd.Decode(&s)
			panik.On(err)
			out[i] = reflect.ValueOf(s)
		case "*st:github.com/tolexo/aqua.Sac":
			var m map[string]interface{}
			err = decd.Decode(&m)
			panik.On(err)
			s := NewSac()
			s.Data = m
			out[i] = reflect.ValueOf(s)
		default:
			panic("Unknown type of output to be decoded from endpoint cache:" + o)
		}
	}

	return out

}
<commit_msg>PRA-410: if json unmarsh error change to string<commit_after>package aqua

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/carbocation/interpose"
	"github.com/gorilla/mux"
	"github.com/tolexo/aero/activity"
	"github.com/tolexo/aero/auth"
	"github.com/tolexo/aero/cache"
	"github.com/tolexo/aero/conf"
	monit "github.com/tolexo/aero/monit"
	"github.com/tolexo/aero/panik"
)

type endPoint struct {
	caller     MethodInvoker
	info       Fixture
	httpMethod string

	isStdHttpHandler bool
	needsJarInput    bool

	muxUrl    string
	muxVars   []string
	modules   []func(http.Handler) http.Handler
	stash     cache.Cacher
	serviceId string
}

func NewEndPoint(inv MethodInvoker, f Fixture, matchUrl string, httpMethod string, mods map[string]func(http.Handler) http.Handler,
	caches map[string]cache.Cacher, serviceId string) endPoint {

	out := endPoint{
		caller:           inv,
		info:             f,
		isStdHttpHandler: false,
		needsJarInput:    false,
		muxUrl:           matchUrl,
		muxVars:          extractRouteVars(matchUrl),
		httpMethod:       httpMethod,
		modules:          make([]func(http.Handler) http.Handler, 0),
		stash:            nil,
		serviceId:        serviceId,
	}

	if f.Stub == "" {
		out.isStdHttpHandler = out.signatureMatchesDefaultHttpHandler()
		out.needsJarInput = out.needsVariableJar()

		out.validateMuxVarsMatchFuncInputs()
		out.validateFuncInputsAreOfRightType()
		out.validateFuncOutputsAreCorrect()
	}

	// Tag modules used by this endpoint
	if mods != nil && f.Modules != "" {
		names := strings.Split(f.Modules, ",")
		out.modules = make([]func(http.Handler) http.Handler, 0)
		for _, name := range names {
			name = strings.TrimSpace(name)
			fn, found := mods[name]
			if !found {
				panic(fmt.Sprintf("Module:%s not found", name))
			}
			out.modules = append(out.modules, fn)
		}
	}

	// Tag the cache
	if c, ok := caches[f.Cache]; ok {
		out.stash = c
	} else if f.Cache != "" {
		panic("Cache not found: " + f.Cache + " for " + matchUrl)
	}

	return out
}

func (me *endPoint) signatureMatchesDefaultHttpHandler() bool {
	return me.caller.outCount == 0 &&
		me.caller.inpCount == 2 &&
		me.caller.inpParams[0] == "i:net/http.ResponseWriter" &&
		me.caller.inpParams[1] == "*st:net/http.Request"
}

func (me *endPoint) needsVariableJar() bool {
	// needs jar input as the last parameter
	for i := 0; i < len(me.caller.inpParams)-1; i++ {
		if me.caller.inpParams[i] == "st:github.com/tolexo/aqua.Jar" {
			panic("Jar parameter should be the last one: " + me.caller.name)
		}
	}
	return me.caller.inpCount > 0 && me.caller.inpParams[me.caller.inpCount-1] == "st:github.com/tolexo/aqua.Jar"
}

func (me *endPoint) validateMuxVarsMatchFuncInputs() {
	// for non-standard http handlers, the mux vars count should match
	// the count of inputs to the user's method
	if !me.isStdHttpHandler {
		inputs := me.caller.inpCount
		if me.needsJarInput {
			inputs += -1
		}
		if len(me.muxVars) != inputs {
			panic(fmt.Sprintf("%s has %d inputs, but the func (%s) has %d",
				me.muxUrl, len(me.muxVars), me.caller.name, inputs))
		}
	}
}

func (me *endPoint) validateFuncInputsAreOfRightType() {
	if !me.isStdHttpHandler {
		for _, s := range me.caller.inpParams {
			switch s {
			case "st:github.com/tolexo/aqua.Jar":
			case "int":
			case "string":
			default:
				panic("Func input params should be 'int' or 'string'. Observed: " + s + " in: " + me.caller.name)
			}
		}
	}
}

func (me *endPoint) validateFuncOutputsAreCorrect() {

	var accepts = make(map[string]bool)
	accepts["string"] = true
	accepts["map"] = true
	accepts["st:github.com/tolexo/aqua.Sac"] = true
	accepts["*st:github.com/tolexo/aqua.Sac"] = true

	if !me.isStdHttpHandler {
		switch me.caller.outCount {
		case 1:
			_, found := accepts[me.caller.outParams[0]]
			if !found && !strings.HasPrefix(me.caller.outParams[0], "st:") {
				fmt.Println(me.caller.outParams[0])
				panic("Incorrect return type found in: " + me.caller.name)
			}
		case 2:
			if me.caller.outParams[0] != "int" {
				panic("When a func returns two params, the first must be an int (http status code) : " + me.caller.name)
			}
			_, found := accepts[me.caller.outParams[1]]
			if !found && !strings.HasPrefix(me.caller.outParams[1], "st:") {
				panic("Incorrect return type for second return param found in: " + me.caller.name)
			}
		default:
			panic("Incorrect number of returns for Func: " + me.caller.name)
		}
	}
}

// func middleman(next http.Handler) http.Handler {
// 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 		fmt.Println("In the middle >>>>")
// 		next.ServeHTTP(w, r)
// 		fmt.Println("And leaving middle <<<<")
// 	})
// }

func (me *endPoint) setupMuxHandlers(mux *mux.Router) {

	fn := handleIncoming(me)

	m := interpose.New()
	for i, _ := range me.modules {
		m.Use(me.modules[i])
		//fmt.Println("using module:", me.modules[i], reflect.TypeOf(me.modules[i]))
	}
	m.UseHandler(http.HandlerFunc(fn))

	if me.info.Version == "*" {
		mux.Handle(me.muxUrl, m).Methods(me.httpMethod)
	} else {
		urlWithVersion := cleanUrl(me.info.Prefix, "v"+me.info.Version, me.muxUrl)
		urlWithoutVersion := cleanUrl(me.info.Prefix, me.muxUrl)

		// versioned url
		mux.Handle(urlWithVersion, m).Methods(me.httpMethod)

		// content type (style1)
		header1 := fmt.Sprintf("application/%s-v%s+json", me.info.Vendor, me.info.Version)
		mux.Handle(urlWithoutVersion, m).Methods(me.httpMethod).Headers("Accept", header1)

		// content type (style2)
		header2 := fmt.Sprintf("application/%s+json;version=%s", me.info.Vendor, me.info.Version)
		mux.Handle(urlWithoutVersion, m).Methods(me.httpMethod).Headers("Accept", header2)
	}
}

//Copy request body
func copyReqBody(reqBody io.ReadCloser) (originalBody io.ReadCloser, copyBody interface{}) {
	bodyByte, _ := ioutil.ReadAll(reqBody)
	if err := json.Unmarshal(bodyByte, &copyBody); err != nil {
		copyBody = string(bodyByte)
	}
	originalBody = ioutil.NopCloser(bytes.NewBuffer(bodyByte))
	return
}

func handleIncoming(e *endPoint) func(http.ResponseWriter, *http.Request) {

	// return stub
	if e.info.Stub != "" {
		return func(w http.ResponseWriter, r *http.Request) {
			d, err := getContent(e.info.Stub)
			if err == nil {
				fmt.Fprintf(w, "%s", d)
			} else {
				w.WriteHeader(400)
				fmt.Fprintf(w, "{ message: \"%s\"}", "Stub path not found")
			}
		}
	}

	return func(w http.ResponseWriter, r *http.Request) {

		// cacheHit := false

		// TODO: create less local variables
		// TODO: move vars to closure level

		var out []reflect.Value
		//TODO: capture this using instrumentation handler

		var body interface{}
		logActivity := conf.Bool("log_activity", false)
		if logActivity == true {
			r.Body, body = copyReqBody(r.Body)
		}
		defer func(reqStartTime time.Time) {
			var (
				response     interface{}
				responseCode int64 = 200
			)
			respTime := time.Since(reqStartTime).Seconds() * 1000
			if out != nil && len(out) == 2 && e.caller.outParams[0] == "int" {
				responseCode = out[0].Int()
			}
			/*
				go func() {
					if e.serviceId != "" {
						monitorParams := monit.MonitorParams{
							ServiceId:    e.serviceId,
							RespTime:     respTime,
							ResponseCode: responseCode,
							CacheHit:     cacheHit,
						}
						monit.MonitorMe(monitorParams)
					}
				}()
			*/

			//User Activity logger start
			if logActivity == true {
				if out != nil {
					outLen := len(out)
					if outLen > 1 {
						response = out[1].Interface()
					} else if outLen > 0 {
						response = out[0].Interface()
					}
				}
				activity.LogActivity(r.RequestURI+" "+e.serviceId, body, response,
					int(responseCode), respTime)
			}
			//User Activity logger end

			if reqR := recover(); reqR != nil {
				monit.PanicLogger(reqR, e.serviceId, r.RequestURI, time.Now())
			}
		}(time.Now())

		//check authentication
		if e.info.Auth != "" {
			ok, errMsg := auth.AuthenticateRequest(r, e.info.Auth)
			if !ok { //print authentication error
				w.WriteHeader(401)
				w.Header().Set("Content-Type", "application/json")
				w.Header().Set("Content-Length", strconv.Itoa(len(errMsg)))
				fmt.Fprintf(w, "%s", errMsg)
				return
			}
		}

		var useCache bool = false
		var ttl time.Duration = 0 * time.Second
		var val []byte
		var err error

		if e.info.Ttl != "" {
			ttl, err = time.ParseDuration(e.info.Ttl)
			panik.On(err)
		}
		useCache = r.Method == "GET" && ttl > 0 && e.stash != nil

		muxVals := mux.Vars(r)
		params := make([]string, len(e.muxVars))
		for i, v := range e.muxVars {
			params[i] = muxVals[v]
		}

		if e.isStdHttpHandler {
			//TODO: caching of standard handler
			e.caller.Do([]reflect.Value{reflect.ValueOf(w), reflect.ValueOf(r)})
		} else {
			ref := convertToType(params, e.caller.inpParams)
			if e.needsJarInput {
				ref = append(ref, reflect.ValueOf(NewJar(r)))
			}

			if useCache {
				val, err = e.stash.Get(r.RequestURI)
				if err == nil {
					// cacheHit = true
					// fmt.Print(".")
					out = decomposeCachedValues(val, e.caller.outParams)
				} else {
					out = e.caller.Do(ref)
					if len(out) == 2 && e.caller.outParams[0] == "int" {
						code := out[0].Int()
						if code < 200 || code > 299 {
							useCache = false
						}
					}
					if useCache {
						bytes := prepareForCaching(out, e.caller.outParams)
						e.stash.Set(r.RequestURI, bytes, ttl)
						// fmt.Print(":", len(bytes), r.RequestURI)
					}

				}
			} else {
				out = e.caller.Do(ref)
				// fmt.Print("!")
			}
			writeOutput(w, e.caller.outParams, out, e.info.Pretty)
		}
	}
}

func prepareForCaching(r []reflect.Value, outputParams []string) []byte {

	var err error
	buf := new(bytes.Buffer)
	encd := json.NewEncoder(buf)

	for i, _ := range r {
		switch outputParams[i] {
		case "int":
			err = encd.Encode(r[i].Int())
			panik.On(err)
		case "map":
			err = encd.Encode(r[i].Interface().(map[string]interface{}))
			panik.On(err)
		case "string":
			err = encd.Encode(r[i].String())
			panik.On(err)
		case "*st:github.com/tolexo/aqua.Sac":
			err = encd.Encode(r[i].Elem().Interface().(Sac).Data)
		default:
			panic("Unknown type of output to be sent to endpoint cache: " + outputParams[i])
		}
	}

	return buf.Bytes()
}

func decomposeCachedValues(data []byte, outputParams []string) []reflect.Value {

	var err error
	buf := bytes.NewBuffer(data)
	decd := json.NewDecoder(buf)
	out := make([]reflect.Value, len(outputParams))

	for i, o := range outputParams {
		switch o {
		case "int":
			var j int
			err = decd.Decode(&j)
			panik.On(err)
			out[i] = reflect.ValueOf(j)
		case "map":
			var m map[string]interface{}
			err = decd.Decode(&m)
			panik.On(err)
			out[i] = reflect.ValueOf(m)
		case "string":
			var s string
			err = decd.Decode(&s)
			panik.On(err)
			out[i] = reflect.ValueOf(s)
		case "*st:github.com/tolexo/aqua.Sac":
			var m map[string]interface{}
			err = decd.Decode(&m)
			panik.On(err)
			s := NewSac()
			s.Data = m
			out[i] = reflect.ValueOf(s)
		default:
			panic("Unknown type of output to be decoded from endpoint cache:" + o)
		}
	}

	return out

}
<|endoftext|>


<commit_before>// service for exchanging current user settings with UI
package settings

import (
	"net/http"
	"sync"

	"github.com/getlantern/flashlight/analytics"
	"github.com/getlantern/flashlight/config"

	"github.com/getlantern/flashlight/ui"
	"github.com/getlantern/golog"
)

const (
	messageType = `Settings`
)

var (
	log          = golog.LoggerFor("flashlight.settings")
	service      *ui.Service
	cfgMutex     sync.Mutex
	baseSettings *Settings
	httpClient   *http.Client
)

type Settings struct {
	Version    string
	BuildDate  string
	AutoReport bool
}

func Configure(cfg *config.Config, version, buildDate string) {
	cfgMutex.Lock()
	defer cfgMutex.Unlock()

	// base settings are always written
	baseSettings = &Settings{
		Version:    version,
		BuildDate:  buildDate,
		AutoReport: *cfg.AutoReport,
	}

	if service == nil {
		err := start(baseSettings)
		if err != nil {
			log.Errorf("Unable to register settings service: %q", err)
			return
		}
		go read()
	}
}

func start(baseSettings *Settings) error {
	var err error

	helloFn := func(write func(interface{}) error) error {
		log.Debugf("Sending Lantern settings to new client")
		return write(baseSettings)
	}

	service, err = ui.Register(messageType, nil, helloFn)
	return err
}

func read() {
	for msg := range service.In {
		settings := (msg).(map[string]interface{})

		cfgMutex.Lock()
		config.Update(func(updated *config.Config) error {
			autoReport := settings["autoReport"].(bool)
			if autoReport {
				analytics.StartService()
			} else {
				analytics.StopService()
			}
			baseSettings.AutoReport = autoReport
			*updated.AutoReport = autoReport
			return nil
		})
		cfgMutex.Unlock()
	}
}
<commit_msg>add separate mutex for settings configuration<commit_after>// service for exchanging current user settings with UI
package settings

import (
	"net/http"
	"sync"

	"github.com/getlantern/flashlight/analytics"
	"github.com/getlantern/flashlight/config"

	"github.com/getlantern/flashlight/ui"
	"github.com/getlantern/golog"
)

const (
	messageType = `Settings`
)

var (
	log          = golog.LoggerFor("flashlight.settings")
	service      *ui.Service
	cfgMutex     sync.Mutex
	startMutex   sync.Mutex
	baseSettings *Settings
	httpClient   *http.Client
)

type Settings struct {
	Version    string
	BuildDate  string
	AutoReport bool
}

func Configure(cfg *config.Config, version, buildDate string) {
	startMutex.Lock()

	// base settings are always written
	baseSettings = &Settings{
		Version:    version,
		BuildDate:  buildDate,
		AutoReport: *cfg.AutoReport,
	}

	if service == nil {
		err := start(baseSettings)
		if err != nil {
			log.Errorf("Unable to register settings service: %q", err)
			return
		}
		go read()
	}

	startMutex.Unlock()
}

func start(baseSettings *Settings) error {
	var err error

	helloFn := func(write func(interface{}) error) error {
		log.Debugf("Sending Lantern settings to new client")
		return write(baseSettings)
	}

	service, err = ui.Register(messageType, nil, helloFn)
	return err
}

func read() {
	for msg := range service.In {
		settings := (msg).(map[string]interface{})

		cfgMutex.Lock()
		config.Update(func(updated *config.Config) error {
			autoReport := settings["autoReport"].(bool)
			if autoReport {
				analytics.StartService()
			} else {
				analytics.StopService()
			}
			baseSettings.AutoReport = autoReport
			*updated.AutoReport = autoReport
			return nil
		})
		cfgMutex.Unlock()
	}
}
<|endoftext|>


<commit_before>// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package env

import "strings"

func toMap(env []string) map[string]string {
	r := map[string]string{}
	for _, e := range env {
		p := strings.SplitN(e, "=", 2)
		r[p[0]] = p[1]
	}
	return r
}
<commit_msg>fix: gofumpt<commit_after>//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package env

import "strings"

func toMap(env []string) map[string]string {
	r := map[string]string{}
	for _, e := range env {
		p := strings.SplitN(e, "=", 2)
		r[p[0]] = p[1]
	}
	return r
}
<|endoftext|>


<commit_before>package goutil

// Blatantly ripped from https://gobyexample.com/collection-functions
// Also added similar functions for integer arrays

// Index returns the first index of the target string `t`, or -1 if no match is found.
func Index(vs []string, t string) int {
	for i, v := range vs {
		if v == t {
			return i
		}
	}

	return -1
}

// Include returns `true` if the target string t is in the slice.
func Include(vs []string, t string) bool {
	return Index(vs, t) >= 0
}

// Any returns `true` if one of the strings in the slice satisfies the predicate `f`.
func Any(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if f(v) {
			return true
		}
	}

	return false
}

// All returns `true` if all of the strings in the slice satisfy the predicate `f`.
func All(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if !f(v) {
			return false
		}
	}

	return true
}

// Filter returns a new slice containing all strings in the slice that satisfy
// the predicate `f`.
func Filter(vs []string, f func(string) bool) []string {
	var vsf []string

	for _, v := range vs {
		if f(v) {
			vsf = append(vsf, v)
		}
	}

	return vsf
}

// Map returns a new slice containing the results of applying the function `f`
// to each string in the original slice.
func Map(vs []string, f func(string) string) []string {
	vsm := make([]string, len(vs))

	for i, v := range vs {
		vsm[i] = f(v)
	}

	return vsm
}
<commit_msg>doc: Remove misleading comment<commit_after>package goutil

// Blatantly ripped from https://gobyexample.com/collection-functions

// Index returns the first index of the target string `t`, or -1 if no match is found.
func Index(vs []string, t string) int {
	for i, v := range vs {
		if v == t {
			return i
		}
	}

	return -1
}

// Include returns `true` if the target string t is in the slice.
func Include(vs []string, t string) bool {
	return Index(vs, t) >= 0
}

// Any returns `true` if one of the strings in the slice satisfies the predicate `f`.
func Any(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if f(v) {
			return true
		}
	}

	return false
}

// All returns `true` if all of the strings in the slice satisfy the predicate `f`.
func All(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if !f(v) {
			return false
		}
	}

	return true
}

// Filter returns a new slice containing all strings in the slice that satisfy
// the predicate `f`.
func Filter(vs []string, f func(string) bool) []string {
	var vsf []string

	for _, v := range vs {
		if f(v) {
			vsf = append(vsf, v)
		}
	}

	return vsf
}

// Map returns a new slice containing the results of applying the function `f`
// to each string in the original slice.
func Map(vs []string, f func(string) string) []string {
	vsm := make([]string, len(vs))

	for i, v := range vs {
		vsm[i] = f(v)
	}

	return vsm
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package kubectl

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/kubernetes/pkg/kubectl/util/hash"
)

// SecretForTLSGeneratorV1 supports stable generation of a TLS secret.
type SecretForTLSGeneratorV1 struct {
	// Name is the name of this TLS secret.
	Name string
	// Key is the path to the user's private key.
	Key string
	// Cert is the path to the user's public key certificate.
	Cert string
	// AppendHash; if true, derive a hash from the Secret and append it to the name
	AppendHash bool
}

// Ensure it supports the generator pattern that uses parameter injection
var _ Generator = &SecretForTLSGeneratorV1{}

// Ensure it supports the generator pattern that uses parameters specified during construction
var _ StructuredGenerator = &SecretForTLSGeneratorV1{}

// Generate returns a secret using the specified parameters
func (s SecretForTLSGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
	err := ValidateParams(s.ParamNames(), genericParams)
	if err != nil {
		return nil, err
	}
	delegate := &SecretForTLSGeneratorV1{}
	hashParam, found := genericParams["append-hash"]
	if found {
		hashBool, isBool := hashParam.(bool)
		if !isBool {
			return nil, fmt.Errorf("expected bool, found :%v", hashParam)
		}
		delegate.AppendHash = hashBool
		delete(genericParams, "append-hash")
	}
	params := map[string]string{}
	for key, value := range genericParams {
		strVal, isString := value.(string)
		if !isString {
			return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
		}
		params[key] = strVal
	}
	delegate.Name = params["name"]
	delegate.Key = params["key"]
	delegate.Cert = params["cert"]
	return delegate.StructuredGenerate()
}

// StructuredGenerate outputs a secret object using the configured fields
func (s SecretForTLSGeneratorV1) StructuredGenerate() (runtime.Object, error) {
	if err := s.validate(); err != nil {
		return nil, err
	}
	tlsCrt, err := readFile(s.Cert)
	if err != nil {
		return nil, err
	}
	tlsKey, err := readFile(s.Key)
	if err != nil {
		return nil, err
	}
	secret := &v1.Secret{}
	secret.Name = s.Name
	secret.Type = v1.SecretTypeTLS
	secret.Data = map[string][]byte{}
	secret.Data[v1.TLSCertKey] = []byte(tlsCrt)
	secret.Data[v1.TLSPrivateKeyKey] = []byte(tlsKey)
	if s.AppendHash {
		h, err := hash.SecretHash(secret)
		if err != nil {
			return nil, err
		}
		secret.Name = fmt.Sprintf("%s-%s", secret.Name, h)
	}
	return secret, nil
}

// readFile just reads a file into a byte array.
func readFile(file string) ([]byte, error) {
	b, err := ioutil.ReadFile(file)
	if err != nil {
		return []byte{}, fmt.Errorf("Cannot read file %v, %v", file, err)
	}
	return b, nil
}

// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern
func (s SecretForTLSGeneratorV1) ParamNames() []GeneratorParam {
	return []GeneratorParam{
		{"name", true},
		{"key", true},
		{"cert", true},
		{"append-hash", false},
	}
}

// validate validates required fields are set to support structured generation
func (s SecretForTLSGeneratorV1) validate() error {
	// TODO: This is not strictly necessary. We can generate a self signed cert
	// if no key/cert is given. The only requiredment is that we either get both
	// or none. See test/e2e/ingress_utils for self signed cert generation.
	if len(s.Key) == 0 {
		return fmt.Errorf("key must be specified")
	}
	if len(s.Cert) == 0 {
		return fmt.Errorf("certificate must be specified")
	}
	if _, err := tls.LoadX509KeyPair(s.Cert, s.Key); err != nil {
		return fmt.Errorf("failed to load key pair %v", err)
	}
	// TODO: Add more validation.
	// 1. If the certificate contains intermediates, it is a valid chain.
	// 2. Format etc.
	return nil
}
<commit_msg>pkg/kubectl: fix spelling mistake<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package kubectl

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/kubernetes/pkg/kubectl/util/hash"
)

// SecretForTLSGeneratorV1 supports stable generation of a TLS secret.
type SecretForTLSGeneratorV1 struct {
	// Name is the name of this TLS secret.
	Name string
	// Key is the path to the user's private key.
	Key string
	// Cert is the path to the user's public key certificate.
	Cert string
	// AppendHash; if true, derive a hash from the Secret and append it to the name
	AppendHash bool
}

// Ensure it supports the generator pattern that uses parameter injection
var _ Generator = &SecretForTLSGeneratorV1{}

// Ensure it supports the generator pattern that uses parameters specified during construction
var _ StructuredGenerator = &SecretForTLSGeneratorV1{}

// Generate returns a secret using the specified parameters
func (s SecretForTLSGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
	err := ValidateParams(s.ParamNames(), genericParams)
	if err != nil {
		return nil, err
	}
	delegate := &SecretForTLSGeneratorV1{}
	hashParam, found := genericParams["append-hash"]
	if found {
		hashBool, isBool := hashParam.(bool)
		if !isBool {
			return nil, fmt.Errorf("expected bool, found :%v", hashParam)
		}
		delegate.AppendHash = hashBool
		delete(genericParams, "append-hash")
	}
	params := map[string]string{}
	for key, value := range genericParams {
		strVal, isString := value.(string)
		if !isString {
			return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
		}
		params[key] = strVal
	}
	delegate.Name = params["name"]
	delegate.Key = params["key"]
	delegate.Cert = params["cert"]
	return delegate.StructuredGenerate()
}

// StructuredGenerate outputs a secret object using the configured fields
func (s SecretForTLSGeneratorV1) StructuredGenerate() (runtime.Object, error) {
	if err := s.validate(); err != nil {
		return nil, err
	}
	tlsCrt, err := readFile(s.Cert)
	if err != nil {
		return nil, err
	}
	tlsKey, err := readFile(s.Key)
	if err != nil {
		return nil, err
	}
	secret := &v1.Secret{}
	secret.Name = s.Name
	secret.Type = v1.SecretTypeTLS
	secret.Data = map[string][]byte{}
	secret.Data[v1.TLSCertKey] = []byte(tlsCrt)
	secret.Data[v1.TLSPrivateKeyKey] = []byte(tlsKey)
	if s.AppendHash {
		h, err := hash.SecretHash(secret)
		if err != nil {
			return nil, err
		}
		secret.Name = fmt.Sprintf("%s-%s", secret.Name, h)
	}
	return secret, nil
}

// readFile just reads a file into a byte array.
func readFile(file string) ([]byte, error) {
	b, err := ioutil.ReadFile(file)
	if err != nil {
		return []byte{}, fmt.Errorf("Cannot read file %v, %v", file, err)
	}
	return b, nil
}

// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern
func (s SecretForTLSGeneratorV1) ParamNames() []GeneratorParam {
	return []GeneratorParam{
		{"name", true},
		{"key", true},
		{"cert", true},
		{"append-hash", false},
	}
}

// validate validates required fields are set to support structured generation
func (s SecretForTLSGeneratorV1) validate() error {
	// TODO: This is not strictly necessary. We can generate a self signed cert
	// if no key/cert is given. The only requirement is that we either get both
	// or none. See test/e2e/ingress_utils for self signed cert generation.
	if len(s.Key) == 0 {
		return fmt.Errorf("key must be specified")
	}
	if len(s.Cert) == 0 {
		return fmt.Errorf("certificate must be specified")
	}
	if _, err := tls.LoadX509KeyPair(s.Cert, s.Key); err != nil {
		return fmt.Errorf("failed to load key pair %v", err)
	}
	// TODO: Add more validation.
	// 1. If the certificate contains intermediates, it is a valid chain.
	// 2. Format etc.
	return nil
}
<|endoftext|>