switch from godep to glide

This commit is contained in:
Tomas Kral
2016-12-07 19:57:19 +01:00
parent 862419b836
commit fe679fbca6
861 changed files with 16916 additions and 81678 deletions
+54 -12
View File
@@ -19,6 +19,12 @@ const (
BuildCloneAnnotation = "openshift.io/build.clone-of"
// BuildPodNameAnnotation is an annotation whose value is the name of the pod running this build
BuildPodNameAnnotation = "openshift.io/build.pod-name"
// BuildJenkinsStatusJSONAnnotation is an annotation holding the Jenkins status information
BuildJenkinsStatusJSONAnnotation = "openshift.io/jenkins-status-json"
// BuildJenkinsLogURLAnnotation is an annotation holding a link to the Jenkins build console log
BuildJenkinsLogURLAnnotation = "openshift.io/jenkins-log-url"
// BuildJenkinsBuildURIAnnotation is an annotation holding a link to the Jenkins build
BuildJenkinsBuildURIAnnotation = "openshift.io/jenkins-build-uri"
// BuildLabel is the key of a Pod label whose value is the Name of a Build which is run.
// NOTE: The value for this label may not contain the entire Build name because it will be
// truncated to maximum label length.
@@ -106,8 +112,22 @@ type CommonSpec struct {
// be active on a node before the system actively tries to terminate the
// build; value must be positive integer.
CompletionDeadlineSeconds *int64
// 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.
NodeSelector map[string]string
}
const (
BuildTriggerCauseManualMsg = "Manually triggered"
BuildTriggerCauseConfigMsg = "Build configuration change"
BuildTriggerCauseImageMsg = "Image change"
BuildTriggerCauseGithubMsg = "GitHub WebHook"
BuildTriggerCauseGenericMsg = "Generic WebHook"
)
// BuildTriggerCause holds information about a triggered build. It is used for
// displaying build trigger data for each build and build configuration in oc
// describe. It is also used to describe which triggers led to the most recent
@@ -240,32 +260,32 @@ const (
// StatusReasonCannotCreateBuildPodSpec is an error condition when the build
// strategy cannot create a build pod spec.
StatusReasonCannotCreateBuildPodSpec = "CannotCreateBuildPodSpec"
StatusReasonCannotCreateBuildPodSpec StatusReason = "CannotCreateBuildPodSpec"
// StatusReasonCannotCreateBuildPod is an error condition when a build pod
// cannot be created.
StatusReasonCannotCreateBuildPod = "CannotCreateBuildPod"
StatusReasonCannotCreateBuildPod StatusReason = "CannotCreateBuildPod"
// StatusReasonInvalidOutputReference is an error condition when the build
// output is an invalid reference.
StatusReasonInvalidOutputReference = "InvalidOutputReference"
StatusReasonInvalidOutputReference StatusReason = "InvalidOutputReference"
// StatusReasonCancelBuildFailed is an error condition when cancelling a build
// fails.
StatusReasonCancelBuildFailed = "CancelBuildFailed"
StatusReasonCancelBuildFailed StatusReason = "CancelBuildFailed"
// StatusReasonBuildPodDeleted is an error condition when the build pod is
// deleted before build completion.
StatusReasonBuildPodDeleted = "BuildPodDeleted"
StatusReasonBuildPodDeleted StatusReason = "BuildPodDeleted"
// StatusReasonExceededRetryTimeout is an error condition when the build has
// not completed and retrying the build times out.
StatusReasonExceededRetryTimeout = "ExceededRetryTimeout"
StatusReasonExceededRetryTimeout StatusReason = "ExceededRetryTimeout"
// StatusReasonMissingPushSecret indicates that the build is missing required
// secret for pushing the output image.
// The build will stay in the pending state until the secret is created, or the build times out.
StatusReasonMissingPushSecret = "MissingPushSecret"
StatusReasonMissingPushSecret StatusReason = "MissingPushSecret"
)
// BuildSource is the input used for the build.
@@ -387,6 +407,18 @@ type GitSourceRevision struct {
Message string
}
// ProxyConfig defines what proxies to use for an operation
type ProxyConfig struct {
// HTTPProxy is a proxy used to reach the git repository over http
HTTPProxy *string
// HTTPSProxy is a proxy used to reach the git repository over https
HTTPSProxy *string
// NoProxy is the list of domains for which the proxy should not be used
NoProxy *string
}
// GitBuildSource defines the parameters of a Git SCM
type GitBuildSource struct {
// URI points to the source that will be built. The structure of the source
@@ -396,11 +428,8 @@ type GitBuildSource struct {
// Ref is the branch/tag/ref to build.
Ref string
// HTTPProxy is a proxy used to reach the git repository over http
HTTPProxy *string
// HTTPSProxy is a proxy used to reach the git repository over https
HTTPSProxy *string
// ProxyConfig defines the proxies to use for the git clone operation
ProxyConfig
}
// SourceControlUser defines the identity of a user of source control
@@ -646,6 +675,19 @@ type BuildOutput struct {
// up the authentication for executing the Docker push to authentication
// enabled Docker Registry (or Docker Hub).
PushSecret *kapi.LocalObjectReference
// ImageLabels define a list of labels that are applied to the resulting image. If there
// are multiple labels with the same name then the last one in the list is used.
ImageLabels []ImageLabel
}
// ImageLabel represents a label applied to the resulting image.
type ImageLabel struct {
// Name defines the name of the label. It must have non-zero length.
Name string
// Value defines the literal value of the label.
Value string
}
// BuildConfig is a template which can be used to create new builds.
+61 -13
View File
@@ -51,9 +51,11 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_GitSourceRevision, InType: reflect.TypeOf(&GitSourceRevision{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ImageChangeCause, InType: reflect.TypeOf(&ImageChangeCause{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ImageChangeTrigger, InType: reflect.TypeOf(&ImageChangeTrigger{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ImageLabel, InType: reflect.TypeOf(&ImageLabel{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ImageSource, InType: reflect.TypeOf(&ImageSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ImageSourcePath, InType: reflect.TypeOf(&ImageSourcePath{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_JenkinsPipelineBuildStrategy, InType: reflect.TypeOf(&JenkinsPipelineBuildStrategy{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ProxyConfig, InType: reflect.TypeOf(&ProxyConfig{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretBuildSource, InType: reflect.TypeOf(&SecretBuildSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretSpec, InType: reflect.TypeOf(&SecretSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SourceBuildStrategy, InType: reflect.TypeOf(&SourceBuildStrategy{})},
@@ -275,6 +277,15 @@ func DeepCopy_api_BuildOutput(in interface{}, out interface{}, c *conversion.Clo
} else {
out.PushSecret = nil
}
if in.ImageLabels != nil {
in, out := &in.ImageLabels, &out.ImageLabels
*out = make([]ImageLabel, len(*in))
for i := range *in {
(*out)[i] = (*in)[i]
}
} else {
out.ImageLabels = nil
}
return nil
}
}
@@ -635,6 +646,15 @@ func DeepCopy_api_CommonSpec(in interface{}, out interface{}, c *conversion.Clon
} else {
out.CompletionDeadlineSeconds = nil
}
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string)
for key, val := range *in {
(*out)[key] = val
}
} else {
out.NodeSelector = nil
}
return nil
}
}
@@ -766,19 +786,8 @@ func DeepCopy_api_GitBuildSource(in interface{}, out interface{}, c *conversion.
out := out.(*GitBuildSource)
out.URI = in.URI
out.Ref = in.Ref
if in.HTTPProxy != nil {
in, out := &in.HTTPProxy, &out.HTTPProxy
*out = new(string)
**out = **in
} else {
out.HTTPProxy = nil
}
if in.HTTPSProxy != nil {
in, out := &in.HTTPSProxy, &out.HTTPSProxy
*out = new(string)
**out = **in
} else {
out.HTTPSProxy = nil
if err := DeepCopy_api_ProxyConfig(&in.ProxyConfig, &out.ProxyConfig, c); err != nil {
return err
}
return nil
}
@@ -881,6 +890,16 @@ func DeepCopy_api_ImageChangeTrigger(in interface{}, out interface{}, c *convers
}
}
func DeepCopy_api_ImageLabel(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ImageLabel)
out := out.(*ImageLabel)
out.Name = in.Name
out.Value = in.Value
return nil
}
}
func DeepCopy_api_ImageSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ImageSource)
@@ -926,6 +945,35 @@ func DeepCopy_api_JenkinsPipelineBuildStrategy(in interface{}, out interface{},
}
}
func DeepCopy_api_ProxyConfig(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ProxyConfig)
out := out.(*ProxyConfig)
if in.HTTPProxy != nil {
in, out := &in.HTTPProxy, &out.HTTPProxy
*out = new(string)
**out = **in
} else {
out.HTTPProxy = nil
}
if in.HTTPSProxy != nil {
in, out := &in.HTTPSProxy, &out.HTTPSProxy
*out = new(string)
**out = **in
} else {
out.HTTPSProxy = nil
}
if in.NoProxy != nil {
in, out := &in.NoProxy, &out.NoProxy
*out = new(string)
**out = **in
} else {
out.NoProxy = nil
}
return nil
}
}
func DeepCopy_api_SecretBuildSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*SecretBuildSource)
-109
View File
@@ -1,109 +0,0 @@
package client
import (
buildapi "github.com/openshift/origin/pkg/build/api"
osclient "github.com/openshift/origin/pkg/client"
kapi "k8s.io/kubernetes/pkg/api"
)
// BuildConfigGetter provides methods for getting BuildConfigs
type BuildConfigGetter interface {
Get(namespace, name string) (*buildapi.BuildConfig, error)
}
// BuildConfigUpdater provides methods for updating BuildConfigs
type BuildConfigUpdater interface {
Update(buildConfig *buildapi.BuildConfig) error
}
// OSClientBuildConfigClient delegates get and update operations to the OpenShift client interface
type OSClientBuildConfigClient struct {
Client osclient.Interface
}
// NewOSClientBuildConfigClient creates a new build config client that uses an openshift client to create and get BuildConfigs
func NewOSClientBuildConfigClient(client osclient.Interface) *OSClientBuildConfigClient {
return &OSClientBuildConfigClient{Client: client}
}
// Get returns a BuildConfig using the OpenShift client.
func (c OSClientBuildConfigClient) Get(namespace, name string) (*buildapi.BuildConfig, error) {
return c.Client.BuildConfigs(namespace).Get(name)
}
// Update updates a BuildConfig using the OpenShift client.
func (c OSClientBuildConfigClient) Update(buildConfig *buildapi.BuildConfig) error {
_, err := c.Client.BuildConfigs(buildConfig.Namespace).Update(buildConfig)
return err
}
// BuildUpdater provides methods for updating existing Builds.
type BuildUpdater interface {
Update(namespace string, build *buildapi.Build) error
}
// BuildLister provides methods for listing the Builds.
type BuildLister interface {
List(namespace string, opts kapi.ListOptions) (*buildapi.BuildList, error)
}
// OSClientBuildClient deletes build create and update operations to the OpenShift client interface
type OSClientBuildClient struct {
Client osclient.Interface
}
// NewOSClientBuildClient creates a new build client that uses an openshift client to update builds
func NewOSClientBuildClient(client osclient.Interface) *OSClientBuildClient {
return &OSClientBuildClient{Client: client}
}
// Update updates builds using the OpenShift client.
func (c OSClientBuildClient) Update(namespace string, build *buildapi.Build) error {
_, e := c.Client.Builds(namespace).Update(build)
return e
}
// List lists the builds using the OpenShift client.
func (c OSClientBuildClient) List(namespace string, opts kapi.ListOptions) (*buildapi.BuildList, error) {
return c.Client.Builds(namespace).List(opts)
}
// BuildCloner provides methods for cloning builds
type BuildCloner interface {
Clone(namespace string, request *buildapi.BuildRequest) (*buildapi.Build, error)
}
// OSClientBuildClonerClient creates a new build client that uses an openshift client to clone builds
type OSClientBuildClonerClient struct {
Client osclient.Interface
}
// NewOSClientBuildClonerClient creates a new build client that uses an openshift client to clone builds
func NewOSClientBuildClonerClient(client osclient.Interface) *OSClientBuildClonerClient {
return &OSClientBuildClonerClient{Client: client}
}
// Clone generates new build for given build name
func (c OSClientBuildClonerClient) Clone(namespace string, request *buildapi.BuildRequest) (*buildapi.Build, error) {
return c.Client.Builds(namespace).Clone(request)
}
// BuildConfigInstantiator provides methods for instantiating builds from build configs
type BuildConfigInstantiator interface {
Instantiate(namespace string, request *buildapi.BuildRequest) (*buildapi.Build, error)
}
// OSClientBuildConfigInstantiatorClient creates a new build client that uses an openshift client to create builds
type OSClientBuildConfigInstantiatorClient struct {
Client osclient.Interface
}
// NewOSClientBuildConfigInstantiatorClient creates a new build client that uses an openshift client to create builds
func NewOSClientBuildConfigInstantiatorClient(client osclient.Interface) *OSClientBuildConfigInstantiatorClient {
return &OSClientBuildConfigInstantiatorClient{Client: client}
}
// Instantiate generates new build for given buildConfig
func (c OSClientBuildConfigInstantiatorClient) Instantiate(namespace string, request *buildapi.BuildRequest) (*buildapi.Build, error) {
return c.Client.BuildConfigs(namespace).Instantiate(request)
}
-2
View File
@@ -1,2 +0,0 @@
// Package cmd provides command helpers for builds
package cmd
-150
View File
@@ -1,150 +0,0 @@
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
}
-351
View File
@@ -1,351 +0,0 @@
package analysis
import (
"fmt"
"strings"
"time"
"github.com/gonum/graph"
"github.com/gonum/graph/topo"
"k8s.io/kubernetes/pkg/api/unversioned"
osgraph "github.com/openshift/origin/pkg/api/graph"
buildapi "github.com/openshift/origin/pkg/build/api"
buildedges "github.com/openshift/origin/pkg/build/graph"
buildgraph "github.com/openshift/origin/pkg/build/graph/nodes"
imageapi "github.com/openshift/origin/pkg/image/api"
imageedges "github.com/openshift/origin/pkg/image/graph"
imagegraph "github.com/openshift/origin/pkg/image/graph/nodes"
)
const (
TagNotAvailableWarning = "ImageStreamTagNotAvailable"
LatestBuildFailedErr = "LatestBuildFailed"
MissingRequiredRegistryErr = "MissingRequiredRegistry"
MissingOutputImageStreamErr = "MissingOutputImageStream"
CyclicBuildConfigWarning = "CyclicBuildConfig"
MissingImageStreamTagWarning = "MissingImageStreamTag"
MissingImageStreamImageWarning = "MissingImageStreamImage"
)
// FindUnpushableBuildConfigs checks all build configs that will output to an IST backed by an ImageStream and checks to make sure their builds can push.
func FindUnpushableBuildConfigs(g osgraph.Graph, f osgraph.Namer) []osgraph.Marker {
markers := []osgraph.Marker{}
// note, unlike with Inputs, ImageStreamImage is not a valid type for build output
bc:
for _, bcNode := range g.NodesByKind(buildgraph.BuildConfigNodeKind) {
for _, istNode := range g.SuccessorNodesByEdgeKind(bcNode, buildedges.BuildOutputEdgeKind) {
for _, uncastImageStreamNode := range g.SuccessorNodesByEdgeKind(istNode, imageedges.ReferencedImageStreamGraphEdgeKind) {
imageStreamNode := uncastImageStreamNode.(*imagegraph.ImageStreamNode)
if !imageStreamNode.IsFound {
markers = append(markers, osgraph.Marker{
Node: bcNode,
RelatedNodes: []graph.Node{istNode},
Severity: osgraph.ErrorSeverity,
Key: MissingOutputImageStreamErr,
Message: fmt.Sprintf("%s is pushing to %s, but the image stream for that tag does not exist.",
f.ResourceName(bcNode), f.ResourceName(istNode)),
})
continue
}
if len(imageStreamNode.Status.DockerImageRepository) == 0 {
markers = append(markers, osgraph.Marker{
Node: bcNode,
RelatedNodes: []graph.Node{istNode},
Severity: osgraph.ErrorSeverity,
Key: MissingRequiredRegistryErr,
Message: fmt.Sprintf("%s is pushing to %s, but the administrator has not configured the integrated Docker registry.",
f.ResourceName(bcNode), f.ResourceName(istNode)),
Suggestion: osgraph.Suggestion("oc adm registry -h"),
})
continue bc
}
}
}
}
return markers
}
// FindMissingInputImageStreams checks all build configs and confirms that their From element exists
//
// Precedence of failures:
// 1. A build config's input points to an image stream that does not exist
// 2. A build config's input uses an image stream tag reference in an existing image stream, but no images within the image stream have that tag assigned
// 3. A build config's input uses an image stream image reference in an exisiting image stream, but no images within the image stream have the supplied image hexadecimal ID
func FindMissingInputImageStreams(g osgraph.Graph, f osgraph.Namer) []osgraph.Marker {
markers := []osgraph.Marker{}
for _, bcNode := range g.NodesByKind(buildgraph.BuildConfigNodeKind) {
for _, bcInputNode := range g.PredecessorNodesByEdgeKind(bcNode, buildedges.BuildInputImageEdgeKind) {
switch bcInputNode.(type) {
case *imagegraph.ImageStreamTagNode:
for _, uncastImageStreamNode := range g.SuccessorNodesByEdgeKind(bcInputNode, imageedges.ReferencedImageStreamGraphEdgeKind) {
imageStreamNode := uncastImageStreamNode.(*imagegraph.ImageStreamNode)
// note, BuildConfig.Spec.BuildSpec.Strategy.[Docker|Source|Custom]Stragegy.From Input of ImageStream has been converted to ImageStreamTag on the vX to api conversion
// prior to our reaching this point in the code; so there is not need to check for that type vs. ImageStreamTag or ImageStreamImage;
tagNode, _ := bcInputNode.(*imagegraph.ImageStreamTagNode)
imageStream := imageStreamNode.Object().(*imageapi.ImageStream)
if _, ok := imageStream.Status.Tags[tagNode.ImageTag()]; !ok {
markers = append(markers, getImageStreamTagMarker(g, f, bcInputNode, imageStreamNode, tagNode, bcNode))
}
}
case *imagegraph.ImageStreamImageNode:
for _, uncastImageStreamNode := range g.SuccessorNodesByEdgeKind(bcInputNode, imageedges.ReferencedImageStreamImageGraphEdgeKind) {
imageStreamNode := uncastImageStreamNode.(*imagegraph.ImageStreamNode)
imageNode, _ := bcInputNode.(*imagegraph.ImageStreamImageNode)
imageStream := imageStreamNode.Object().(*imageapi.ImageStream)
found, imageID := validImageStreamImage(imageNode, imageStream)
if !found {
markers = append(markers, getImageStreamImageMarker(g, f, bcNode, bcInputNode, imageStreamNode, imageNode, imageStream, imageID))
}
}
}
}
}
return markers
}
// FindCircularBuilds checks all build configs for cycles
func FindCircularBuilds(g osgraph.Graph, f osgraph.Namer) []osgraph.Marker {
// Filter out all but ImageStreamTag and BuildConfig nodes
nodeFn := osgraph.NodesOfKind(imagegraph.ImageStreamTagNodeKind, buildgraph.BuildConfigNodeKind)
// Filter out all but BuildInputImage and BuildOutput edges
edgeFn := osgraph.EdgesOfKind(buildedges.BuildInputImageEdgeKind, buildedges.BuildOutputEdgeKind)
// Create desired subgraph
sub := g.Subgraph(nodeFn, edgeFn)
markers := []osgraph.Marker{}
// Check for cycles
for _, cycle := range topo.CyclesIn(sub) {
nodeNames := []string{}
for _, node := range cycle {
nodeNames = append(nodeNames, f.ResourceName(node))
}
markers = append(markers, osgraph.Marker{
Node: cycle[0],
RelatedNodes: cycle,
Severity: osgraph.WarningSeverity,
Key: CyclicBuildConfigWarning,
Message: fmt.Sprintf("Cycle detected in build configurations: %s", strings.Join(nodeNames, " -> ")),
})
}
return markers
}
// multiBCStartBuildSuggestion builds the `oc start-build` suggestion string with multiple build configs
func multiBCStartBuildSuggestion(bcNodes []*buildgraph.BuildConfigNode) string {
var ret string
if len(bcNodes) > 1 {
ret = "Run one of the following commands: "
}
for i, bcNode := range bcNodes {
// use of f.ResourceName(bcNode) will produce a string like oc start-build BuildConfig|example/ruby-hello-world
ret = ret + fmt.Sprintf("oc start-build %s", bcNode.BuildConfig.GetName())
if i < (len(bcNodes) - 1) {
ret = ret + ", "
}
}
return ret
}
// bcNodesToRelatedNodes takes an array of BuildConfigNode's and returns an array of graph.Node's for the Marker.RelatedNodes field
func bcNodesToRelatedNodes(bcNodes []*buildgraph.BuildConfigNode) []graph.Node {
relatedNodes := []graph.Node{}
for _, bcNode := range bcNodes {
relatedNodes = append(relatedNodes, graph.Node(bcNode))
}
return relatedNodes
}
// findPendingTagMarkers is the guts behind FindPendingTags .... break out some of the content and reduce some indentation
func findPendingTagMarkers(istNode *imagegraph.ImageStreamTagNode, g osgraph.Graph, f osgraph.Namer) []osgraph.Marker {
markers := []osgraph.Marker{}
buildFound := false
bcNodes := buildedges.BuildConfigsForTag(g, graph.Node(istNode))
for _, bcNode := range bcNodes {
latestBuild := buildedges.GetLatestBuild(g, bcNode)
// A build config points to the non existent tag but no current build exists.
if latestBuild == nil {
continue
}
buildFound = true
// A build config points to the non existent tag but something is going on with
// the latest build.
// TODO: Handle other build phases.
switch latestBuild.Build.Status.Phase {
case buildapi.BuildPhaseCancelled:
// TODO: Add a warning here.
case buildapi.BuildPhaseError:
// TODO: Add a warning here.
case buildapi.BuildPhaseComplete:
// We should never hit this. The output of our build is missing but the build is complete.
// Most probably the user has messed up?
case buildapi.BuildPhaseFailed:
// Since the tag hasn't been populated yet, we assume there hasn't been a successful
// build so far.
markers = append(markers, osgraph.Marker{
Node: graph.Node(latestBuild),
RelatedNodes: []graph.Node{graph.Node(istNode), graph.Node(bcNode)},
Severity: osgraph.ErrorSeverity,
Key: LatestBuildFailedErr,
Message: fmt.Sprintf("%s has failed.", f.ResourceName(latestBuild)),
Suggestion: osgraph.Suggestion(fmt.Sprintf("Inspect the build failure with 'oc logs -f bc/%s'", bcNode.BuildConfig.GetName())),
})
default:
// Do nothing when latest build is new, pending, or running.
}
}
// if no current builds exist for any of the build configs, append marker for that
// but ignore ISTs which have no build configs
if !buildFound && len(bcNodes) > 0 {
markers = append(markers, osgraph.Marker{
Node: graph.Node(istNode),
RelatedNodes: bcNodesToRelatedNodes(bcNodes),
Severity: osgraph.WarningSeverity,
Key: TagNotAvailableWarning,
Message: fmt.Sprintf("%s needs to be imported or created by a build.", f.ResourceName(istNode)),
Suggestion: osgraph.Suggestion(multiBCStartBuildSuggestion(bcNodes)),
})
}
return markers
}
// FindPendingTags inspects all imageStreamTags that serve as outputs to builds.
//
// Precedence of failures:
// 1. A build config points to the non existent tag but no current build exists.
// 2. A build config points to the non existent tag but the latest build has failed.
func FindPendingTags(g osgraph.Graph, f osgraph.Namer) []osgraph.Marker {
markers := []osgraph.Marker{}
for _, uncastIstNode := range g.NodesByKind(imagegraph.ImageStreamTagNodeKind) {
istNode := uncastIstNode.(*imagegraph.ImageStreamTagNode)
if !istNode.Found() {
markers = append(markers, findPendingTagMarkers(istNode, g, f)...)
}
}
return markers
}
// getImageStreamTagMarker will return the appropriate marker for when a BuildConfig is missing its input ImageStreamTag
func getImageStreamTagMarker(g osgraph.Graph, f osgraph.Namer, bcInputNode graph.Node, imageStreamNode graph.Node, tagNode *imagegraph.ImageStreamTagNode, bcNode graph.Node) osgraph.Marker {
return osgraph.Marker{
Node: bcNode,
RelatedNodes: []graph.Node{bcInputNode,
imageStreamNode},
Severity: osgraph.WarningSeverity,
Key: MissingImageStreamImageWarning,
Message: fmt.Sprintf("%s builds from %s, but the image stream tag does not exist.", f.ResourceName(bcNode), f.ResourceName(bcInputNode)),
Suggestion: getImageStreamTagSuggestion(g, f, tagNode),
}
}
// getImageStreamTagSuggestion will return the appropriate marker Suggestion for when a BuildConfig is missing its input ImageStreamTag; in particular,
// it will determine whether or not another BuildConfig can produce the aforementioned ImageStreamTag
func getImageStreamTagSuggestion(g osgraph.Graph, f osgraph.Namer, tagNode *imagegraph.ImageStreamTagNode) osgraph.Suggestion {
bcs := []string{}
for _, bcNode := range g.PredecessorNodesByEdgeKind(tagNode, buildedges.BuildOutputEdgeKind) {
bcs = append(bcs, f.ResourceName(bcNode))
}
if len(bcs) == 1 {
return osgraph.Suggestion(fmt.Sprintf("oc start-build %s", bcs[0]))
}
if len(bcs) > 0 {
return osgraph.Suggestion(fmt.Sprintf("`oc start-build` with one of these: %s.", strings.Join(bcs[:], ",")))
}
return osgraph.Suggestion(fmt.Sprintf("%s needs to be imported.", f.ResourceName(tagNode)))
}
// getImageStreamImageMarker will return the appropriate marker for when a BuildConfig is missing its input ImageStreamImage
func getImageStreamImageMarker(g osgraph.Graph, f osgraph.Namer, bcNode graph.Node, bcInputNode graph.Node, imageStreamNode graph.Node, imageNode *imagegraph.ImageStreamImageNode, imageStream *imageapi.ImageStream, imageID string) osgraph.Marker {
return osgraph.Marker{
Node: bcNode,
RelatedNodes: []graph.Node{bcInputNode,
imageStreamNode},
Severity: osgraph.WarningSeverity,
Key: MissingImageStreamImageWarning,
Message: fmt.Sprintf("%s builds from %s, but the image stream image does not exist.", f.ResourceName(bcNode), f.ResourceName(bcInputNode)),
Suggestion: getImageStreamImageSuggestion(imageID, imageStream),
}
}
// getImageStreamImageSuggestion will return the appropriate marker Suggestion for when a BuildConfig is missing its input ImageStreamImage
func getImageStreamImageSuggestion(imageID string, imageStream *imageapi.ImageStream) osgraph.Suggestion {
// check the images stream to see if any import images are in flight or have failed
annotation, ok := imageStream.Annotations[imageapi.DockerImageRepositoryCheckAnnotation]
if !ok {
return osgraph.Suggestion(fmt.Sprintf("`oc import-image %s --from=` where `--from` specifies an image with hexadecimal ID %s", imageStream.GetName(), imageID))
}
if checkTime, err := time.Parse(time.RFC3339, annotation); err == nil {
// this time based annotation is set by pkg/image/controller/controller.go whenever import/tag operations are performed; unless
// in the midst of an import/tag operation, it stays set and serves as a timestamp for when the last operation occurred;
// so we will check if the image stream has been updated "recently";
// in case it is a slow link to the remote repo, see if if the check annotation occurred within the last 5 minutes; if so, consider that as potentially "in progress"
compareTime := checkTime.Add(5 * time.Minute)
currentTime, _ := time.Parse(time.RFC3339, unversioned.Now().UTC().Format(time.RFC3339))
if compareTime.Before(currentTime) {
return osgraph.Suggestion(fmt.Sprintf("`oc import-image %s --from=` where `--from` specifies an image with hexadecimal ID %s", imageStream.GetName(), imageID))
}
return osgraph.Suggestion(fmt.Sprintf("`oc import-image %s --from=` with hexadecimal ID %s possibly in progress", imageStream.GetName(), imageID))
}
return osgraph.Suggestion(fmt.Sprintf("Possible error occurred with `oc import-image %s --from=` with hexadecimal ID %s; inspect images stream annotations", imageStream.GetName(), imageID))
}
// validImageStreamImage will cycle through the imageStream.Status.Tags.[]TagEvent.DockerImageReference and determine whether an image with the hexadecimal image id
// associated with an ImageStreamImage reference in fact exists in a given ImageStream; on return, this method returns a true if does exist, and as well as the hexadecimal image
// id from the ImageStreamImage
func validImageStreamImage(imageNode *imagegraph.ImageStreamImageNode, imageStream *imageapi.ImageStream) (bool, string) {
dockerImageReference, err := imageapi.ParseDockerImageReference(imageNode.Name)
if err == nil {
for _, tagEventList := range imageStream.Status.Tags {
for _, tagEvent := range tagEventList.Items {
if strings.Contains(tagEvent.DockerImageReference, dockerImageReference.ID) {
return true, dockerImageReference.ID
}
}
}
return false, dockerImageReference.ID
}
return false, ""
}
-133
View File
@@ -1,133 +0,0 @@
package graph
import (
"github.com/gonum/graph"
kapi "k8s.io/kubernetes/pkg/api"
osgraph "github.com/openshift/origin/pkg/api/graph"
buildapi "github.com/openshift/origin/pkg/build/api"
buildgraph "github.com/openshift/origin/pkg/build/graph/nodes"
buildutil "github.com/openshift/origin/pkg/build/util"
imageapi "github.com/openshift/origin/pkg/image/api"
imagegraph "github.com/openshift/origin/pkg/image/graph/nodes"
)
const (
// BuildTriggerImageEdgeKind is an edge from an ImageStream to a BuildConfig that
// represents a trigger connection. Changes to the ImageStream will trigger a new build
// from the BuildConfig.
BuildTriggerImageEdgeKind = "BuildTriggerImage"
// BuildInputImageEdgeKind is an edge from an ImageStream to a BuildConfig, where the
// ImageStream is the source image for the build (builder in S2I builds, FROM in Docker builds,
// custom builder in Custom builds). The same ImageStream can also have a trigger
// relationship with the BuildConfig, but not necessarily.
BuildInputImageEdgeKind = "BuildInputImage"
// BuildOutputEdgeKind is an edge from a BuildConfig to an ImageStream. The ImageStream will hold
// the ouptut of the Builds created with that BuildConfig.
BuildOutputEdgeKind = "BuildOutput"
// BuildInputEdgeKind is an edge from a source repository to a BuildConfig. The source repository is the
// input source for the build.
BuildInputEdgeKind = "BuildInput"
// BuildEdgeKind goes from a BuildConfigNode to a BuildNode and indicates that the buildConfig owns the build
BuildEdgeKind = "Build"
)
// AddBuildEdges adds edges that connect a BuildConfig to Builds to the given graph
func AddBuildEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildConfigNode) {
for _, n := range g.(graph.Graph).Nodes() {
if buildNode, ok := n.(*buildgraph.BuildNode); ok {
if buildNode.Build.Namespace != node.BuildConfig.Namespace {
continue
}
if belongsToBuildConfig(node.BuildConfig, buildNode.Build) {
g.AddEdge(node, buildNode, BuildEdgeKind)
}
}
}
}
// AddAllBuildEdges adds build edges to all BuildConfig nodes in the given graph
func AddAllBuildEdges(g osgraph.MutableUniqueGraph) {
for _, node := range g.(graph.Graph).Nodes() {
if bcNode, ok := node.(*buildgraph.BuildConfigNode); ok {
AddBuildEdges(g, bcNode)
}
}
}
func imageRefNode(g osgraph.MutableUniqueGraph, ref *kapi.ObjectReference, bc *buildapi.BuildConfig) graph.Node {
if ref == nil {
return nil
}
switch ref.Kind {
case "DockerImage":
if ref, err := imageapi.ParseDockerImageReference(ref.Name); err == nil {
tag := ref.Tag
ref.Tag = ""
return imagegraph.EnsureDockerRepositoryNode(g, ref.String(), tag)
}
case "ImageStream":
return imagegraph.FindOrCreateSyntheticImageStreamTagNode(g, imagegraph.MakeImageStreamTagObjectMeta(defaultNamespace(ref.Namespace, bc.Namespace), ref.Name, imageapi.DefaultImageTag))
case "ImageStreamTag":
return imagegraph.FindOrCreateSyntheticImageStreamTagNode(g, imagegraph.MakeImageStreamTagObjectMeta2(defaultNamespace(ref.Namespace, bc.Namespace), ref.Name))
case "ImageStreamImage":
return imagegraph.FindOrCreateSyntheticImageStreamImageNode(g, imagegraph.MakeImageStreamImageObjectMeta(defaultNamespace(ref.Namespace, bc.Namespace), ref.Name))
}
return nil
}
// AddOutputEdges links the build config to its output image node.
func AddOutputEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildConfigNode) {
if node.BuildConfig.Spec.Output.To == nil {
return
}
out := imageRefNode(g, node.BuildConfig.Spec.Output.To, node.BuildConfig)
g.AddEdge(node, out, BuildOutputEdgeKind)
}
// AddInputEdges links the build config to its input image and source nodes.
func AddInputEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildConfigNode) {
if in := buildgraph.EnsureSourceRepositoryNode(g, node.BuildConfig.Spec.Source); in != nil {
g.AddEdge(in, node, BuildInputEdgeKind)
}
inputImage := buildutil.GetInputReference(node.BuildConfig.Spec.Strategy)
if input := imageRefNode(g, inputImage, node.BuildConfig); input != nil {
g.AddEdge(input, node, BuildInputImageEdgeKind)
}
}
// AddTriggerEdges links the build config to its trigger input image nodes.
func AddTriggerEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildConfigNode) {
for _, trigger := range node.BuildConfig.Spec.Triggers {
if trigger.Type != buildapi.ImageChangeBuildTriggerType {
continue
}
from := trigger.ImageChange.From
if trigger.ImageChange.From == nil {
from = buildutil.GetInputReference(node.BuildConfig.Spec.Strategy)
}
triggerNode := imageRefNode(g, from, node.BuildConfig)
g.AddEdge(triggerNode, node, BuildTriggerImageEdgeKind)
}
}
// AddInputOutputEdges links the build config to other nodes for the images and source repositories it depends on.
func AddInputOutputEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildConfigNode) *buildgraph.BuildConfigNode {
AddInputEdges(g, node)
AddTriggerEdges(g, node)
AddOutputEdges(g, node)
return node
}
// AddAllInputOutputEdges adds input and output edges for all BuildConfigs in the given graph
func AddAllInputOutputEdges(g osgraph.MutableUniqueGraph) {
for _, node := range g.(graph.Graph).Nodes() {
if bcNode, ok := node.(*buildgraph.BuildConfigNode); ok {
AddInputOutputEdges(g, bcNode)
}
}
}
-111
View File
@@ -1,111 +0,0 @@
package graph
import (
"sort"
"github.com/gonum/graph"
osgraph "github.com/openshift/origin/pkg/api/graph"
buildapi "github.com/openshift/origin/pkg/build/api"
buildgraph "github.com/openshift/origin/pkg/build/graph/nodes"
)
// RelevantBuilds returns the lastSuccessful build, lastUnsuccessful build, and a list of active builds
func RelevantBuilds(g osgraph.Graph, bcNode *buildgraph.BuildConfigNode) (*buildgraph.BuildNode, *buildgraph.BuildNode, []*buildgraph.BuildNode) {
var (
lastSuccessfulBuild *buildgraph.BuildNode
lastUnsuccessfulBuild *buildgraph.BuildNode
)
activeBuilds := []*buildgraph.BuildNode{}
allBuilds := []*buildgraph.BuildNode{}
uncastBuilds := g.SuccessorNodesByEdgeKind(bcNode, BuildEdgeKind)
for i := range uncastBuilds {
buildNode := uncastBuilds[i].(*buildgraph.BuildNode)
if belongsToBuildConfig(bcNode.BuildConfig, buildNode.Build) {
allBuilds = append(allBuilds, buildNode)
}
}
if len(allBuilds) == 0 {
return nil, nil, []*buildgraph.BuildNode{}
}
sort.Sort(RecentBuildReferences(allBuilds))
for i := range allBuilds {
switch allBuilds[i].Build.Status.Phase {
case buildapi.BuildPhaseComplete:
if lastSuccessfulBuild == nil {
lastSuccessfulBuild = allBuilds[i]
}
case buildapi.BuildPhaseFailed, buildapi.BuildPhaseCancelled, buildapi.BuildPhaseError:
if lastUnsuccessfulBuild == nil {
lastUnsuccessfulBuild = allBuilds[i]
}
default:
activeBuilds = append(activeBuilds, allBuilds[i])
}
}
return lastSuccessfulBuild, lastUnsuccessfulBuild, activeBuilds
}
func belongsToBuildConfig(config *buildapi.BuildConfig, b *buildapi.Build) bool {
if b.Labels == nil {
return false
}
if b.Annotations != nil && b.Annotations[buildapi.BuildConfigAnnotation] == config.Name {
return true
}
if b.Labels[buildapi.BuildConfigLabel] == config.Name {
return true
}
if b.Labels[buildapi.BuildConfigLabelDeprecated] == config.Name {
return true
}
return false
}
type RecentBuildReferences []*buildgraph.BuildNode
func (m RecentBuildReferences) Len() int { return len(m) }
func (m RecentBuildReferences) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m RecentBuildReferences) Less(i, j int) bool {
return m[i].Build.CreationTimestamp.After(m[j].Build.CreationTimestamp.Time)
}
func defaultNamespace(value, defaultValue string) string {
if len(value) == 0 {
return defaultValue
}
return value
}
// BuildConfigsForTag returns the buildConfig that points to the provided imageStreamTag.
func BuildConfigsForTag(g osgraph.Graph, istag graph.Node) []*buildgraph.BuildConfigNode {
bcs := []*buildgraph.BuildConfigNode{}
for _, bcNode := range g.PredecessorNodesByEdgeKind(istag, BuildOutputEdgeKind) {
bcs = append(bcs, bcNode.(*buildgraph.BuildConfigNode))
}
return bcs
}
// GetLatestBuild returns the latest build for the provided buildConfig.
func GetLatestBuild(g osgraph.Graph, bc graph.Node) *buildgraph.BuildNode {
builds := g.SuccessorNodesByEdgeKind(bc, BuildEdgeKind)
if len(builds) == 0 {
return nil
}
latestBuild := builds[0].(*buildgraph.BuildNode)
for _, buildNode := range builds[1:] {
if build, ok := buildNode.(*buildgraph.BuildNode); ok {
if latestBuild.Build.CreationTimestamp.Before(build.Build.CreationTimestamp) {
latestBuild = build
}
}
}
return latestBuild
}
-47
View File
@@ -1,47 +0,0 @@
package nodes
import (
"github.com/gonum/graph"
osgraph "github.com/openshift/origin/pkg/api/graph"
buildapi "github.com/openshift/origin/pkg/build/api"
)
// EnsureBuildConfigNode adds a graph node for the specific build config if it does not exist
func EnsureBuildConfigNode(g osgraph.MutableUniqueGraph, config *buildapi.BuildConfig) *BuildConfigNode {
return osgraph.EnsureUnique(
g,
BuildConfigNodeName(config),
func(node osgraph.Node) graph.Node {
return &BuildConfigNode{
Node: node,
BuildConfig: config,
}
},
).(*BuildConfigNode)
}
// EnsureSourceRepositoryNode adds the specific BuildSource to the graph if it does not already exist.
func EnsureSourceRepositoryNode(g osgraph.MutableUniqueGraph, source buildapi.BuildSource) *SourceRepositoryNode {
switch {
case source.Git != nil:
default:
return nil
}
return osgraph.EnsureUnique(g,
SourceRepositoryNodeName(source),
func(node osgraph.Node) graph.Node {
return &SourceRepositoryNode{node, source}
},
).(*SourceRepositoryNode)
}
// EnsureBuildNode adds a graph node for the build if it does not already exist.
func EnsureBuildNode(g osgraph.MutableUniqueGraph, build *buildapi.Build) *BuildNode {
return osgraph.EnsureUnique(g,
BuildNodeName(build),
func(node osgraph.Node) graph.Node {
return &BuildNode{node, build}
},
).(*BuildNode)
}
-90
View File
@@ -1,90 +0,0 @@
package nodes
import (
"fmt"
"reflect"
osgraph "github.com/openshift/origin/pkg/api/graph"
buildapi "github.com/openshift/origin/pkg/build/api"
)
var (
BuildConfigNodeKind = reflect.TypeOf(buildapi.BuildConfig{}).Name()
BuildNodeKind = reflect.TypeOf(buildapi.Build{}).Name()
// non-api types
SourceRepositoryNodeKind = reflect.TypeOf(buildapi.BuildSource{}).Name()
)
func BuildConfigNodeName(o *buildapi.BuildConfig) osgraph.UniqueName {
return osgraph.GetUniqueRuntimeObjectNodeName(BuildConfigNodeKind, o)
}
type BuildConfigNode struct {
osgraph.Node
BuildConfig *buildapi.BuildConfig
}
func (n BuildConfigNode) Object() interface{} {
return n.BuildConfig
}
func (n BuildConfigNode) String() string {
return string(BuildConfigNodeName(n.BuildConfig))
}
func (n BuildConfigNode) UniqueName() osgraph.UniqueName {
return BuildConfigNodeName(n.BuildConfig)
}
func (*BuildConfigNode) Kind() string {
return BuildConfigNodeKind
}
func SourceRepositoryNodeName(source buildapi.BuildSource) osgraph.UniqueName {
switch {
case source.Git != nil:
sourceType, uri, ref := "git", source.Git.URI, source.Git.Ref
return osgraph.UniqueName(fmt.Sprintf("%s|%s|%s#%s", SourceRepositoryNodeKind, sourceType, uri, ref))
default:
panic(fmt.Sprintf("invalid build source: %v", source))
}
}
type SourceRepositoryNode struct {
osgraph.Node
Source buildapi.BuildSource
}
func (n SourceRepositoryNode) String() string {
return string(SourceRepositoryNodeName(n.Source))
}
func (SourceRepositoryNode) Kind() string {
return SourceRepositoryNodeKind
}
func BuildNodeName(o *buildapi.Build) osgraph.UniqueName {
return osgraph.GetUniqueRuntimeObjectNodeName(BuildNodeKind, o)
}
type BuildNode struct {
osgraph.Node
Build *buildapi.Build
}
func (n BuildNode) Object() interface{} {
return n.Build
}
func (n BuildNode) String() string {
return string(BuildNodeName(n.Build))
}
func (n BuildNode) UniqueName() osgraph.UniqueName {
return BuildNodeName(n.Build)
}
func (*BuildNode) Kind() string {
return BuildNodeKind
}
-3
View File
@@ -1,3 +0,0 @@
// Package util contains common functions that are used
// by the rest of the OpenShift build system.
package util
-169
View File
@@ -1,169 +0,0 @@
package util
import (
"fmt"
"strconv"
"strings"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/labels"
"github.com/golang/glog"
buildapi "github.com/openshift/origin/pkg/build/api"
buildclient "github.com/openshift/origin/pkg/build/client"
)
const (
// NoBuildLogsMessage reports that no build logs are available
NoBuildLogsMessage = "No logs are available."
)
// GetBuildName returns name of the build pod.
func GetBuildName(pod *kapi.Pod) string {
if pod == nil {
return ""
}
return pod.Annotations[buildapi.BuildAnnotation]
}
// GetInputReference returns the From ObjectReference associated with the
// BuildStrategy.
func GetInputReference(strategy buildapi.BuildStrategy) *kapi.ObjectReference {
switch {
case strategy.SourceStrategy != nil:
return &strategy.SourceStrategy.From
case strategy.DockerStrategy != nil:
return strategy.DockerStrategy.From
case strategy.CustomStrategy != nil:
return &strategy.CustomStrategy.From
default:
return nil
}
}
// NameFromImageStream returns a concatenated name representing an ImageStream[Tag/Image]
// reference. If the reference does not contain a Namespace, the namespace parameter
// is used instead.
func NameFromImageStream(namespace string, ref *kapi.ObjectReference, tag string) string {
var ret string
if ref.Namespace == "" {
ret = namespace
} else {
ret = ref.Namespace
}
ret = ret + "/" + ref.Name
if tag != "" && strings.Index(ref.Name, ":") == -1 && strings.Index(ref.Name, "@") == -1 {
ret = ret + ":" + tag
}
return ret
}
// IsBuildComplete returns whether the provided build is complete or not
func IsBuildComplete(build *buildapi.Build) bool {
return build.Status.Phase != buildapi.BuildPhaseRunning && build.Status.Phase != buildapi.BuildPhasePending && build.Status.Phase != buildapi.BuildPhaseNew
}
// IsPaused returns true if the provided BuildConfig is paused and cannot be used to create a new Build
func IsPaused(bc *buildapi.BuildConfig) bool {
return strings.ToLower(bc.Annotations[buildapi.BuildConfigPausedAnnotation]) == "true"
}
// BuildNumber returns the given build number.
func BuildNumber(build *buildapi.Build) (int64, error) {
annotations := build.GetAnnotations()
if stringNumber, ok := annotations[buildapi.BuildNumberAnnotation]; ok {
return strconv.ParseInt(stringNumber, 10, 64)
}
return 0, fmt.Errorf("build %s/%s does not have %s annotation", build.Namespace, build.Name, buildapi.BuildNumberAnnotation)
}
// BuildRunPolicy returns the scheduling policy for the build based on the
// "queued" label.
func BuildRunPolicy(build *buildapi.Build) buildapi.BuildRunPolicy {
labels := build.GetLabels()
if value, found := labels[buildapi.BuildRunPolicyLabel]; found {
switch value {
case "Parallel":
return buildapi.BuildRunPolicyParallel
case "Serial":
return buildapi.BuildRunPolicySerial
case "SerialLatestOnly":
return buildapi.BuildRunPolicySerialLatestOnly
}
}
glog.V(5).Infof("Build %s/%s does not have start policy label set, using default (Serial)")
return buildapi.BuildRunPolicySerial
}
// BuildNameForConfigVersion returns the name of the version-th build
// for the config that has the provided name.
func BuildNameForConfigVersion(name string, version int) string {
return fmt.Sprintf("%s-%d", name, version)
}
// BuildConfigSelector returns a label Selector which can be used to find all
// builds for a BuildConfig.
func BuildConfigSelector(name string) labels.Selector {
return labels.Set{buildapi.BuildConfigLabel: buildapi.LabelValue(name)}.AsSelector()
}
// BuildConfigSelectorDeprecated returns a label Selector which can be used to find
// all builds for a BuildConfig that use the deprecated labels.
func BuildConfigSelectorDeprecated(name string) labels.Selector {
return labels.Set{buildapi.BuildConfigLabelDeprecated: name}.AsSelector()
}
type buildFilter func(buildapi.Build) bool
// BuildConfigBuilds return a list of builds for the given build config.
// Optionally you can specify a filter function to select only builds that
// matches your criteria.
func BuildConfigBuilds(c buildclient.BuildLister, namespace, name string, filterFunc buildFilter) (*buildapi.BuildList, error) {
result, err := c.List(namespace, kapi.ListOptions{
LabelSelector: BuildConfigSelector(name),
})
if err != nil {
return nil, err
}
if filterFunc == nil {
return result, nil
}
filteredList := &buildapi.BuildList{TypeMeta: result.TypeMeta, ListMeta: result.ListMeta}
for _, b := range result.Items {
if filterFunc(b) {
filteredList.Items = append(filteredList.Items, b)
}
}
return filteredList, nil
}
// ConfigNameForBuild returns the name of the build config from a
// build name.
func ConfigNameForBuild(build *buildapi.Build) string {
if build == nil {
return ""
}
if build.Annotations != nil {
if _, exists := build.Annotations[buildapi.BuildConfigAnnotation]; exists {
return build.Annotations[buildapi.BuildConfigAnnotation]
}
}
if _, exists := build.Labels[buildapi.BuildConfigLabel]; exists {
return build.Labels[buildapi.BuildConfigLabel]
}
return build.Labels[buildapi.BuildConfigLabelDeprecated]
}
// VersionForBuild returns the version from the provided build name.
// If no version can be found, 0 is returned to indicate no version.
func VersionForBuild(build *buildapi.Build) int {
if build == nil {
return 0
}
versionString := build.Annotations[buildapi.BuildNumberAnnotation]
version, err := strconv.Atoi(versionString)
if err != nil {
return 0
}
return version
}