update vendor

added files required by BuildConfig reaper
This commit is contained in:
Tomas Kral 2017-04-27 15:40:39 +02:00
parent bee784faf6
commit 166eedfc1c
No known key found for this signature in database
GPG Key ID: E690DA7E4F291FA6
6 changed files with 484 additions and 0 deletions

View File

@ -0,0 +1,2 @@
// Package cmd provides command helpers for builds
package cmd

View File

@ -0,0 +1,150 @@
package cmd
import (
"sort"
"strings"
"time"
"github.com/golang/glog"
kapi "k8s.io/kubernetes/pkg/api"
kerrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/kubectl"
ktypes "k8s.io/kubernetes/pkg/types"
kutilerrors "k8s.io/kubernetes/pkg/util/errors"
buildapi "github.com/openshift/origin/pkg/build/api"
buildutil "github.com/openshift/origin/pkg/build/util"
"github.com/openshift/origin/pkg/client"
"github.com/openshift/origin/pkg/util"
)
// NewBuildConfigReaper returns a new reaper for buildConfigs
func NewBuildConfigReaper(oc *client.Client) kubectl.Reaper {
return &BuildConfigReaper{oc: oc, pollInterval: kubectl.Interval, timeout: kubectl.Timeout}
}
// BuildConfigReaper implements the Reaper interface for buildConfigs
type BuildConfigReaper struct {
oc client.Interface
pollInterval, timeout time.Duration
}
// Stop deletes the build configuration and all of the associated builds.
func (reaper *BuildConfigReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *kapi.DeleteOptions) error {
_, err := reaper.oc.BuildConfigs(namespace).Get(name)
if err != nil {
return err
}
var bcPotentialBuilds []buildapi.Build
// Collect builds related to the config.
builds, err := reaper.oc.Builds(namespace).List(kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(name)})
if err != nil {
return err
}
bcPotentialBuilds = append(bcPotentialBuilds, builds.Items...)
// Collect deprecated builds related to the config.
// TODO: Delete this block after BuildConfigLabelDeprecated is removed.
builds, err = reaper.oc.Builds(namespace).List(kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(name)})
if err != nil {
return err
}
bcPotentialBuilds = append(bcPotentialBuilds, builds.Items...)
// A map of builds associated with this build configuration
bcBuilds := make(map[ktypes.UID]buildapi.Build)
// Because of name length limits in the BuildConfigSelector, annotations are used to ensure
// reliable selection of associated builds.
for _, build := range bcPotentialBuilds {
if build.Annotations != nil {
if bcName, ok := build.Annotations[buildapi.BuildConfigAnnotation]; ok {
// The annotation, if present, has the full build config name.
if bcName != name {
// If the name does not match exactly, the build is not truly associated with the build configuration
continue
}
}
}
// Note that if there is no annotation, this is a deprecated build spec
// and we choose to include it in the deletion having matched only the BuildConfigSelectorDeprecated
// Use a map to union the lists returned by the contemporary & deprecated build queries
// (there will be overlap between the lists, and we only want to try to delete each build once)
bcBuilds[build.UID] = build
}
// If there are builds associated with this build configuration, pause it before attempting the deletion
if len(bcBuilds) > 0 {
// Add paused annotation to the build config pending the deletion
err = unversioned.RetryOnConflict(unversioned.DefaultRetry, func() error {
bc, err := reaper.oc.BuildConfigs(namespace).Get(name)
if err != nil {
return err
}
// Ignore if the annotation already exists
if strings.ToLower(bc.Annotations[buildapi.BuildConfigPausedAnnotation]) == "true" {
return nil
}
// Set the annotation and update
if err := util.AddObjectAnnotations(bc, map[string]string{buildapi.BuildConfigPausedAnnotation: "true"}); err != nil {
return err
}
_, err = reaper.oc.BuildConfigs(namespace).Update(bc)
return err
})
if err != nil {
return err
}
}
// Warn the user if the BuildConfig won't get deleted after this point.
bcDeleted := false
defer func() {
if !bcDeleted {
glog.Warningf("BuildConfig %s/%s will not be deleted because not all associated builds could be deleted. You can try re-running the command or removing them manually", namespace, name)
}
}()
// For the benefit of test cases, sort the UIDs so that the deletion order is deterministic
buildUIDs := make([]string, 0, len(bcBuilds))
for buildUID := range bcBuilds {
buildUIDs = append(buildUIDs, string(buildUID))
}
sort.Strings(buildUIDs)
errList := []error{}
for _, buildUID := range buildUIDs {
build := bcBuilds[ktypes.UID(buildUID)]
if err := reaper.oc.Builds(namespace).Delete(build.Name); err != nil {
glog.Warningf("Cannot delete Build %s/%s: %v", build.Namespace, build.Name, err)
if !kerrors.IsNotFound(err) {
errList = append(errList, err)
}
}
}
// Aggregate all errors
if len(errList) > 0 {
return kutilerrors.NewAggregate(errList)
}
if err := reaper.oc.BuildConfigs(namespace).Delete(name); err != nil {
return err
}
bcDeleted = true
return nil
}

4
vendor/github.com/openshift/origin/pkg/util/doc.go generated vendored Normal file
View File

@ -0,0 +1,4 @@
// Package util implements various utility functions used in both testing and
// implementation of OpenShift. Package util may not depend on any other
// package in the OpenShift package tree.
package util

21
vendor/github.com/openshift/origin/pkg/util/etcd.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
package util
import (
"path"
kapi "k8s.io/kubernetes/pkg/api"
kerrors "k8s.io/kubernetes/pkg/api/errors"
)
// NoNamespaceKeyFunc is the default function for constructing etcd paths to a resource relative to prefix enforcing
// If a namespace is on context, it errors.
func NoNamespaceKeyFunc(ctx kapi.Context, prefix string, name string) (string, error) {
ns, ok := kapi.NamespaceFrom(ctx)
if ok && len(ns) > 0 {
return "", kerrors.NewBadRequest("Namespace parameter is not allowed.")
}
if len(name) == 0 {
return "", kerrors.NewBadRequest("Name parameter required.")
}
return path.Join(prefix, name), nil
}

286
vendor/github.com/openshift/origin/pkg/util/labels.go generated vendored Normal file
View File

@ -0,0 +1,286 @@
package util
import (
"fmt"
"reflect"
kmeta "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
deployapi "github.com/openshift/origin/pkg/deploy/api"
)
// MergeInto flags
const (
OverwriteExistingDstKey = 1 << iota
ErrorOnExistingDstKey
ErrorOnDifferentDstKeyValue
)
// AddObjectLabelsWithFlags will set labels on the target object. Label overwrite behavior
// is controlled by the flags argument.
func AddObjectLabelsWithFlags(obj runtime.Object, labels labels.Set, flags int) error {
if labels == nil {
return nil
}
accessor, err := kmeta.Accessor(obj)
if err != nil {
if _, ok := obj.(*runtime.Unstructured); !ok {
// error out if it's not possible to get an accessor and it's also not an unstructured object
return err
}
} else {
metaLabels := accessor.GetLabels()
if metaLabels == nil {
metaLabels = make(map[string]string)
}
switch objType := obj.(type) {
case *deployapi.DeploymentConfig:
if err := addDeploymentConfigNestedLabels(objType, labels, flags); err != nil {
return fmt.Errorf("unable to add nested labels to %s/%s: %v", obj.GetObjectKind().GroupVersionKind(), accessor.GetName(), err)
}
}
if err := MergeInto(metaLabels, labels, flags); err != nil {
return fmt.Errorf("unable to add labels to %s/%s: %v", obj.GetObjectKind().GroupVersionKind(), accessor.GetName(), err)
}
accessor.SetLabels(metaLabels)
return nil
}
// handle unstructured object
// TODO: allow meta.Accessor to handle runtime.Unstructured
if unstruct, ok := obj.(*runtime.Unstructured); ok && unstruct.Object != nil {
// the presence of "metadata" is sufficient for us to apply the rules for Kube-like
// objects.
// TODO: add swagger detection to allow this to happen more effectively
if obj, ok := unstruct.Object["metadata"]; ok {
if m, ok := obj.(map[string]interface{}); ok {
existing := make(map[string]string)
if l, ok := m["labels"]; ok {
if found, ok := interfaceToStringMap(l); ok {
existing = found
}
}
if err := MergeInto(existing, labels, flags); err != nil {
return err
}
m["labels"] = mapToGeneric(existing)
}
return nil
}
// only attempt to set root labels if a root object called labels exists
// TODO: add swagger detection to allow this to happen more effectively
if obj, ok := unstruct.Object["labels"]; ok {
existing := make(map[string]string)
if found, ok := interfaceToStringMap(obj); ok {
existing = found
}
if err := MergeInto(existing, labels, flags); err != nil {
return err
}
unstruct.Object["labels"] = mapToGeneric(existing)
return nil
}
}
return nil
}
// AddObjectLabels adds new label(s) to a single runtime.Object, overwriting
// existing labels that have the same key.
func AddObjectLabels(obj runtime.Object, labels labels.Set) error {
return AddObjectLabelsWithFlags(obj, labels, OverwriteExistingDstKey)
}
// AddObjectAnnotations adds new annotation(s) to a single runtime.Object
func AddObjectAnnotations(obj runtime.Object, annotations map[string]string) error {
if len(annotations) == 0 {
return nil
}
accessor, err := kmeta.Accessor(obj)
if err != nil {
if _, ok := obj.(*runtime.Unstructured); !ok {
// error out if it's not possible to get an accessor and it's also not an unstructured object
return err
}
} else {
metaAnnotations := accessor.GetAnnotations()
if metaAnnotations == nil {
metaAnnotations = make(map[string]string)
}
switch objType := obj.(type) {
case *deployapi.DeploymentConfig:
if err := addDeploymentConfigNestedAnnotations(objType, annotations); err != nil {
return fmt.Errorf("unable to add nested annotations to %s/%s: %v", obj.GetObjectKind().GroupVersionKind(), accessor.GetName(), err)
}
}
MergeInto(metaAnnotations, annotations, OverwriteExistingDstKey)
accessor.SetAnnotations(metaAnnotations)
return nil
}
// handle unstructured object
// TODO: allow meta.Accessor to handle runtime.Unstructured
if unstruct, ok := obj.(*runtime.Unstructured); ok && unstruct.Object != nil {
// the presence of "metadata" is sufficient for us to apply the rules for Kube-like
// objects.
// TODO: add swagger detection to allow this to happen more effectively
if obj, ok := unstruct.Object["metadata"]; ok {
if m, ok := obj.(map[string]interface{}); ok {
existing := make(map[string]string)
if l, ok := m["annotations"]; ok {
if found, ok := interfaceToStringMap(l); ok {
existing = found
}
}
if err := MergeInto(existing, annotations, OverwriteExistingDstKey); err != nil {
return err
}
m["annotations"] = mapToGeneric(existing)
}
return nil
}
// only attempt to set root annotations if a root object called annotations exists
// TODO: add swagger detection to allow this to happen more effectively
if obj, ok := unstruct.Object["annotations"]; ok {
existing := make(map[string]string)
if found, ok := interfaceToStringMap(obj); ok {
existing = found
}
if err := MergeInto(existing, annotations, OverwriteExistingDstKey); err != nil {
return err
}
unstruct.Object["annotations"] = mapToGeneric(existing)
return nil
}
}
return nil
}
// addDeploymentConfigNestedLabels adds new label(s) to a nested labels of a single DeploymentConfig object
func addDeploymentConfigNestedLabels(obj *deployapi.DeploymentConfig, labels labels.Set, flags int) error {
if obj.Spec.Template.Labels == nil {
obj.Spec.Template.Labels = make(map[string]string)
}
if err := MergeInto(obj.Spec.Template.Labels, labels, flags); err != nil {
return fmt.Errorf("unable to add labels to Template.DeploymentConfig.Template.ControllerTemplate.Template: %v", err)
}
return nil
}
func addDeploymentConfigNestedAnnotations(obj *deployapi.DeploymentConfig, annotations map[string]string) error {
if obj.Spec.Template == nil {
return nil
}
if obj.Spec.Template.Annotations == nil {
obj.Spec.Template.Annotations = make(map[string]string)
}
if err := MergeInto(obj.Spec.Template.Annotations, annotations, OverwriteExistingDstKey); err != nil {
return fmt.Errorf("unable to add annotations to Template.DeploymentConfig.Template.ControllerTemplate.Template: %v", err)
}
return nil
}
// interfaceToStringMap extracts a map[string]string from a map[string]interface{}
func interfaceToStringMap(obj interface{}) (map[string]string, bool) {
if obj == nil {
return nil, false
}
lm, ok := obj.(map[string]interface{})
if !ok {
return nil, false
}
existing := make(map[string]string)
for k, v := range lm {
switch t := v.(type) {
case string:
existing[k] = t
}
}
return existing, true
}
// mapToGeneric converts a map[string]string into a map[string]interface{}
func mapToGeneric(obj map[string]string) map[string]interface{} {
if obj == nil {
return nil
}
res := make(map[string]interface{})
for k, v := range obj {
res[k] = v
}
return res
}
// MergeInto merges items from a src map into a dst map.
// Returns an error when the maps are not of the same type.
// Flags:
// - ErrorOnExistingDstKey
// When set: Return an error if any of the dst keys is already set.
// - ErrorOnDifferentDstKeyValue
// When set: Return an error if any of the dst keys is already set
// to a different value than src key.
// - OverwriteDstKey
// When set: Overwrite existing dst key value with src key value.
func MergeInto(dst, src interface{}, flags int) error {
dstVal := reflect.ValueOf(dst)
srcVal := reflect.ValueOf(src)
if dstVal.Kind() != reflect.Map {
return fmt.Errorf("dst is not a valid map: %v", dstVal.Kind())
}
if srcVal.Kind() != reflect.Map {
return fmt.Errorf("src is not a valid map: %v", srcVal.Kind())
}
if dstTyp, srcTyp := dstVal.Type(), srcVal.Type(); !dstTyp.AssignableTo(srcTyp) {
return fmt.Errorf("type mismatch, can't assign '%v' to '%v'", srcTyp, dstTyp)
}
if dstVal.IsNil() {
return fmt.Errorf("dst value is nil")
}
if srcVal.IsNil() {
// Nothing to merge
return nil
}
for _, k := range srcVal.MapKeys() {
if dstVal.MapIndex(k).IsValid() {
if flags&ErrorOnExistingDstKey != 0 {
return fmt.Errorf("dst key already set (ErrorOnExistingDstKey=1), '%v'='%v'", k, dstVal.MapIndex(k))
}
if dstVal.MapIndex(k).String() != srcVal.MapIndex(k).String() {
if flags&ErrorOnDifferentDstKeyValue != 0 {
return fmt.Errorf("dst key already set to a different value (ErrorOnDifferentDstKeyValue=1), '%v'='%v'", k, dstVal.MapIndex(k))
}
if flags&OverwriteExistingDstKey != 0 {
dstVal.SetMapIndex(k, srcVal.MapIndex(k))
}
}
} else {
dstVal.SetMapIndex(k, srcVal.MapIndex(k))
}
}
return nil
}

21
vendor/github.com/openshift/origin/pkg/util/strings.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
package util
import "sort"
// UniqueStrings returns a sorted, uniquified slice of the specified strings
func UniqueStrings(strings []string) []string {
m := make(map[string]bool, len(strings))
for _, s := range strings {
m[s] = true
}
i := 0
strings = make([]string, len(m), len(m))
for s := range m {
strings[i] = s
i++
}
sort.Strings(strings)
return strings
}