<commit_before>/*
Copyright 2016 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 announced

import (
	"fmt"

	"github.com/golang/glog"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apimachinery"
	"k8s.io/apimachinery/pkg/apimachinery/registered"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/sets"
)

type SchemeFunc func(*runtime.Scheme) error
type VersionToSchemeFunc map[string]SchemeFunc

// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory.
type GroupVersionFactoryArgs struct {
	GroupName   string
	VersionName string

	AddToScheme SchemeFunc
}

// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory.
type GroupMetaFactoryArgs struct {
	GroupName              string
	VersionPreferenceOrder []string
	ImportPrefix           string

	RootScopedKinds sets.String // nil is allowed
	IgnoredKinds    sets.String // nil is allowed

	// May be nil if there are no internal objects.
	AddInternalObjectsToScheme SchemeFunc
}

// NewGroupMetaFactory builds the args for you. This is for if you're
// constructing a factory all at once and not using the registry.
func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory {
	gmf := &GroupMetaFactory{
		GroupArgs:   groupArgs,
		VersionArgs: map[string]*GroupVersionFactoryArgs{},
	}
	for v, f := range versions {
		gmf.VersionArgs[v] = &GroupVersionFactoryArgs{
			GroupName:   groupArgs.GroupName,
			VersionName: v,
			AddToScheme: f,
		}
	}
	return gmf
}

// Announce adds this Group factory to the global factory registry. It should
// only be called if you constructed the GroupMetaFactory yourself via
// NewGroupMetadFactory.
// Note that this will panic on an error, since it's expected that you'll be
// calling this at initialization time and any error is a result of a
// programmer importing the wrong set of packages. If this assumption doesn't
// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory
// yourself.
func (gmf *GroupMetaFactory) Announce(groupFactoryRegistry APIGroupFactoryRegistry) *GroupMetaFactory {
	if err := groupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil {
		panic(err)
	}
	return gmf
}

// GroupMetaFactory has the logic for actually assembling and registering a group.
//
// There are two ways of obtaining one of these.
// 1. You can announce your group and versions separately, and then let the
//    GroupFactoryRegistry assemble this object for you. (This allows group and
//    versions to be imported separately, without referencing each other, to
//    keep import trees small.)
// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement
//    for the old, bad way of doing things. You can then call .Announce() to
//    announce your constructed factory to any code that would like to do
//    things the new, better way.
//
// Note that GroupMetaFactory actually does construct GroupMeta objects, but
// currently it does so in a way that's very entangled with an
// APIRegistrationManager. It's a TODO item to cleanly separate that interface.
type GroupMetaFactory struct {
	GroupArgs *GroupMetaFactoryArgs
	// map of version name to version factory
	VersionArgs map[string]*GroupVersionFactoryArgs

	// assembled by Register()
	prioritizedVersionList []schema.GroupVersion
}

// Register constructs the finalized prioritized version list and sanity checks
// the announced group & versions. Then it calls register.
func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error {
	if gmf.GroupArgs == nil {
		return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs)
	}
	if len(gmf.VersionArgs) == 0 {
		return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName)
	}

	pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...)
	if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) {
		return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder)
	}
	prioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.GroupArgs.VersionPreferenceOrder {
		prioritizedVersions = append(
			prioritizedVersions,
			schema.GroupVersion{
				Group:   gmf.GroupArgs.GroupName,
				Version: v,
			},
		)
	}

	// Go through versions that weren't explicitly prioritized.
	unprioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.VersionArgs {
		if v.GroupName != gmf.GroupArgs.GroupName {
			return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName)
		}
		if pvSet.Has(v.VersionName) {
			pvSet.Delete(v.VersionName)
			continue
		}
		unprioritizedVersions = append(unprioritizedVersions, schema.GroupVersion{Group: v.GroupName, Version: v.VersionName})
	}
	if len(unprioritizedVersions) > 1 {
		glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions)
	}
	if pvSet.Len() != 0 {
		return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet)
	}
	prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...)
	m.RegisterVersions(prioritizedVersions)
	gmf.prioritizedVersionList = prioritizedVersions
	return nil
}

func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
	// the list of kinds that are scoped at the root of the api hierarchy
	// if a kind is not enumerated here, it is assumed to have a namespace scope
	rootScoped := sets.NewString()
	if gmf.GroupArgs.RootScopedKinds != nil {
		rootScoped = gmf.GroupArgs.RootScopedKinds
	}
	ignoredKinds := sets.NewString()
	if gmf.GroupArgs.IgnoredKinds != nil {
		ignoredKinds = gmf.GroupArgs.IgnoredKinds
	}

	return meta.NewDefaultRESTMapperFromScheme(
		externalVersions,
		groupMeta.InterfacesFor,
		gmf.GroupArgs.ImportPrefix,
		ignoredKinds,
		rootScoped,
		scheme,
	)
}

// Enable enables group versions that are allowed, adds methods to the scheme, etc.
func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	externalVersions := []schema.GroupVersion{}
	for _, v := range gmf.prioritizedVersionList {
		if !m.IsAllowedVersion(v) {
			continue
		}
		externalVersions = append(externalVersions, v)
		if err := m.EnableVersions(v); err != nil {
			return err
		}
		gmf.VersionArgs[v.Version].AddToScheme(scheme)
	}
	if len(externalVersions) == 0 {
		glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName)
		return nil
	}

	if gmf.GroupArgs.AddInternalObjectsToScheme != nil {
		gmf.GroupArgs.AddInternalObjectsToScheme(scheme)
	}

	preferredExternalVersion := externalVersions[0]
	accessor := meta.NewAccessor()

	groupMeta := &apimachinery.GroupMeta{
		GroupVersion:  preferredExternalVersion,
		GroupVersions: externalVersions,
		SelfLinker:    runtime.SelfLinker(accessor),
	}
	for _, v := range externalVersions {
		gvf := gmf.VersionArgs[v.Version]
		if err := groupMeta.AddVersionInterfaces(
			schema.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName},
			&meta.VersionInterfaces{
				ObjectConvertor:  scheme,
				MetadataAccessor: accessor,
			},
		); err != nil {
			return err
		}
	}
	groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor
	groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)

	if err := m.RegisterGroup(*groupMeta); err != nil {
		return err
	}
	return nil
}

// RegisterAndEnable is provided only to allow this code to get added in multiple steps.
// It's really bad that this is called in init() methods, but supporting this
// temporarily lets us do the change incrementally.
func (gmf *GroupMetaFactory) RegisterAndEnable(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	if err := gmf.Register(registry); err != nil {
		return err
	}
	if err := gmf.Enable(registry, scheme); err != nil {
		return err
	}

	return nil
}
<commit_msg>GroupMetaFactoryArgs documentation<commit_after>/*
Copyright 2016 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 announced

import (
	"fmt"

	"github.com/golang/glog"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apimachinery"
	"k8s.io/apimachinery/pkg/apimachinery/registered"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/sets"
)

type SchemeFunc func(*runtime.Scheme) error
type VersionToSchemeFunc map[string]SchemeFunc

// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory.
type GroupVersionFactoryArgs struct {
	GroupName   string
	VersionName string

	AddToScheme SchemeFunc
}

// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory.
type GroupMetaFactoryArgs struct {
	// GroupName is the name of the API-Group
	//
	// example: 'servicecatalog.k8s.io'
	GroupName              string
	VersionPreferenceOrder []string
	// ImportPrefix is the base go package of the API-Group
	//
	// example: 'k8s.io/kubernetes/pkg/apis/autoscaling'
	ImportPrefix string
	// RootScopedKinds are resources that are not namespaced.
	RootScopedKinds sets.String // nil is allowed
	IgnoredKinds    sets.String // nil is allowed

	// May be nil if there are no internal objects.
	AddInternalObjectsToScheme SchemeFunc
}

// NewGroupMetaFactory builds the args for you. This is for if you're
// constructing a factory all at once and not using the registry.
func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory {
	gmf := &GroupMetaFactory{
		GroupArgs:   groupArgs,
		VersionArgs: map[string]*GroupVersionFactoryArgs{},
	}
	for v, f := range versions {
		gmf.VersionArgs[v] = &GroupVersionFactoryArgs{
			GroupName:   groupArgs.GroupName,
			VersionName: v,
			AddToScheme: f,
		}
	}
	return gmf
}

// Announce adds this Group factory to the global factory registry. It should
// only be called if you constructed the GroupMetaFactory yourself via
// NewGroupMetadFactory.
// Note that this will panic on an error, since it's expected that you'll be
// calling this at initialization time and any error is a result of a
// programmer importing the wrong set of packages. If this assumption doesn't
// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory
// yourself.
func (gmf *GroupMetaFactory) Announce(groupFactoryRegistry APIGroupFactoryRegistry) *GroupMetaFactory {
	if err := groupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil {
		panic(err)
	}
	return gmf
}

// GroupMetaFactory has the logic for actually assembling and registering a group.
//
// There are two ways of obtaining one of these.
// 1. You can announce your group and versions separately, and then let the
//    GroupFactoryRegistry assemble this object for you. (This allows group and
//    versions to be imported separately, without referencing each other, to
//    keep import trees small.)
// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement
//    for the old, bad way of doing things. You can then call .Announce() to
//    announce your constructed factory to any code that would like to do
//    things the new, better way.
//
// Note that GroupMetaFactory actually does construct GroupMeta objects, but
// currently it does so in a way that's very entangled with an
// APIRegistrationManager. It's a TODO item to cleanly separate that interface.
type GroupMetaFactory struct {
	GroupArgs *GroupMetaFactoryArgs
	// map of version name to version factory
	VersionArgs map[string]*GroupVersionFactoryArgs

	// assembled by Register()
	prioritizedVersionList []schema.GroupVersion
}

// Register constructs the finalized prioritized version list and sanity checks
// the announced group & versions. Then it calls register.
func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error {
	if gmf.GroupArgs == nil {
		return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs)
	}
	if len(gmf.VersionArgs) == 0 {
		return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName)
	}

	pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...)
	if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) {
		return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder)
	}
	prioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.GroupArgs.VersionPreferenceOrder {
		prioritizedVersions = append(
			prioritizedVersions,
			schema.GroupVersion{
				Group:   gmf.GroupArgs.GroupName,
				Version: v,
			},
		)
	}

	// Go through versions that weren't explicitly prioritized.
	unprioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.VersionArgs {
		if v.GroupName != gmf.GroupArgs.GroupName {
			return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName)
		}
		if pvSet.Has(v.VersionName) {
			pvSet.Delete(v.VersionName)
			continue
		}
		unprioritizedVersions = append(unprioritizedVersions, schema.GroupVersion{Group: v.GroupName, Version: v.VersionName})
	}
	if len(unprioritizedVersions) > 1 {
		glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions)
	}
	if pvSet.Len() != 0 {
		return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet)
	}
	prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...)
	m.RegisterVersions(prioritizedVersions)
	gmf.prioritizedVersionList = prioritizedVersions
	return nil
}

func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
	// the list of kinds that are scoped at the root of the api hierarchy
	// if a kind is not enumerated here, it is assumed to have a namespace scope
	rootScoped := sets.NewString()
	if gmf.GroupArgs.RootScopedKinds != nil {
		rootScoped = gmf.GroupArgs.RootScopedKinds
	}
	ignoredKinds := sets.NewString()
	if gmf.GroupArgs.IgnoredKinds != nil {
		ignoredKinds = gmf.GroupArgs.IgnoredKinds
	}

	return meta.NewDefaultRESTMapperFromScheme(
		externalVersions,
		groupMeta.InterfacesFor,
		gmf.GroupArgs.ImportPrefix,
		ignoredKinds,
		rootScoped,
		scheme,
	)
}

// Enable enables group versions that are allowed, adds methods to the scheme, etc.
func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	externalVersions := []schema.GroupVersion{}
	for _, v := range gmf.prioritizedVersionList {
		if !m.IsAllowedVersion(v) {
			continue
		}
		externalVersions = append(externalVersions, v)
		if err := m.EnableVersions(v); err != nil {
			return err
		}
		gmf.VersionArgs[v.Version].AddToScheme(scheme)
	}
	if len(externalVersions) == 0 {
		glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName)
		return nil
	}

	if gmf.GroupArgs.AddInternalObjectsToScheme != nil {
		gmf.GroupArgs.AddInternalObjectsToScheme(scheme)
	}

	preferredExternalVersion := externalVersions[0]
	accessor := meta.NewAccessor()

	groupMeta := &apimachinery.GroupMeta{
		GroupVersion:  preferredExternalVersion,
		GroupVersions: externalVersions,
		SelfLinker:    runtime.SelfLinker(accessor),
	}
	for _, v := range externalVersions {
		gvf := gmf.VersionArgs[v.Version]
		if err := groupMeta.AddVersionInterfaces(
			schema.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName},
			&meta.VersionInterfaces{
				ObjectConvertor:  scheme,
				MetadataAccessor: accessor,
			},
		); err != nil {
			return err
		}
	}
	groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor
	groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)

	if err := m.RegisterGroup(*groupMeta); err != nil {
		return err
	}
	return nil
}

// RegisterAndEnable is provided only to allow this code to get added in multiple steps.
// It's really bad that this is called in init() methods, but supporting this
// temporarily lets us do the change incrementally.
func (gmf *GroupMetaFactory) RegisterAndEnable(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	if err := gmf.Register(registry); err != nil {
		return err
	}
	if err := gmf.Enable(registry, scheme); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/anthonynsimon/parrot/model"
	"github.com/gorilla/mux"
)

func CreateDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	projID, err := strconv.Atoi(mux.Vars(r)["projectID"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	doc := &model.Document{}
	if err := json.NewDecoder(r.Body).Decode(&doc); err != nil {
		return http.StatusBadRequest, err
	}

	doc.ProjectID = projID

	proj, err := store.GetProject(projID)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	doc.SyncKeys(proj.Keys, true)

	err = store.CreateDoc(doc)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, doc)
}

func ShowDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	projID, err := strconv.Atoi(mux.Vars(r)["projectID"])
	if err != nil {
		return http.StatusBadRequest, err
	}
	id, err := strconv.Atoi(mux.Vars(r)["id"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	doc, err := store.GetProjectDoc(projID, id)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, doc)
}

func UpdateDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	id, err := strconv.Atoi(mux.Vars(r)["id"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	doc := &model.Document{}
	if err := json.NewDecoder(r.Body).Decode(&doc.Pairs); err != nil {
		return http.StatusBadRequest, err
	}
	doc.ID = id

	err = store.UpdateDoc(doc)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, doc)
}

func DeleteDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	id, err := strconv.Atoi(mux.Vars(r)["id"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	resultID, err := store.DeleteDoc(id)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, map[string]interface{}{
		"message": fmt.Sprintf("deleted document with id %d", resultID),
	})
}
<commit_msg>Add not found err<commit_after>package api

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/anthonynsimon/parrot/model"
	"github.com/gorilla/mux"
)

func CreateDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	projID, err := strconv.Atoi(mux.Vars(r)["projectID"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	doc := &model.Document{}
	if err := json.NewDecoder(r.Body).Decode(&doc); err != nil {
		return http.StatusBadRequest, err
	}

	doc.ProjectID = projID

	proj, err := store.GetProject(projID)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	doc.SyncKeys(proj.Keys, true)

	err = store.CreateDoc(doc)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, doc)
}

func ShowDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	projID, err := strconv.Atoi(mux.Vars(r)["projectID"])
	if err != nil {
		return http.StatusBadRequest, err
	}
	id, err := strconv.Atoi(mux.Vars(r)["id"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	doc, err := store.GetProjectDoc(projID, id)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, doc)
}

func UpdateDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	id, err := strconv.Atoi(mux.Vars(r)["id"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	doc := &model.Document{}
	if err := json.NewDecoder(r.Body).Decode(&doc.Pairs); err != nil {
		return http.StatusBadRequest, err
	}
	doc.ID = id

	err = store.UpdateDoc(doc)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, doc)
}

func DeleteDocument(w http.ResponseWriter, r *http.Request) (int, error) {
	id, err := strconv.Atoi(mux.Vars(r)["id"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	resultID, err := store.DeleteDoc(id)
	if err != nil {
		if err == sql.ErrNoRows {
			return http.StatusNotFound, err
		}
		return http.StatusInternalServerError, err
	}

	return writeJSON(w, http.StatusOK, map[string]interface{}{
		"message": fmt.Sprintf("deleted document with id %d", resultID),
	})
}
<|endoftext|>


<commit_before>package management

import (
	"fmt"
	"os"
	"strings"

	v32 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"

	"github.com/rancher/rancher/pkg/controllers/management/drivers/kontainerdriver"
	v3 "github.com/rancher/rancher/pkg/generated/norman/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/types/config"
	"github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/api/errors"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func addKontainerDrivers(management *config.ManagementContext) error {
	// create binary drop location if not exists
	err := os.MkdirAll(kontainerdriver.DriverDir, 0777)
	if err != nil {
		return fmt.Errorf("error creating binary drop folder: %v", err)
	}

	creator := driverCreator{
		driversLister: management.Management.KontainerDrivers("").Controller().Lister(),
		drivers:       management.Management.KontainerDrivers(""),
	}

	if err := cleanupImportDriver(creator); err != nil {
		return err
	}

	if err := creator.add("rancherKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("googleKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("azureKubernetesService"); err != nil {
		return err
	}

	if err := creator.add("amazonElasticContainerService"); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"baiducloudcontainerengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/kontainer-engine-driver-baidu-linux",
		"4613e3be3ae5487b0e21dfa761b95de2144f80f98bf76847411e5fcada343d5e",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/component.js",
		false,
		"drivers.rancher.cn", "*.baidubce.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"aliyunkubernetescontainerservice",
		"https://drivers.rancher.cn/kontainer-engine-driver-aliyun/0.2.6/kontainer-engine-driver-aliyun-linux",
		"8a5360269ec803e3d8cf2c9cc94c66879da03a1fd2b580912c1a83454509c84c",
		"https://drivers.rancher.cn/pandaria/ui/cluster-driver-aliyun/0.1.1/component.js",
		false,
		"*.aliyuncs.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"tencentkubernetesengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-tencent/0.3.0/kontainer-engine-driver-tencent-linux",
		"ad5406502daf826874889963d7bdaed78db4689f147889ecf97394bc4e8d3d76",
		"",
		false,
		"*.tencentcloudapi.com", "*.qcloud.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"huaweicontainercloudengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-huawei/0.1.2/kontainer-engine-driver-huawei-linux",
		"0b6c1dfaa477a60a3bd9f8a60a55fcafd883866c2c5c387aec75b95d6ba81d45",
		"",
		false,
		"*.myhuaweicloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"oraclecontainerengine",
		"https://github.com/rancher-plugins/kontainer-engine-driver-oke/releases/download/v1.7.1/kontainer-engine-driver-oke-linux",
		"5a708bfc01c67558adc887258615900082263ca7d6f4160efb1a58501b0cc608",
		"",
		false,
		"*.oraclecloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"linodekubernetesengine",
		"https://github.com/linode/kontainer-engine-driver-lke/releases/download/v0.0.3/kontainer-engine-driver-lke-linux-amd64",
		"02fa95d24a1c6f9c520307e24a543c1777ed21fc3a4f060434e067806578e647",
		"",
		false,
		"api.linode.com",
	); err != nil {
		return err
	}

	return creator.addCustomDriver(
		"opentelekomcloudcontainerengine",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/driver/1.0.2/kontainer-engine-driver-otccce_linux_amd64.tar.gz",
		"f2c0a8d1195cd51ae1ccdeb4a8defd2c3147b9a2c7510b091be0c12028740f5f",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/ui/v1.1.0/component.js",
		false,
		"*.otc.t-systems.com",
	)
}

func cleanupImportDriver(creator driverCreator) error {
	var err error
	if _, err = creator.driversLister.Get("", "import"); err == nil {
		err = creator.drivers.Delete("import", &v1.DeleteOptions{})
	}

	if !errors.IsNotFound(err) {
		return err
	}

	return nil
}

type driverCreator struct {
	driversLister v3.KontainerDriverLister
	drivers       v3.KontainerDriverInterface
}

func (c *driverCreator) add(name string) error {
	logrus.Infof("adding kontainer driver %v", name)

	driver, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name:      strings.ToLower(name),
					Namespace: "",
				},
				Spec: v32.KontainerDriverSpec{
					URL:     "",
					BuiltIn: true,
					Active:  true,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	} else {
		driver.Spec.URL = ""

		_, err = c.drivers.Update(driver)
		if err != nil {
			return fmt.Errorf("error updating driver: %v", err)
		}
	}

	return nil
}

func (c *driverCreator) addCustomDriver(name, url, checksum, uiURL string, active bool, domains ...string) error {
	logrus.Infof("adding kontainer driver %v", name)
	_, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name: strings.ToLower(name),
				},
				Spec: v32.KontainerDriverSpec{
					URL:              url,
					BuiltIn:          false,
					Active:           active,
					Checksum:         checksum,
					UIURL:            uiURL,
					WhitelistDomains: domains,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	}
	return nil
}
<commit_msg>Bump kontainer-engine-driver-lke to v0.0.4 (#37081)<commit_after>package management

import (
	"fmt"
	"os"
	"strings"

	v32 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"

	"github.com/rancher/rancher/pkg/controllers/management/drivers/kontainerdriver"
	v3 "github.com/rancher/rancher/pkg/generated/norman/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/types/config"
	"github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/api/errors"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func addKontainerDrivers(management *config.ManagementContext) error {
	// create binary drop location if not exists
	err := os.MkdirAll(kontainerdriver.DriverDir, 0777)
	if err != nil {
		return fmt.Errorf("error creating binary drop folder: %v", err)
	}

	creator := driverCreator{
		driversLister: management.Management.KontainerDrivers("").Controller().Lister(),
		drivers:       management.Management.KontainerDrivers(""),
	}

	if err := cleanupImportDriver(creator); err != nil {
		return err
	}

	if err := creator.add("rancherKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("googleKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("azureKubernetesService"); err != nil {
		return err
	}

	if err := creator.add("amazonElasticContainerService"); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"baiducloudcontainerengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/kontainer-engine-driver-baidu-linux",
		"4613e3be3ae5487b0e21dfa761b95de2144f80f98bf76847411e5fcada343d5e",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/component.js",
		false,
		"drivers.rancher.cn", "*.baidubce.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"aliyunkubernetescontainerservice",
		"https://drivers.rancher.cn/kontainer-engine-driver-aliyun/0.2.6/kontainer-engine-driver-aliyun-linux",
		"8a5360269ec803e3d8cf2c9cc94c66879da03a1fd2b580912c1a83454509c84c",
		"https://drivers.rancher.cn/pandaria/ui/cluster-driver-aliyun/0.1.1/component.js",
		false,
		"*.aliyuncs.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"tencentkubernetesengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-tencent/0.3.0/kontainer-engine-driver-tencent-linux",
		"ad5406502daf826874889963d7bdaed78db4689f147889ecf97394bc4e8d3d76",
		"",
		false,
		"*.tencentcloudapi.com", "*.qcloud.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"huaweicontainercloudengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-huawei/0.1.2/kontainer-engine-driver-huawei-linux",
		"0b6c1dfaa477a60a3bd9f8a60a55fcafd883866c2c5c387aec75b95d6ba81d45",
		"",
		false,
		"*.myhuaweicloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"oraclecontainerengine",
		"https://github.com/rancher-plugins/kontainer-engine-driver-oke/releases/download/v1.7.1/kontainer-engine-driver-oke-linux",
		"5a708bfc01c67558adc887258615900082263ca7d6f4160efb1a58501b0cc608",
		"",
		false,
		"*.oraclecloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"linodekubernetesengine",
		"https://github.com/linode/kontainer-engine-driver-lke/releases/download/v0.0.4/kontainer-engine-driver-lke-linux-amd64",
		"5609314fe7ff7339a7c8292738d36ccf5a25460f79ca094db72eb6ccf722bc27",
		"",
		false,
		"api.linode.com",
	); err != nil {
		return err
	}

	return creator.addCustomDriver(
		"opentelekomcloudcontainerengine",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/driver/1.0.2/kontainer-engine-driver-otccce_linux_amd64.tar.gz",
		"f2c0a8d1195cd51ae1ccdeb4a8defd2c3147b9a2c7510b091be0c12028740f5f",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/ui/v1.1.0/component.js",
		false,
		"*.otc.t-systems.com",
	)
}

func cleanupImportDriver(creator driverCreator) error {
	var err error
	if _, err = creator.driversLister.Get("", "import"); err == nil {
		err = creator.drivers.Delete("import", &v1.DeleteOptions{})
	}

	if !errors.IsNotFound(err) {
		return err
	}

	return nil
}

type driverCreator struct {
	driversLister v3.KontainerDriverLister
	drivers       v3.KontainerDriverInterface
}

func (c *driverCreator) add(name string) error {
	logrus.Infof("adding kontainer driver %v", name)

	driver, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name:      strings.ToLower(name),
					Namespace: "",
				},
				Spec: v32.KontainerDriverSpec{
					URL:     "",
					BuiltIn: true,
					Active:  true,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	} else {
		driver.Spec.URL = ""

		_, err = c.drivers.Update(driver)
		if err != nil {
			return fmt.Errorf("error updating driver: %v", err)
		}
	}

	return nil
}

func (c *driverCreator) addCustomDriver(name, url, checksum, uiURL string, active bool, domains ...string) error {
	logrus.Infof("adding kontainer driver %v", name)
	_, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name: strings.ToLower(name),
				},
				Spec: v32.KontainerDriverSpec{
					URL:              url,
					BuiltIn:          false,
					Active:           active,
					Checksum:         checksum,
					UIURL:            uiURL,
					WhitelistDomains: domains,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 go-swagger maintainers
//
// 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 validate

import (
	"reflect"
	"regexp"
	"strings"

	"k8s.io/kube-openapi/pkg/validation/errors"
	"k8s.io/kube-openapi/pkg/validation/spec"
	"k8s.io/kube-openapi/pkg/validation/strfmt"
)

type objectValidator struct {
	Path                 string
	In                   string
	MaxProperties        *int64
	MinProperties        *int64
	Required             []string
	Properties           map[string]spec.Schema
	AdditionalProperties *spec.SchemaOrBool
	PatternProperties    map[string]spec.Schema
	Root                 interface{}
	KnownFormats         strfmt.Registry
	Options              SchemaValidatorOptions
}

func (o *objectValidator) SetPath(path string) {
	o.Path = path
}

func (o *objectValidator) Applies(source interface{}, kind reflect.Kind) bool {
	// TODO: this should also work for structs
	// there is a problem in the type validator where it will be unhappy about null values
	// so that requires more testing
	r := reflect.TypeOf(source) == specSchemaType && (kind == reflect.Map || kind == reflect.Struct)
	debugLog("object validator for %q applies %t for %T (kind: %v)\n", o.Path, r, source, kind)
	return r
}

func (o *objectValidator) isProperties() bool {
	p := strings.Split(o.Path, ".")
	return len(p) > 1 && p[len(p)-1] == jsonProperties && p[len(p)-2] != jsonProperties
}

func (o *objectValidator) isDefault() bool {
	p := strings.Split(o.Path, ".")
	return len(p) > 1 && p[len(p)-1] == jsonDefault && p[len(p)-2] != jsonDefault
}

func (o *objectValidator) isExample() bool {
	p := strings.Split(o.Path, ".")
	return len(p) > 1 && (p[len(p)-1] == swaggerExample || p[len(p)-1] == swaggerExamples) && p[len(p)-2] != swaggerExample
}

func (o *objectValidator) Validate(data interface{}) *Result {
	val := data.(map[string]interface{})
	// TODO: guard against nil data
	numKeys := int64(len(val))

	if o.MinProperties != nil && numKeys < *o.MinProperties {
		return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties))
	}
	if o.MaxProperties != nil && numKeys > *o.MaxProperties {
		return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties))
	}

	res := new(Result)

	// check validity of field names
	if o.AdditionalProperties != nil && !o.AdditionalProperties.Allows {
		// Case: additionalProperties: false
		for k := range val {
			_, regularProperty := o.Properties[k]
			matched := false

			for pk := range o.PatternProperties {
				if matches, _ := regexp.MatchString(pk, k); matches {
					matched = true
					break
				}
			}

			if !regularProperty && !matched {
				// Special properties "$schema" and "id" are ignored
				res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k))
			}
		}
	} else {
		// Cases: no additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <<schema>> }
		for key, value := range val {
			_, regularProperty := o.Properties[key]

			// Validates property against "patternProperties" if applicable
			// BUG(fredbi): succeededOnce is always false

			// NOTE: how about regular properties which do not match patternProperties?
			matched, succeededOnce, _ := o.validatePatternProperty(key, value, res)

			if !(regularProperty || matched || succeededOnce) {

				// Cases: properties which are not regular properties and have not been matched by the PatternProperties validator
				if o.AdditionalProperties != nil && o.AdditionalProperties.Schema != nil {
					// AdditionalProperties as Schema
					res.Merge(NewSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...).Validate(value))
				} else if regularProperty && !(matched || succeededOnce) {
					// TODO: this is dead code since regularProperty=false here
					res.AddErrors(errors.FailedAllPatternProperties(o.Path, o.In, key))
				}
			}
		}
		// Valid cases: additionalProperties: true or undefined
	}

	createdFromDefaults := map[string]bool{}

	// Property types:
	// - regular Property
	for pName, pSchema := range o.Properties {
		rName := pName
		if o.Path != "" {
			rName = o.Path + "." + pName
		}

		// Recursively validates each property against its schema
		if v, ok := val[pName]; ok {
			r := NewSchemaValidator(&pSchema, o.Root, rName, o.KnownFormats, o.Options.Options()...).Validate(v)
			res.Merge(r)
		}
	}

	// Check required properties
	if len(o.Required) > 0 {
		for _, k := range o.Required {
			if _, ok := val[k]; !ok && !createdFromDefaults[k] {
				res.AddErrors(errors.Required(o.Path+"."+k, o.In))
				continue
			}
		}
	}

	// Check patternProperties
	// TODO: it looks like we have done that twice in many cases
	for key, value := range val {
		_, regularProperty := o.Properties[key]
		matched, _ /*succeededOnce*/, patterns := o.validatePatternProperty(key, value, res)
		if !regularProperty && (matched /*|| succeededOnce*/) {
			for _, pName := range patterns {
				if v, ok := o.PatternProperties[pName]; ok {
					res.Merge(NewSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...).Validate(value))
				}
			}
		}
	}
	return res
}

// TODO: succeededOnce is not used anywhere
func (o *objectValidator) validatePatternProperty(key string, value interface{}, result *Result) (bool, bool, []string) {
	matched := false
	succeededOnce := false
	var patterns []string

	for k, schema := range o.PatternProperties {
		sch := schema
		if match, _ := regexp.MatchString(k, key); match {
			patterns = append(patterns, k)
			matched = true
			validator := NewSchemaValidator(&sch, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...)

			res := validator.Validate(value)
			result.Merge(res)
		}
	}

	// BUG(fredbi): can't get to here. Should remove dead code (commented out).

	//if succeededOnce {
	//	result.Inc()
	//}

	return matched, succeededOnce, patterns
}
<commit_msg>Remove unused code paths in object validator<commit_after>// Copyright 2015 go-swagger maintainers
//
// 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 validate

import (
	"reflect"
	"regexp"

	"k8s.io/kube-openapi/pkg/validation/errors"
	"k8s.io/kube-openapi/pkg/validation/spec"
	"k8s.io/kube-openapi/pkg/validation/strfmt"
)

type objectValidator struct {
	Path                 string
	In                   string
	MaxProperties        *int64
	MinProperties        *int64
	Required             []string
	Properties           map[string]spec.Schema
	AdditionalProperties *spec.SchemaOrBool
	PatternProperties    map[string]spec.Schema
	Root                 interface{}
	KnownFormats         strfmt.Registry
	Options              SchemaValidatorOptions
}

func (o *objectValidator) SetPath(path string) {
	o.Path = path
}

func (o *objectValidator) Applies(source interface{}, kind reflect.Kind) bool {
	// TODO: this should also work for structs
	// there is a problem in the type validator where it will be unhappy about null values
	// so that requires more testing
	r := reflect.TypeOf(source) == specSchemaType && (kind == reflect.Map || kind == reflect.Struct)
	debugLog("object validator for %q applies %t for %T (kind: %v)\n", o.Path, r, source, kind)
	return r
}

func (o *objectValidator) Validate(data interface{}) *Result {
	val := data.(map[string]interface{})
	// TODO: guard against nil data
	numKeys := int64(len(val))

	if o.MinProperties != nil && numKeys < *o.MinProperties {
		return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties))
	}
	if o.MaxProperties != nil && numKeys > *o.MaxProperties {
		return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties))
	}

	res := new(Result)

	// check validity of field names
	if o.AdditionalProperties != nil && !o.AdditionalProperties.Allows {
		// Case: additionalProperties: false
		for k := range val {
			_, regularProperty := o.Properties[k]
			matched := false

			for pk := range o.PatternProperties {
				if matches, _ := regexp.MatchString(pk, k); matches {
					matched = true
					break
				}
			}

			if !regularProperty && !matched {
				// Special properties "$schema" and "id" are ignored
				res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k))
			}
		}
	} else {
		// Cases: no additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <<schema>> }
		for key, value := range val {
			_, regularProperty := o.Properties[key]

			// Validates property against "patternProperties" if applicable
			// BUG(fredbi): succeededOnce is always false

			// NOTE: how about regular properties which do not match patternProperties?
			matched, succeededOnce, _ := o.validatePatternProperty(key, value, res)

			if !(regularProperty || matched || succeededOnce) {

				// Cases: properties which are not regular properties and have not been matched by the PatternProperties validator
				if o.AdditionalProperties != nil && o.AdditionalProperties.Schema != nil {
					// AdditionalProperties as Schema
					res.Merge(NewSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...).Validate(value))
				} else if regularProperty && !(matched || succeededOnce) {
					// TODO: this is dead code since regularProperty=false here
					res.AddErrors(errors.FailedAllPatternProperties(o.Path, o.In, key))
				}
			}
		}
		// Valid cases: additionalProperties: true or undefined
	}

	createdFromDefaults := map[string]bool{}

	// Property types:
	// - regular Property
	for pName, pSchema := range o.Properties {
		rName := pName
		if o.Path != "" {
			rName = o.Path + "." + pName
		}

		// Recursively validates each property against its schema
		if v, ok := val[pName]; ok {
			r := NewSchemaValidator(&pSchema, o.Root, rName, o.KnownFormats, o.Options.Options()...).Validate(v)
			res.Merge(r)
		}
	}

	// Check required properties
	if len(o.Required) > 0 {
		for _, k := range o.Required {
			if _, ok := val[k]; !ok && !createdFromDefaults[k] {
				res.AddErrors(errors.Required(o.Path+"."+k, o.In))
				continue
			}
		}
	}

	// Check patternProperties
	// TODO: it looks like we have done that twice in many cases
	for key, value := range val {
		_, regularProperty := o.Properties[key]
		matched, _ /*succeededOnce*/, patterns := o.validatePatternProperty(key, value, res)
		if !regularProperty && (matched /*|| succeededOnce*/) {
			for _, pName := range patterns {
				if v, ok := o.PatternProperties[pName]; ok {
					res.Merge(NewSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...).Validate(value))
				}
			}
		}
	}
	return res
}

// TODO: succeededOnce is not used anywhere
func (o *objectValidator) validatePatternProperty(key string, value interface{}, result *Result) (bool, bool, []string) {
	matched := false
	succeededOnce := false
	var patterns []string

	for k, schema := range o.PatternProperties {
		sch := schema
		if match, _ := regexp.MatchString(k, key); match {
			patterns = append(patterns, k)
			matched = true
			validator := NewSchemaValidator(&sch, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...)

			res := validator.Validate(value)
			result.Merge(res)
		}
	}

	// BUG(fredbi): can't get to here. Should remove dead code (commented out).

	//if succeededOnce {
	//	result.Inc()
	//}

	return matched, succeededOnce, patterns
}
<|endoftext|>


<commit_before>package main

import "testing"

var list = []struct {
	word     string
	expected bool
}{
	{"ugknbfddgicrmopn", true},
	{"aaa", true},
	{"jchzalrnumimnmhp", false},
	{"haegwjzuvuyypxyu", false},
	{"dvszwmarrgswjxmb", false},
}

func TestNaughtOrNice(t *testing.T) {

	for _, s := range list {
		check := NiceWord(s.word)
		if check != s.expected {
			t.Errorf("Fib(%s): expected %t, actual %t", s.word, s.expected, check)
		}
	}

}
<commit_msg>add part 2 tests<commit_after>package main

import "testing"

var list = []struct {
	word     string
	expected bool
}{
	{"ugknbfddgicrmopn", true},
	{"aaa", true},
	{"jchzalrnumimnmhp", false},
	{"haegwjzuvuyypxyu", false},
	{"dvszwmarrgswjxmb", false},
}

var list2 = []struct {
	word     string
	expected bool
}{
	{"qjhvhtzxzqqjkmpb", true},
	{"xxyxx", true},
	{"uurcxstgmygtbstg", false},
	{"ieodomkazucvgmuy", false},
}

func TestNaughtOrNice(t *testing.T) {

	for _, s := range list {
		check := NiceWord(s.word)
		if check != s.expected {
			t.Errorf("Fib(%s): expected %t, actual %t", s.word, s.expected, check)
		}
	}
}

func TestNaughtOrNice2(t *testing.T) {

	for _, s := range list2 {
		check := NiceWordPt2(s.word)
		if check != s.expected {
			t.Errorf("Fib(%s): expected %t, actual %t", s.word, s.expected, check)
		}
	}
}
<|endoftext|>


<commit_before>package godata

import "testing"

const TEST_SQLITE3_CREATE_STATEMENT_A = "CREATE TABLE FOO ( X INTEGER, Y TEXT PRIMARY KEY)"
const TEST_SQLITE3_CREATE_STATEMENT_B = "CREATE TABLE FOO ( X INTEGER, Y TEXT PRIMARY KEY, Z BETA NOT NULL)"
const TEST_SQLITE3_CREATE_STATEMENT_C = "CREATE TABLE FOO ( X INTEGER, PRIMARY KEY Y, Z BETA NOT NULL)"
const TEST_SQLITE3_CREATE_STATEMENT_D = "CREATE TABLE FOO ( X INTEGER, Y TEXT PRIMARY KEY, Z BETA NOT NULL, T DEFAULT  CURRENT_TIMESTAMP)"

func TestNewMetaTableFromCreateStatement(t *testing.T) {

	//TEST A
	meta, err := NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_A)
	if err != nil {
		t.Error(err)
	}

	if meta.name != "FOO" {
		t.Error("table name not stored properly")
	}

	if meta.dbVendor != "sqlite3" {
		t.Error("table name not stored properly")
	}

	columns := meta.columns.GetAll()

	if columns[0].name != "X" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[0].name)
	}

	if columns[0].sqlType != "INTEGER" {
		t.Error("Error column sql type is wrong")
	}

	if columns[0].goType != "int" {
		t.Error("Error column go type  is wrong")
	}

	if columns[1].name != "Y" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[1].name)
	}

	if columns[1].sqlType != "TEXT" {
		t.Error("Error column sql type is wrong")
	}

	if columns[1].goType != "string" {
		t.Error("Error column go type  is wrong")
	}

	//TEST B

	meta, err = NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_B)
	if err != nil {
		t.Error(err)
		return
	}

	if meta.name != "FOO" {
		t.Error("table name not stored properly")
	}

	if meta.dbVendor != "sqlite3" {
		t.Error("table name not stored properly")
	}

	columns = meta.columns.GetAll()

	if columns[0].name != "X" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[0].name)
	}

	if columns[0].sqlType != "INTEGER" {
		t.Error("Error column sql type is wrong")
	}

	if columns[0].goType != "int" {
		t.Error("Error column go type  is wrong")
	}

	if columns[1].name != "Y" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[1].name)
	}

	if columns[1].sqlType != "TEXT" {
		t.Error("Error column sql type is wrong")
	}

	if columns[1].goType != "string" {
		t.Error("Error column go type  is wrong")
	}

	if columns[2].name != "Z" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[0].name)
	}

	if columns[2].sqlType != "BETA" {
		t.Error("Error column sql type is wrong")
	}

	if columns[2].goType != "" {
		t.Error("Error column go type  is wrong")
	}

	//TEST C

	meta, err = NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_C)
	if err == nil {
		t.Error(err)
		return
	}

	//TEST D

	meta, err = NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_D)
	if err != nil {
		t.Error(err)
		return
	}

	if meta.name != "FOO" {
		t.Error("table name not stored properly")
	}

	if meta.dbVendor != "sqlite3" {
		t.Error("table name not stored properly")
	}

	columns = meta.columns.GetAll()

	if columns[0].name != "X" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[0].name)
	}

	if columns[0].sqlType != "INTEGER" {
		t.Error("Error column sql type is wrong")
	}

	if columns[0].goType != "int" {
		t.Error("Error column go type  is wrong")
	}

	if columns[1].name != "Y" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[1].name)
	}

	if columns[1].sqlType != "TEXT" {
		t.Error("Error column sql type is wrong")
	}

	if columns[1].goType != "string" {
		t.Error("Error column go type  is wrong")
	}

	if columns[2].name != "Z" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[0].name)
	}

	if columns[2].sqlType != "BETA" {
		t.Error("Error column sql type is wrong")
	}

	if columns[2].goType != "" {
		t.Error("Error column go type  is wrong")
	}

	if columns[3].name != "T" {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + columns[0].name)
	}

	if columns[3].sqlType != "TIMESTAMP" {
		t.Error("Error column sql type is wrong")
	}

	if columns[3].goType != "time.Time" {
		t.Error("Error column go type  is wrong")
	}

}
<commit_msg>Appended godata_test to use the new simplified data structures for godata<commit_after>package godata

import "testing"

const TEST_SQLITE3_CREATE_STATEMENT_A = "CREATE TABLE FOO ( X INTEGER, Y TEXT PRIMARY KEY)"
const TEST_SQLITE3_CREATE_STATEMENT_B = "CREATE TABLE FOO ( X INTEGER, Y TEXT PRIMARY KEY, Z BETA NOT NULL)"
const TEST_SQLITE3_CREATE_STATEMENT_C = "CREATE TABLE FOO ( X INTEGER, PRIMARY KEY Y, Z BETA NOT NULL)"
const TEST_SQLITE3_CREATE_STATEMENT_D = "CREATE TABLE FOO ( X INTEGER, Y TEXT PRIMARY KEY, Z BETA NOT NULL, T DEFAULT  CURRENT_TIMESTAMP)"

func TestNewMetaTableFromCreateStatement(t *testing.T) {

	//TEST A
	meta, err := NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_A)
	if err != nil {
		t.Error(err)
	}

	if meta.name != "FOO" {
		t.Error("table name not stored properly")
	}

	if meta.dbVendor != "sqlite3" {
		t.Error("table name not stored properly")
	}

	columns := meta.columns

	colName := "X"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "INTEGER" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "int" {
		t.Error("Error column go type  is wrong")
	}

	colName = "Y"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "TEXT" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "string" {
		t.Error("Error column go type  is wrong")
	}

	//TEST B

	meta, err = NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_B)

	if err != nil {
		t.Error(err)
	}

	if meta.name != "FOO" {
		t.Error("table name not stored properly")
	}

	if meta.dbVendor != "sqlite3" {
		t.Error("table name not stored properly")
	}

	columns = meta.columns

	colName = "X"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "INTEGER" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "int" {
		t.Error("Error column go type  is wrong")
	}

	colName = "Y"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "TEXT" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "string" {
		t.Error("Error column go type  is wrong")
	}

	colName = "Z"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "BETA" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "" {
		t.Error("Error column go type  is wrong")
	}

	//TEST C

	meta, err = NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_C)
	if err == nil {
		t.Error(err)
		return
	}

	//TEST D
	meta, err = NewMetaTableFromCreateStatement(TEST_SQLITE3_CREATE_STATEMENT_D)

	if err != nil {
		t.Error(err)
	}

	if meta.name != "FOO" {
		t.Error("table name not stored properly")
	}

	if meta.dbVendor != "sqlite3" {
		t.Error("table name not stored properly")
	}

	columns = meta.columns

	colName = "X"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "INTEGER" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "int" {
		t.Error("Error column go type  is wrong")
	}

	colName = "Y"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "TEXT" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "string" {
		t.Error("Error column go type  is wrong")
	}

	colName = "Z"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "BETA" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "" {
		t.Error("Error column go type  is wrong")
	}

	colName = "T"

	if _, ok := columns[colName]; !ok {
		t.Error("Error column name is wrong")
		t.Error("Column name is => " + colName)
	}

	if columns[colName].SqlType() != "TIMESTAMP" {
		t.Error("Error column sql type is wrong")
	}

	if columns[colName].GoType() != "time.Time" {
		t.Error("Error column go type  is wrong")
	}

}
<|endoftext|>


<commit_before>package kvdbredis

import (
	"io"

	"github.com/garyburd/redigo/redis"
	"github.com/google/btree"
	"github.com/pkg/errors"
	"github.com/xiaonanln/goworld/engine/gwlog"
	"github.com/xiaonanln/goworld/engine/kvdb/types"
)

const (
	keyPrefix = "_KV_"
)

type redisKVDB struct {
	c       redis.Conn
	keyTree *btree.BTree
}

type keyTreeItem struct {
	key string
}

func (ki keyTreeItem) Less(_other btree.Item) bool {
	return ki.key < _other.(keyTreeItem).key
}

// OpenRedisKVDB opens Redis for KVDB backend
func OpenRedisKVDB(url string, dbindex int) (kvdbtypes.KVDBEngine, error) {
	c, err := redis.DialURL(url)
	if err != nil {
		return nil, errors.Wrap(err, "redis dail failed")
	}

	db := &redisKVDB{
		c:       c,
		keyTree: btree.New(2),
	}

	if err := db.initialize(dbindex); err != nil {
		panic(errors.Wrap(err, "redis kvdb initialize failed"))
	}

	return db, nil
}

func (db *redisKVDB) initialize(dbindex int) error {
	if dbindex >= 0 {
		if _, err := db.c.Do("SELECT", dbindex); err != nil {
			return err
		}
	}

	keyMatch := keyPrefix + "*"
	r, err := redis.Values(db.c.Do("SCAN", "0", "MATCH", keyMatch, "COUNT", 10000))
	if err != nil {
		return err
	}
	for {
		nextCursor := r[0]
		keys, err := redis.Strings(r[1], nil)
		if err != nil {
			return err
		}
		//gwlog.Info("SCAN: %v, nextcursor=%s", keys, string(nextCursor.([]byte)))
		for _, key := range keys {
			key := key[len(keyPrefix):]
			db.keyTree.ReplaceOrInsert(keyTreeItem{key})
		}

		if db.isZeroCursor(nextCursor) {
			break
		}
		r, err = redis.Values(db.c.Do("SCAN", nextCursor, "MATCH", keyMatch, "COUNT", 10000))
		if err != nil {
			return err
		}
	}
	return nil
}

func (db *redisKVDB) isZeroCursor(c interface{}) bool {
	return string(c.([]byte)) == "0"
}

func (db *redisKVDB) Get(key string) (val string, err error) {
	r, err := db.c.Do("GET", keyPrefix+key)
	if err != nil {
		return "", err
	}
	if r == nil {
		return "", nil
	}
	return string(r.([]byte)), err
}

func (db *redisKVDB) Put(key string, val string) error {
	_, err := db.c.Do("SET", keyPrefix+key, val)
	if err != nil {
		db.keyTree.ReplaceOrInsert(keyTreeItem{key})
	}
	return err
}

type redisKVDBIterator struct {
	db       *redisKVDB
	leftKeys []string
}

func (it *redisKVDBIterator) Next() (kvdbtypes.KVItem, error) {
	if len(it.leftKeys) == 0 {
		return kvdbtypes.KVItem{}, io.EOF
	}

	key := it.leftKeys[0]
	it.leftKeys = it.leftKeys[1:]
	val, err := it.db.Get(key)
	if err != nil {
		return kvdbtypes.KVItem{}, err
	}

	return kvdbtypes.KVItem{key, val}, nil
}

func (db *redisKVDB) Find(beginKey string, endKey string) (kvdbtypes.Iterator, error) {
	keys := []string{} // retrive all keys in the range, ordered
	db.keyTree.AscendRange(keyTreeItem{beginKey}, keyTreeItem{endKey}, func(it btree.Item) bool {
		keys = append(keys, it.(keyTreeItem).key)
		return true
	})

	gwlog.Infof("found keys from %s to %s: %v", beginKey, endKey, keys)
	return &redisKVDBIterator{
		db:       db,
		leftKeys: keys,
	}, nil
}

func (db *redisKVDB) Close() {
	db.c.Close()
}

func (db *redisKVDB) IsConnectionError(err error) bool {
	return err == io.EOF || err == io.ErrUnexpectedEOF
}
<commit_msg>kvdb testing 1<commit_after>package kvdbredis

import (
	"io"

	"github.com/garyburd/redigo/redis"
	"github.com/google/btree"
	"github.com/pkg/errors"
	"github.com/xiaonanln/goworld/engine/gwlog"
	"github.com/xiaonanln/goworld/engine/kvdb/types"
)

const (
	keyPrefix = "_KV_"
)

type redisKVDB struct {
	c       redis.Conn
	keyTree *btree.BTree
}

type keyTreeItem struct {
	key string
}

func (ki keyTreeItem) Less(_other btree.Item) bool {
	return ki.key < _other.(keyTreeItem).key
}

// OpenRedisKVDB opens Redis for KVDB backend
func OpenRedisKVDB(url string, dbindex int) (kvdbtypes.KVDBEngine, error) {
	c, err := redis.DialURL(url)
	if err != nil {
		return nil, errors.Wrap(err, "redis dail failed")
	}

	db := &redisKVDB{
		c:       c,
		keyTree: btree.New(2),
	}

	if err := db.initialize(dbindex); err != nil {
		panic(errors.Wrap(err, "redis kvdb initialize failed"))
	}

	return db, nil
}

func (db *redisKVDB) initialize(dbindex int) error {
	if dbindex >= 0 {
		if _, err := db.c.Do("SELECT", dbindex); err != nil {
			return err
		}
	}

	keyMatch := keyPrefix + "*"
	r, err := redis.Values(db.c.Do("SCAN", "0", "MATCH", keyMatch, "COUNT", 10000))
	if err != nil {
		return err
	}
	for {
		nextCursor := r[0]
		keys, err := redis.Strings(r[1], nil)
		if err != nil {
			return err
		}
		//gwlog.Info("SCAN: %v, nextcursor=%s", keys, string(nextCursor.([]byte)))
		for _, key := range keys {
			key := key[len(keyPrefix):]
			db.keyTree.ReplaceOrInsert(keyTreeItem{key})
		}

		if db.isZeroCursor(nextCursor) {
			break
		}
		r, err = redis.Values(db.c.Do("SCAN", nextCursor, "MATCH", keyMatch, "COUNT", 10000))
		if err != nil {
			return err
		}
	}
	return nil
}

func (db *redisKVDB) isZeroCursor(c interface{}) bool {
	return string(c.([]byte)) == "0"
}

func (db *redisKVDB) Get(key string) (val string, err error) {
	r, err := db.c.Do("GET", keyPrefix+key)
	if err != nil {
		return "", err
	}
	if r == nil {
		return "", nil
	}
	return string(r.([]byte)), err
}

func (db *redisKVDB) Put(key string, val string) error {
	_, err := db.c.Do("SET", keyPrefix+key, val)
	gwlog.Infof("kvdb set key %s to redis: err=%v", key, err)
	if err != nil {
		db.keyTree.ReplaceOrInsert(keyTreeItem{key})
		if !db.keyTree.Has(keyTreeItem{key}) {
			panic(errors.New("insert key tree fail"))
		}
	}
	return err
}

type redisKVDBIterator struct {
	db       *redisKVDB
	leftKeys []string
}

func (it *redisKVDBIterator) Next() (kvdbtypes.KVItem, error) {
	if len(it.leftKeys) == 0 {
		return kvdbtypes.KVItem{}, io.EOF
	}

	key := it.leftKeys[0]
	it.leftKeys = it.leftKeys[1:]
	val, err := it.db.Get(key)
	if err != nil {
		return kvdbtypes.KVItem{}, err
	}

	return kvdbtypes.KVItem{key, val}, nil
}

func (db *redisKVDB) Find(beginKey string, endKey string) (kvdbtypes.Iterator, error) {
	keys := []string{} // retrive all keys in the range, ordered
	db.keyTree.AscendRange(keyTreeItem{beginKey}, keyTreeItem{endKey}, func(it btree.Item) bool {
		keys = append(keys, it.(keyTreeItem).key)
		return true
	})

	gwlog.Infof("found keys from %s to %s: %v", beginKey, endKey, keys)
	return &redisKVDBIterator{
		db:       db,
		leftKeys: keys,
	}, nil
}

func (db *redisKVDB) Close() {
	db.c.Close()
}

func (db *redisKVDB) IsConnectionError(err error) bool {
	return err == io.EOF || err == io.ErrUnexpectedEOF
}
<|endoftext|>


<commit_before>// Copyright 2011 Arne Roomann-Kurrik.
//
// 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 oauth1a

import (
	"net/http"
	"net/url"
	"strings"
	"testing"
)

var user = NewAuthorizedConfig("token", "secret")

var client = &ClientConfig{
	ConsumerKey:    "consumer_key",
	ConsumerSecret: "consumer_secret",
	CallbackURL:    "https://example.com/callback",
}

var signer = new(HmacSha1Signer)

var service = &Service{
	RequestURL:   "https://example.com/request_token",
	AuthorizeURL: "https://example.com/request_token",
	AccessURL:    "https://example.com/request_token",
	ClientConfig: client,
	Signer:       signer,
}

func TestSignature(t *testing.T) {
	api_url := "https://example.com/endpoint"
	request, _ := http.NewRequest("GET", api_url, nil)
	service.Sign(request, user)
	params, _ := signer.GetOAuthParams(request, client, user, "nonce", "timestamp")
	signature := params["oauth_signature"]
	expected := "8+ZC6DP8FU3z50qSWDeYCGix2x0="
	if signature != expected {
		t.Errorf("Signature %v did not match expected %v", signature, expected)
	}
}

func TestSlashInParameter(t *testing.T) {
	api_url := "https://stream.twitter.com/1.1/statuses/filter.json"
	data := url.Values{}
	data.Set("track", "example.com/abcd")
	body := strings.NewReader(data.Encode())
	request, _ := http.NewRequest("POST", api_url, body)
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	service.Sign(request, user)
	nonce := "bf2cb6d611e59f99103238fc9a3bb8d8"
	timestamp := "1362434376"
	params, _ := signer.GetOAuthParams(request, client, user, nonce, timestamp)
	signature := params["oauth_signature"]
	expected := "LcxylEOnNdgoKSJi7jX07mxcvfM="
	if signature != expected {
		t.Errorf("Signature %v did not match expected %v", signature, expected)
	}
}

func TestNonceOverride(t *testing.T) {
	api_url := "https://example.com/endpoint"
	request, _ := http.NewRequest("GET", api_url, nil)
	request.Header.Set("X-OAuth-Nonce", "12345")
	service.Sign(request, user)
	if request.Header.Get("X-OAuth-Nonce") != "" {
		t.Errorf("Nonce override should be cleared after signing")
	}
	header := request.Header.Get("Authorization")
	if !strings.Contains(header, "oauth_nonce=\"12345\"") {
		t.Errorf("Nonce override was not used")
	}
	if strings.Contains(header, "oauth_timestamp=\"\"") {
		t.Errorf("Timestamp not sent when nonce override used")
	}
}

func TestTimestampOverride(t *testing.T) {
	api_url := "https://example.com/endpoint"
	request, _ := http.NewRequest("GET", api_url, nil)
	request.Header.Set("X-OAuth-Timestamp", "54321")
	service.Sign(request, user)
	if request.Header.Get("X-OAuth-Timestamp") != "" {
		t.Errorf("Timestamp override should be cleared after signing")
	}
	header := request.Header.Get("Authorization")
	if !strings.Contains(header, "oauth_timestamp=\"54321\"") {
		t.Errorf("Timestamp override was not used")
	}
	if strings.Contains(header, "oauth_nonce=\"\"") {
		t.Errorf("Nonce not sent when timestamp override used")
	}
}

var ESCAPE_TESTS = map[string]string{
	"Ā": "%C4%80",
	"㤹": "%E3%A4%B9",
}

func TestEscaping(t *testing.T) {
	for str, expected := range ESCAPE_TESTS {
		if Rfc3986Escape(str) != expected {
			t.Errorf("Escaped %v was %v, expected %v", str, Rfc3986Escape(str), expected)
		}
	}
}
<commit_msg>Check to make sure that slashes in the query are parsed correctly too.<commit_after>// Copyright 2011 Arne Roomann-Kurrik.
//
// 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 oauth1a

import (
	"net/http"
	"net/url"
	"strings"
	"testing"
	"io"
)

var user = NewAuthorizedConfig("token", "secret")

var client = &ClientConfig{
	ConsumerKey:    "consumer_key",
	ConsumerSecret: "consumer_secret",
	CallbackURL:    "https://example.com/callback",
}

var signer = new(HmacSha1Signer)

var service = &Service{
	RequestURL:   "https://example.com/request_token",
	AuthorizeURL: "https://example.com/request_token",
	AccessURL:    "https://example.com/request_token",
	ClientConfig: client,
	Signer:       signer,
}

func TestSignature(t *testing.T) {
	api_url := "https://example.com/endpoint"
	request, _ := http.NewRequest("GET", api_url, nil)
	service.Sign(request, user)
	params, _ := signer.GetOAuthParams(request, client, user, "nonce", "timestamp")
	signature := params["oauth_signature"]
	expected := "8+ZC6DP8FU3z50qSWDeYCGix2x0="
	if signature != expected {
		t.Errorf("Signature %v did not match expected %v", signature, expected)
	}
}

func TestSlashInParameter(t *testing.T) {
	api_url := "https://stream.twitter.com/1.1/statuses/filter.json"
	data := url.Values{}
	data.Set("track", "example.com/abcd")
	body := strings.NewReader(data.Encode())
	request, _ := http.NewRequest("POST", api_url, body)
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	service.Sign(request, user)
	nonce := "bf2cb6d611e59f99103238fc9a3bb8d8"
	timestamp := "1362434376"
	params, _ := signer.GetOAuthParams(request, client, user, nonce, timestamp)
	signature := params["oauth_signature"]
	expected := "LcxylEOnNdgoKSJi7jX07mxcvfM="
	if signature != expected {
		t.Errorf("Signature %v did not match expected %v", signature, expected)
	}
}

func TestSlashInQuerystring(t *testing.T) {
	api_url := "https://stream.twitter.com/1.1/statuses/filter.json?track=example.com/query"
	var body io.Reader
	request, _ := http.NewRequest("POST", api_url, body)
	service.Sign(request, user)
	nonce := "884275759fbab914654b50ae643c563a"
	timestamp := "1362435218"
	params, _ := signer.GetOAuthParams(request, client, user, nonce, timestamp)
	signature := params["oauth_signature"]
	expected := "OAldqvRrKDXRGZ9BqSi2CqeVH0g="
	if signature != expected {
		t.Errorf("Signature %v did not match expected %v", signature, expected)
	}
}

func TestNonceOverride(t *testing.T) {
	api_url := "https://example.com/endpoint"
	request, _ := http.NewRequest("GET", api_url, nil)
	request.Header.Set("X-OAuth-Nonce", "12345")
	service.Sign(request, user)
	if request.Header.Get("X-OAuth-Nonce") != "" {
		t.Errorf("Nonce override should be cleared after signing")
	}
	header := request.Header.Get("Authorization")
	if !strings.Contains(header, "oauth_nonce=\"12345\"") {
		t.Errorf("Nonce override was not used")
	}
	if strings.Contains(header, "oauth_timestamp=\"\"") {
		t.Errorf("Timestamp not sent when nonce override used")
	}
}

func TestTimestampOverride(t *testing.T) {
	api_url := "https://example.com/endpoint"
	request, _ := http.NewRequest("GET", api_url, nil)
	request.Header.Set("X-OAuth-Timestamp", "54321")
	service.Sign(request, user)
	if request.Header.Get("X-OAuth-Timestamp") != "" {
		t.Errorf("Timestamp override should be cleared after signing")
	}
	header := request.Header.Get("Authorization")
	if !strings.Contains(header, "oauth_timestamp=\"54321\"") {
		t.Errorf("Timestamp override was not used")
	}
	if strings.Contains(header, "oauth_nonce=\"\"") {
		t.Errorf("Nonce not sent when timestamp override used")
	}
}

var ESCAPE_TESTS = map[string]string{
	"Ā": "%C4%80",
	"㤹": "%E3%A4%B9",
}

func TestEscaping(t *testing.T) {
	for str, expected := range ESCAPE_TESTS {
		if Rfc3986Escape(str) != expected {
			t.Errorf("Escaped %v was %v, expected %v", str, Rfc3986Escape(str), expected)
		}
	}
}
<|endoftext|>


<commit_before>package definition

type Tout interface {
    // Nothing
}

const Version="0.2.3"
<commit_msg>update version<commit_after>package definition

type Tout interface {
    // Nothing
}

const Version="0.2.4"
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 install installs the batch API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install

import (
	"fmt"

	"github.com/golang/glog"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/apimachinery"
	"k8s.io/kubernetes/pkg/apimachinery/registered"
	"k8s.io/kubernetes/pkg/apis/batch"
	"k8s.io/kubernetes/pkg/apis/batch/v1"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/util/sets"
)

const importPrefix = "k8s.io/kubernetes/pkg/apis/batch"

var accessor = meta.NewAccessor()

// availableVersions lists all known external versions for this group from most preferred to least preferred
var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}

func init() {
	registered.RegisterVersions(availableVersions)
	externalVersions := []unversioned.GroupVersion{}
	for _, v := range availableVersions {
		if registered.IsAllowedVersion(v) {
			externalVersions = append(externalVersions, v)
		}
	}
	if len(externalVersions) == 0 {
		glog.V(4).Infof("No version is registered for group %v", batch.GroupName)
		return
	}

	if err := registered.EnableVersions(externalVersions...); err != nil {
		glog.V(4).Infof("%v", err)
		return
	}
	if err := enableVersions(externalVersions); err != nil {
		glog.V(4).Infof("%v", err)
		return
	}
}

// TODO: enableVersions should be centralized rather than spread in each API
// group.
// We can combine registered.RegisterVersions, registered.EnableVersions and
// registered.RegisterGroup once we have moved enableVersions there.
func enableVersions(externalVersions []unversioned.GroupVersion) error {
	addVersionsToScheme(externalVersions...)
	preferredExternalVersion := externalVersions[0]

	groupMeta := apimachinery.GroupMeta{
		GroupVersion:  preferredExternalVersion,
		GroupVersions: externalVersions,
		RESTMapper:    newRESTMapper(externalVersions),
		SelfLinker:    runtime.SelfLinker(accessor),
		InterfacesFor: interfacesFor,
	}

	if err := registered.RegisterGroup(groupMeta); err != nil {
		return err
	}
	api.RegisterRESTMapper(groupMeta.RESTMapper)
	return nil
}

func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
	// the list of kinds that are scoped at the root of the api hierarchy
	// if a kind is not enumerated here, it is assumed to have a namespace scope
	rootScoped := sets.NewString()

	ignoredKinds := sets.NewString()

	return api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
}

// interfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
	switch version {
	case v1.SchemeGroupVersion:
		return &meta.VersionInterfaces{
			ObjectConvertor:  api.Scheme,
			MetadataAccessor: accessor,
		}, nil
	default:
		g, _ := registered.Group(batch.GroupName)
		return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
	}
}

func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
	// add the internal version to Scheme
	batch.AddToScheme(api.Scheme)
	// add the enabled external versions to Scheme
	for _, v := range externalVersions {
		if !registered.IsEnabledVersion(v) {
			glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
			continue
		}
		switch v {
		case v1.SchemeGroupVersion:
			v1.AddToScheme(api.Scheme)
		}
	}
}
<commit_msg>UPSTREAM: <carry>: force import ordering for stable codegen<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 install installs the batch API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install

import (
	"fmt"

	"github.com/golang/glog"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/apimachinery"
	"k8s.io/kubernetes/pkg/apimachinery/registered"
	"k8s.io/kubernetes/pkg/apis/batch"
	"k8s.io/kubernetes/pkg/apis/batch/v1"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/util/sets"

	// force determinstic ordering when loading these packages
	_ "k8s.io/kubernetes/pkg/apis/extensions/install"
)

const importPrefix = "k8s.io/kubernetes/pkg/apis/batch"

var accessor = meta.NewAccessor()

// availableVersions lists all known external versions for this group from most preferred to least preferred
var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}

func init() {
	registered.RegisterVersions(availableVersions)
	externalVersions := []unversioned.GroupVersion{}
	for _, v := range availableVersions {
		if registered.IsAllowedVersion(v) {
			externalVersions = append(externalVersions, v)
		}
	}
	if len(externalVersions) == 0 {
		glog.V(4).Infof("No version is registered for group %v", batch.GroupName)
		return
	}

	if err := registered.EnableVersions(externalVersions...); err != nil {
		glog.V(4).Infof("%v", err)
		return
	}
	if err := enableVersions(externalVersions); err != nil {
		glog.V(4).Infof("%v", err)
		return
	}
}

// TODO: enableVersions should be centralized rather than spread in each API
// group.
// We can combine registered.RegisterVersions, registered.EnableVersions and
// registered.RegisterGroup once we have moved enableVersions there.
func enableVersions(externalVersions []unversioned.GroupVersion) error {
	addVersionsToScheme(externalVersions...)
	preferredExternalVersion := externalVersions[0]

	groupMeta := apimachinery.GroupMeta{
		GroupVersion:  preferredExternalVersion,
		GroupVersions: externalVersions,
		RESTMapper:    newRESTMapper(externalVersions),
		SelfLinker:    runtime.SelfLinker(accessor),
		InterfacesFor: interfacesFor,
	}

	if err := registered.RegisterGroup(groupMeta); err != nil {
		return err
	}
	api.RegisterRESTMapper(groupMeta.RESTMapper)
	return nil
}

func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
	// the list of kinds that are scoped at the root of the api hierarchy
	// if a kind is not enumerated here, it is assumed to have a namespace scope
	rootScoped := sets.NewString()

	ignoredKinds := sets.NewString()

	return api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
}

// interfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
	switch version {
	case v1.SchemeGroupVersion:
		return &meta.VersionInterfaces{
			ObjectConvertor:  api.Scheme,
			MetadataAccessor: accessor,
		}, nil
	default:
		g, _ := registered.Group(batch.GroupName)
		return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
	}
}

func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
	// add the internal version to Scheme
	batch.AddToScheme(api.Scheme)
	// add the enabled external versions to Scheme
	for _, v := range externalVersions {
		if !registered.IsEnabledVersion(v) {
			glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
			continue
		}
		switch v {
		case v1.SchemeGroupVersion:
			v1.AddToScheme(api.Scheme)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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

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

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

package main

import (
	"fmt"
	"sort"
	"strings"

	"github.com/GoogleCloudPlatform/gcloud/gcloud_apis/commands"
)

func ListMethods(args []string) error {

	fullNames := false
	for i, arg := range args {
		if arg == "--full" {
			fullNames = true
			args = append(args[:i], args[i+1:]...)
			break
		}
	}

	if len(args) > 1 {
		Usage()
	}
	prefix := ""
	if len(args) == 1 {
		prefix = args[0]
	}
	return listMethods(prefix, fullNames)
}

func listMethods(prefix string, fullNames bool) error {
	listedThings := map[string]bool{}
	if prefix == "" {
		for methodName := range commands.AllMethods {
			if fullNames {
				listedThings[methodName] = true
			} else {
				methodPrefix := strings.SplitN(methodName, ".", 2)[0]
				listedThings[methodPrefix] = true
			}
		}
	} else {
		for methodName := range commands.AllMethods {
			if methodName == prefix {
				listedThings[methodName] = true
				break
			}
			if strings.HasPrefix(methodName, prefix+".") {
				firstUntypedDot := strings.Index(methodName[len(prefix)+1:], ".")
				if !fullNames && firstUntypedDot != -1 {
					listedThings[methodName[:firstUntypedDot+len(prefix)+1]] = true
				} else {
					listedThings[methodName] = true
				}
			}
		}
	}

	if len(listedThings) == 0 {
		return fmt.Errorf("no listing for %q", prefix)
	}

	var listedThingSlice []string
	for thing := range listedThings {
		listedThingSlice = append(listedThingSlice, thing)
	}

	sort.Sort(sort.StringSlice(listedThingSlice))
	for _, thing := range listedThingSlice {
		fmt.Println(thing)
	}

	return nil
}
<commit_msg>Removing empty line.<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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

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

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

package main

import (
	"fmt"
	"sort"
	"strings"

	"github.com/GoogleCloudPlatform/gcloud/gcloud_apis/commands"
)

func ListMethods(args []string) error {
	fullNames := false
	for i, arg := range args {
		if arg == "--full" {
			fullNames = true
			args = append(args[:i], args[i+1:]...)
			break
		}
	}

	if len(args) > 1 {
		Usage()
	}
	prefix := ""
	if len(args) == 1 {
		prefix = args[0]
	}
	return listMethods(prefix, fullNames)
}

func listMethods(prefix string, fullNames bool) error {
	listedThings := map[string]bool{}
	if prefix == "" {
		for methodName := range commands.AllMethods {
			if fullNames {
				listedThings[methodName] = true
			} else {
				methodPrefix := strings.SplitN(methodName, ".", 2)[0]
				listedThings[methodPrefix] = true
			}
		}
	} else {
		for methodName := range commands.AllMethods {
			if methodName == prefix {
				listedThings[methodName] = true
				break
			}
			if strings.HasPrefix(methodName, prefix+".") {
				firstUntypedDot := strings.Index(methodName[len(prefix)+1:], ".")
				if !fullNames && firstUntypedDot != -1 {
					listedThings[methodName[:firstUntypedDot+len(prefix)+1]] = true
				} else {
					listedThings[methodName] = true
				}
			}
		}
	}

	if len(listedThings) == 0 {
		return fmt.Errorf("no listing for %q", prefix)
	}

	var listedThingSlice []string
	for thing := range listedThings {
		listedThingSlice = append(listedThingSlice, thing)
	}

	sort.Sort(sort.StringSlice(listedThingSlice))
	for _, thing := range listedThingSlice {
		fmt.Println(thing)
	}

	return nil
}
<|endoftext|>