Skip to content

Commit

Permalink
Merge pull request #11380 from bparees/merging
Browse files Browse the repository at this point in the history
Merged by openshift-bot
  • Loading branch information
OpenShift Bot committed Oct 24, 2016
2 parents 22f150d + c1e03fe commit 1566e8d
Show file tree
Hide file tree
Showing 50 changed files with 1,431 additions and 605 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion api/swagger-spec/oapi-v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -21416,7 +21416,8 @@
"description": "BuildConfigSpec describes when and how builds are created",
"required": [
"triggers",
"strategy"
"strategy",
"nodeSelector"
],
"properties": {
"triggers": {
Expand Down Expand Up @@ -21462,6 +21463,10 @@
"type": "integer",
"format": "int64",
"description": "completionDeadlineSeconds is an optional duration in seconds, counted from the time when a build pod gets scheduled in the system, that the build may be active on a node before the system actively tries to terminate the build; value must be positive integer"
},
"nodeSelector": {
"type": "object",
"description": "nodeSelector is a selector which must be true for the build pod to fit on a node If nil, it can be overridden by default build nodeselector values for the cluster. If set to an empty map or a map with any values, default build nodeselector values are ignored."
}
}
},
Expand Down Expand Up @@ -22477,6 +22482,7 @@
"description": "BuildSpec has the information to represent a build and also additional information about a build",
"required": [
"strategy",
"nodeSelector",
"triggeredBy"
],
"properties": {
Expand Down Expand Up @@ -22513,6 +22519,10 @@
"format": "int64",
"description": "completionDeadlineSeconds is an optional duration in seconds, counted from the time when a build pod gets scheduled in the system, that the build may be active on a node before the system actively tries to terminate the build; value must be positive integer"
},
"nodeSelector": {
"type": "object",
"description": "nodeSelector is a selector which must be true for the build pod to fit on a node If nil, it can be overridden by default build nodeselector values for the cluster. If set to an empty map or a map with any values, default build nodeselector values are ignored."
},
"triggeredBy": {
"type": "array",
"items": {
Expand Down
12 changes: 11 additions & 1 deletion api/swagger-spec/openshift-openapi-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -44686,14 +44686,19 @@
"description": "BuildConfigSpec describes when and how builds are created",
"required": [
"triggers",
"strategy"
"strategy",
"nodeSelector"
],
"properties": {
"completionDeadlineSeconds": {
"description": "completionDeadlineSeconds is an optional duration in seconds, counted from the time when a build pod gets scheduled in the system, that the build may be active on a node before the system actively tries to terminate the build; value must be positive integer",
"type": "integer",
"format": "int64"
},
"nodeSelector": {
"description": "nodeSelector is a selector which must be true for the build pod to fit on a node If nil, it can be overridden by default build nodeselector values for the cluster. If set to an empty map or a map with any values, default build nodeselector values are ignored.",
"type": "object"
},
"output": {
"$ref": "#/definitions/v1.BuildOutput"
},
Expand Down Expand Up @@ -44919,6 +44924,7 @@
"description": "BuildSpec has the information to represent a build and also additional information about a build",
"required": [
"strategy",
"nodeSelector",
"triggeredBy"
],
"properties": {
Expand All @@ -44927,6 +44933,10 @@
"type": "integer",
"format": "int64"
},
"nodeSelector": {
"description": "nodeSelector is a selector which must be true for the build pod to fit on a node If nil, it can be overridden by default build nodeselector values for the cluster. If set to an empty map or a map with any values, default build nodeselector values are ignored.",
"type": "object"
},
"output": {
"$ref": "#/definitions/v1.BuildOutput"
},
Expand Down
2 changes: 1 addition & 1 deletion docs/man/man1/openshift-start-kubernetes-apiserver.1
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ This command launches an instance of the Kubernetes apiserver (kube\-apiserver).

.PP
\fB\-\-admission\-control\fP="AlwaysAdmit"
Ordered list of plug\-ins to do admission control of resources into cluster. Comma\-delimited list of: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, BuildByStrategy, BuildDefaults, BuildOverrides, ClusterResourceOverride, DefaultStorageClass, DenyEscalatingExec, DenyExecOnPrivileged, ExternalIPRanger, ImagePolicyWebhook, InitialResources, LimitPodHardAntiAffinityTopology, LimitRanger, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, OriginNamespaceLifecycle, OriginPodNodeEnvironment, OwnerReferencesPermissionEnforcement, PersistentVolumeLabel, PodNodeConstraints, PodSecurityPolicy, ProjectRequestLimit, ResourceQuota, RunOnceDuration, SCCExecRestrictions, SecurityContextConstraint, SecurityContextDeny, ServiceAccount, openshift.io/ClusterResourceQuota, openshift.io/ImageLimitRange, openshift.io/ImagePolicy, openshift.io/JenkinsBootstrapper, openshift.io/OriginResourceQuota, openshift.io/RestrictedEndpointsAdmission.
Ordered list of plug\-ins to do admission control of resources into cluster. Comma\-delimited list of: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, BuildByStrategy, ClusterResourceOverride, DefaultStorageClass, DenyEscalatingExec, DenyExecOnPrivileged, ExternalIPRanger, ImagePolicyWebhook, InitialResources, LimitPodHardAntiAffinityTopology, LimitRanger, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, OriginNamespaceLifecycle, OriginPodNodeEnvironment, OwnerReferencesPermissionEnforcement, PersistentVolumeLabel, PodNodeConstraints, PodSecurityPolicy, ProjectRequestLimit, ResourceQuota, RunOnceDuration, SCCExecRestrictions, SecurityContextConstraint, SecurityContextDeny, ServiceAccount, openshift.io/ClusterResourceQuota, openshift.io/ImageLimitRange, openshift.io/ImagePolicy, openshift.io/JenkinsBootstrapper, openshift.io/OriginResourceQuota, openshift.io/RestrictedEndpointsAdmission.

.PP
\fB\-\-admission\-control\-config\-file\fP=""
Expand Down
98 changes: 19 additions & 79 deletions pkg/build/admission/buildpodutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,51 @@ import (
"errors"
"fmt"

"k8s.io/kubernetes/pkg/admission"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"

buildapi "github.com/openshift/origin/pkg/build/api"
)

// IsBuildPod returns true if a pod is a pod generated for a Build
func IsBuildPod(a admission.Attributes) bool {
if a.GetResource().GroupResource() != kapi.Resource("pods") {
return false
}
if len(a.GetSubresource()) != 0 {
return false
}
pod, err := GetPod(a)
if err != nil {
return false
}
return hasBuildAnnotation(pod) && hasBuildEnvVar(pod)
}

// GetBuild returns a build object encoded in a pod's BUILD environment variable along with
// GetBuildFromPod returns a build object encoded in a pod's BUILD environment variable along with
// its encoding version
func GetBuild(a admission.Attributes) (*buildapi.Build, unversioned.GroupVersion, error) {
pod, err := GetPod(a)
func GetBuildFromPod(pod *kapi.Pod) (*buildapi.Build, unversioned.GroupVersion, error) {
envVar, err := buildEnvVar(pod)
if err != nil {
return nil, unversioned.GroupVersion{}, err
return nil, unversioned.GroupVersion{}, fmt.Errorf("unable to get build from pod: %v", err)
}
build, version, err := getBuildFromPod(pod)
obj, groupVersionKind, err := kapi.Codecs.UniversalDecoder().Decode([]byte(envVar.Value), nil, nil)
if err != nil {
return nil, unversioned.GroupVersion{}, admission.NewForbidden(a, fmt.Errorf("unable to get build from pod: %v", err))
return nil, unversioned.GroupVersion{}, fmt.Errorf("unable to get build from pod: %v", err)
}
return build, version, nil
}

// GetPod returns a pod from an admission attributes object
func GetPod(a admission.Attributes) (*kapi.Pod, error) {
pod, isPod := a.GetObject().(*kapi.Pod)
if !isPod {
return nil, admission.NewForbidden(a, fmt.Errorf("unrecognized request object: %#v", a.GetObject()))
build, ok := obj.(*buildapi.Build)
if !ok {
return nil, unversioned.GroupVersion{}, fmt.Errorf("unable to get build from pod: %v", errors.New("decoded object is not of type Build"))
}
return pod, nil
return build, groupVersionKind.GroupVersion(), nil
}

// SetBuild encodes a build object and sets it in a pod's BUILD environment variable
func SetBuild(a admission.Attributes, build *buildapi.Build, groupVersion unversioned.GroupVersion) error {
pod, err := GetPod(a)
// SetBuildInPod encodes a build object and sets it in a pod's BUILD environment variable
func SetBuildInPod(pod *kapi.Pod, build *buildapi.Build, groupVersion unversioned.GroupVersion) error {
envVar, err := buildEnvVar(pod)
if err != nil {
return err
return fmt.Errorf("unable to set build in pod: %v", err)
}

err = setBuildInPod(build, pod, groupVersion)
encodedBuild, err := runtime.Encode(kapi.Codecs.LegacyCodec(groupVersion), build)
if err != nil {
return admission.NewForbidden(a, fmt.Errorf("unable to set build in pod: %v", err))
return fmt.Errorf("unable to set build in pod: %v", err)
}

envVar.Value = string(encodedBuild)
return nil
}

// SetBuildLogLevel extracts BUILD_LOGLEVEL from the Build environment
// SetPodLogLevelFromBuild extracts BUILD_LOGLEVEL from the Build environment
// and feeds it as an argument to the Pod's entrypoint. The BUILD_LOGLEVEL
// environment variable may have been set in multiple ways: a default value,
// by a BuildConfig, or by the BuildDefaults admission plugin. In this method
// we finally act on the value by injecting it into the Pod.
func SetBuildLogLevel(attributes admission.Attributes, build *buildapi.Build) error {
pod, err := GetPod(attributes)
if err != nil {
return err
}

func SetPodLogLevelFromBuild(pod *kapi.Pod, build *buildapi.Build) error {
var envs []kapi.EnvVar

// Check whether the build strategy supports --loglevel parameter.
Expand All @@ -102,39 +75,6 @@ func SetBuildLogLevel(attributes admission.Attributes, build *buildapi.Build) er
return nil
}

// getBuildFromPod detects the encoding of a Build in a pod and returns the Build
// object along with its detected version.
func getBuildFromPod(pod *kapi.Pod) (*buildapi.Build, unversioned.GroupVersion, error) {
envVar, err := buildEnvVar(pod)
if err != nil {
return nil, unversioned.GroupVersion{}, err
}
obj, groupVersionKind, err := kapi.Codecs.UniversalDecoder().Decode([]byte(envVar.Value), nil, nil)
if err != nil {
return nil, unversioned.GroupVersion{}, err
}
build, ok := obj.(*buildapi.Build)
if !ok {
return nil, unversioned.GroupVersion{}, errors.New("decoded object is not of type Build")
}
return build, groupVersionKind.GroupVersion(), nil
}

// setBuildInPod encodes a build with the given version and sets it in the BUILD environment variable
// of the pod.
func setBuildInPod(build *buildapi.Build, pod *kapi.Pod, groupVersion unversioned.GroupVersion) error {
envVar, err := buildEnvVar(pod)
if err != nil {
return err
}
encodedBuild, err := runtime.Encode(kapi.Codecs.LegacyCodec(groupVersion), build)
if err != nil {
return err
}
envVar.Value = string(encodedBuild)
return nil
}

func buildEnvVar(pod *kapi.Pod) (*kapi.EnvVar, error) {
if len(pod.Spec.Containers) == 0 {
return nil, errors.New("pod has no containers")
Expand Down
42 changes: 4 additions & 38 deletions pkg/build/admission/buildpodutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,13 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"

u "github.com/openshift/origin/pkg/build/admission/testutil"
buildapi "github.com/openshift/origin/pkg/build/api"
)

func TestIsBuildPod(t *testing.T) {
tests := []struct {
pod *u.TestPod
expected bool
}{
{
pod: u.Pod().WithAnnotation("foo", "bar"),
expected: false,
},
{
pod: u.Pod().WithEnvVar("BUILD", "blah"),
expected: false,
},
{
pod: u.Pod().WithAnnotation(buildapi.BuildAnnotation, "build"),
expected: false,
},
{
pod: u.Pod().
WithAnnotation(buildapi.BuildAnnotation, "build").
WithEnvVar("BUILD", "true"),
expected: true,
},
}

for _, tc := range tests {
actual := IsBuildPod(tc.pod.ToAttributes())
if actual != tc.expected {
t.Errorf("unexpected result (%v) for pod %#v", actual, tc.pod)
}
}
}

func TestGetBuild(t *testing.T) {
build := u.Build().WithDockerStrategy()
for _, version := range []string{"v1"} {
pod := u.Pod().WithBuild(t, build.AsBuild(), version)
resultBuild, resultVersion, err := GetBuild(pod.ToAttributes())
resultBuild, resultVersion, err := GetBuildFromPod((*kapi.Pod)(pod))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -69,7 +35,7 @@ func TestSetBuild(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = SetBuild(pod.ToAttributes(), build.AsBuild(), groupVersion)
err = SetBuildInPod((*kapi.Pod)(pod), build.AsBuild(), groupVersion)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -83,7 +49,7 @@ func TestSetBuild(t *testing.T) {
func TestSetBuildLogLevel(t *testing.T) {
build := u.Build().WithSourceStrategy()
pod := u.Pod().WithEnvVar("BUILD", "foo")
SetBuildLogLevel(pod.ToAttributes(), build.AsBuild())
SetPodLogLevelFromBuild((*kapi.Pod)(pod), build.AsBuild())

if len(pod.Spec.Containers[0].Args) == 0 {
t.Errorf("Builds pod loglevel was not set")
Expand All @@ -96,7 +62,7 @@ func TestSetBuildLogLevel(t *testing.T) {
build = u.Build().WithSourceStrategy()
pod = u.Pod().WithEnvVar("BUILD", "foo")
build.Spec.Strategy.SourceStrategy.Env = []kapi.EnvVar{{Name: "BUILD_LOGLEVEL", Value: "7", ValueFrom: nil}}
SetBuildLogLevel(pod.ToAttributes(), build.AsBuild())
SetPodLogLevelFromBuild((*kapi.Pod)(pod), build.AsBuild())

if pod.Spec.Containers[0].Args[0] != "--loglevel=7" {
t.Errorf("Build pod loglevel was not transferred from BUILD_LOGLEVEL environment variable: %#v", pod)
Expand Down
19 changes: 9 additions & 10 deletions pkg/build/admission/config.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
package admission

import (
"io"
"io/ioutil"
"reflect"
"github.com/golang/glog"

"k8s.io/kubernetes/pkg/runtime"

configapi "github.com/openshift/origin/pkg/cmd/server/api"
configlatest "github.com/openshift/origin/pkg/cmd/server/api/latest"
"github.com/openshift/origin/pkg/cmd/util/pluginconfig"
)

// ReadPluginConfig will read a plugin configuration object from a reader stream
func ReadPluginConfig(reader io.Reader, config runtime.Object) error {
if reader == nil || reflect.ValueOf(reader).IsNil() {
func ReadPluginConfig(pluginConfig map[string]configapi.AdmissionPluginConfig, name string, config runtime.Object) error {

configFilePath, err := pluginconfig.GetPluginConfigFile(pluginConfig, name, "")
if configFilePath == "" {
return nil
}

configBytes, err := ioutil.ReadAll(reader)
if err != nil {
return err
}
err = configlatest.ReadYAMLInto(configBytes, config)
err = configlatest.ReadYAMLFileInto(configFilePath, config)
if err != nil {
glog.Errorf("couldn't open plugin configuration %s: %#v", configFilePath, err)
return err
}
return nil
Expand Down
Loading

0 comments on commit 1566e8d

Please sign in to comment.