Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch logs, idle commands to externals #20343

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hack/import-restrictions.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@

"github.com/openshift/origin/pkg/apps/generated",
"github.com/openshift/origin/pkg/authorization/generated",
"github.com/openshift/origin/pkg/build/apis/build/v1",
"github.com/openshift/origin/pkg/build/client/v1",
"github.com/openshift/origin/pkg/build/generated",
"github.com/openshift/origin/pkg/image/generated",
"github.com/openshift/origin/pkg/network/generated",
Expand Down
31 changes: 31 additions & 0 deletions pkg/build/client/v1/logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package v1

import (
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme"

buildv1 "github.com/openshift/api/build/v1"
)

type BuildLogInterface interface {
Logs(name string, options buildv1.BuildLogOptions) *rest.Request
}

func NewBuildLogClient(c rest.Interface, ns string) BuildLogInterface {
return &buildLogs{client: c, ns: ns}
}

type buildLogs struct {
client rest.Interface
ns string
}

func (c *buildLogs) Logs(name string, options buildv1.BuildLogOptions) *rest.Request {
return c.client.
Get().
Namespace(c.ns).
Resource("builds").
Name(name).
SubResource("log").
VersionedParams(&options, legacyscheme.ParameterCodec)
}
106 changes: 60 additions & 46 deletions pkg/oc/cli/idle/idle.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,31 @@ import (
"github.com/spf13/cobra"

utilerrors "github.com/openshift/origin/pkg/util/errors"
corev1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/strategicpatch"
clientset "k8s.io/client-go/kubernetes"
kextensionsclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme"
kapi "k8s.io/kubernetes/pkg/apis/core"
kinternalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/scheme"

appsv1client "github.com/openshift/client-go/apps/clientset/versioned/typed/apps/v1"
appsmanualclient "github.com/openshift/origin/pkg/apps/client/v1"
appsclientinternal "github.com/openshift/origin/pkg/apps/generated/internalclientset"
"github.com/openshift/origin/pkg/oc/util/ocscheme"
unidlingapi "github.com/openshift/origin/pkg/unidling/api"
utilunidling "github.com/openshift/origin/pkg/unidling/util"
kinternalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
)

var (
Expand All @@ -54,23 +56,26 @@ var (
)

type IdleOptions struct {
dryRun bool

dryRun bool
filename string
all bool
selector string
allNamespaces bool
resources string
resources []string

cmdFullName string

ClientForMappingFn func(*meta.RESTMapping) (resource.RESTClient, error)
ClientConfig *rest.Config
ClientSet kinternalclientset.Interface
ClientSet clientset.Interface
Mapper meta.RESTMapper

nowTime time.Time
svcBuilder *resource.Builder
// TODO(juanvallejo): remove this once we switch unidling helpers to use external versions
InternalClientset kinternalclientset.Interface

Builder func() *resource.Builder
Namespace string
nowTime time.Time

genericclioptions.IOStreams
}
Expand Down Expand Up @@ -110,7 +115,8 @@ func NewCmdIdle(fullName string, f kcmdutil.Factory, streams genericclioptions.I
}

func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error {
namespace, _, err := f.ToRawKubeConfigLoader().Namespace()
var err error
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
Expand All @@ -127,7 +133,7 @@ func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []st
return err
}

o.ClientSet, err = f.ClientSet()
o.ClientSet, err = clientset.NewForConfig(o.ClientConfig)
if err != nil {
return err
}
Expand All @@ -137,33 +143,15 @@ func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []st
return err
}

o.ClientForMappingFn = f.ClientForMapping

o.svcBuilder = f.NewBuilder().
WithScheme(ocscheme.ReadingInternalScheme).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().AllNamespaces(o.allNamespaces).
Flatten().
SingleResourceType()

if len(o.filename) > 0 {
targetServiceNames, err := scanLinesFromFile(o.filename)
if err != nil {
return err
}
o.svcBuilder.ResourceNames("endpoints", targetServiceNames...)
} else {
// NB: this is a bit weird because the resource builder will complain if we use ResourceTypes and ResourceNames when len(args) > 0
if o.selector != "" {
o.svcBuilder.LabelSelectorParam(o.selector).ResourceTypes("endpoints")
}
o.InternalClientset, err = f.ClientSet()
if err != nil {
return err
}

o.svcBuilder.ResourceNames("endpoints", args...)
o.ClientForMappingFn = f.ClientForMapping
o.Builder = f.NewBuilder

if o.all {
o.svcBuilder.ResourceTypes("endpoints").SelectAllParam(o.all)
}
}
o.resources = args

return nil
}
Expand Down Expand Up @@ -206,7 +194,7 @@ func scanLinesFromFile(filename string) ([]string, error) {
// idleUpdateInfo contains the required info to annotate an endpoints object
// with the scalable resources that it should unidle
type idleUpdateInfo struct {
obj *kapi.Endpoints
obj *corev1.Endpoints
scaleRefs map[unidlingapi.CrossGroupObjectReference]struct{}
}

Expand All @@ -224,9 +212,9 @@ type controllerRef struct {
// Using the list of services, it figures out the associated scalable objects, and returns a map from the endpoints object for the services to
// the list of scalable resources associated with that endpoints object, as well as a map from CrossGroupObjectReferences to scale to 0 to the
// name of the associated service.
func (o *IdleOptions) calculateIdlableAnnotationsByService() (map[types.NamespacedName]idleUpdateInfo, map[namespacedCrossGroupObjectReference]types.NamespacedName, error) {
podsLoaded := make(map[kapi.ObjectReference]*kapi.Pod)
getPod := func(ref kapi.ObjectReference) (*kapi.Pod, error) {
func (o *IdleOptions) calculateIdlableAnnotationsByService(infoVisitor func(resource.VisitorFunc) error) (map[types.NamespacedName]idleUpdateInfo, map[namespacedCrossGroupObjectReference]types.NamespacedName, error) {
podsLoaded := make(map[corev1.ObjectReference]*corev1.Pod)
getPod := func(ref corev1.ObjectReference) (*corev1.Pod, error) {
if pod, ok := podsLoaded[ref]; ok {
return pod, nil
}
Expand Down Expand Up @@ -287,12 +275,12 @@ func (o *IdleOptions) calculateIdlableAnnotationsByService() (map[types.Namespac
targetScaleRefs := make(map[namespacedCrossGroupObjectReference]types.NamespacedName)
endpointsInfo := make(map[types.NamespacedName]idleUpdateInfo)

err := o.svcBuilder.Do().Visit(func(info *resource.Info, err error) error {
err := infoVisitor(func(info *resource.Info, err error) error {
if err != nil {
return err
}

endpoints, isEndpoints := info.Object.(*kapi.Endpoints)
endpoints, isEndpoints := info.Object.(*corev1.Endpoints)
if !isEndpoints {
return fmt.Errorf("you must specify endpoints, not %v (view available endpoints with \"%s get endpoints\").", info.Mapping.Resource, o.cmdFullName)
}
Expand Down Expand Up @@ -372,9 +360,9 @@ func normalizedNSOwnerRef(namespace string, ownerRef *metav1.OwnerReference) nam
// scalable objects by checking each address in each subset to see if it has a pod
// reference, and the following that pod reference to find the owning controller,
// and returning the unique set of controllers found this way.
func findScalableResourcesForEndpoints(endpoints *kapi.Endpoints, getPod func(kapi.ObjectReference) (*kapi.Pod, error), getController func(namespacedOwnerReference) (metav1.Object, error)) (map[namespacedCrossGroupObjectReference]struct{}, error) {
func findScalableResourcesForEndpoints(endpoints *corev1.Endpoints, getPod func(corev1.ObjectReference) (*corev1.Pod, error), getController func(namespacedOwnerReference) (metav1.Object, error)) (map[namespacedCrossGroupObjectReference]struct{}, error) {
// To find all RCs and DCs for an endpoint, we first figure out which pods are pointed to by that endpoint...
podRefs := map[kapi.ObjectReference]*kapi.Pod{}
podRefs := map[corev1.ObjectReference]*corev1.Pod{}
for _, subset := range endpoints.Subsets {
for _, addr := range subset.Addresses {
if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" {
Expand Down Expand Up @@ -547,6 +535,32 @@ type scaleInfo struct {
// scalable resources to zero, and annotating the associated endpoints objects with the scalable resources to unidle
// when they receive traffic.
func (o *IdleOptions) RunIdle() error {
b := o.Builder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
ContinueOnError().
NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.allNamespaces).
Flatten().
SingleResourceType()

if len(o.filename) > 0 {
targetServiceNames, err := scanLinesFromFile(o.filename)
if err != nil {
return err
}
b.ResourceNames("endpoints", targetServiceNames...)
} else {
// NB: this is a bit weird because the resource builder will complain if we use ResourceTypes and ResourceNames when len(args) > 0
if o.selector != "" {
b.LabelSelectorParam(o.selector).ResourceTypes("endpoints")
}

b.ResourceNames("endpoints", o.resources...)

if o.all {
b.ResourceTypes("endpoints").SelectAllParam(o.all)
}
}

hadError := false
nowTime := time.Now().UTC()

Expand All @@ -556,7 +570,7 @@ func (o *IdleOptions) RunIdle() error {
}

// figure out which endpoints and resources we need to idle
byService, byScalable, err := o.calculateIdlableAnnotationsByService()
byService, byScalable, err := o.calculateIdlableAnnotationsByService(b.Do().Visit)

if err != nil {
if len(byService) == 0 || len(byScalable) == 0 {
Expand All @@ -576,7 +590,7 @@ func (o *IdleOptions) RunIdle() error {

externalKubeExtensionClient := kextensionsclient.New(o.ClientSet.Extensions().RESTClient())
delegScaleGetter := appsmanualclient.NewDelegatingScaleNamespacer(appsV1Client, externalKubeExtensionClient)
scaleAnnotater := utilunidling.NewScaleAnnotater(delegScaleGetter, appClient.Apps(), o.ClientSet.Core(), func(currentReplicas int32, annotations map[string]string) {
scaleAnnotater := utilunidling.NewScaleAnnotater(delegScaleGetter, appClient.Apps(), o.InternalClientset.Core(), func(currentReplicas int32, annotations map[string]string) {
annotations[unidlingapi.IdledAtAnnotation] = nowTime.UTC().Format(time.RFC3339)
annotations[unidlingapi.PreviousScaleAnnotation] = fmt.Sprintf("%v", currentReplicas)
})
Expand Down Expand Up @@ -679,7 +693,7 @@ func (o *IdleOptions) RunIdle() error {
for scaleRef, info := range toScale {
if !o.dryRun {
info.scale.Spec.Replicas = 0
scaleUpdater := utilunidling.NewScaleUpdater(kcmdutil.InternalVersionJSONEncoder(), info.namespace, appClient.Apps(), o.ClientSet.Core())
scaleUpdater := utilunidling.NewScaleUpdater(kcmdutil.InternalVersionJSONEncoder(), info.namespace, appClient.Apps(), o.InternalClientset.Core())
if err := scaleAnnotater.UpdateObjectScale(scaleUpdater, info.namespace, scaleRef.CrossGroupObjectReference, info.obj, info.scale); err != nil {
fmt.Fprintf(o.ErrOut, "error: unable to scale %s %s/%s to 0, but still listed as target for unidling: %v\n", scaleRef.Kind, info.namespace, scaleRef.Name, err)
hadError = true
Expand Down
31 changes: 16 additions & 15 deletions pkg/oc/cli/idle/idle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ import (
"fmt"
"testing"

unidlingapi "github.com/openshift/origin/pkg/unidling/api"

oappsapi "github.com/openshift/origin/pkg/apps/apis/apps"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
ktypes "k8s.io/apimachinery/pkg/types"
kapi "k8s.io/kubernetes/pkg/apis/core"

oappsapi "github.com/openshift/origin/pkg/apps/apis/apps"
unidlingapi "github.com/openshift/origin/pkg/unidling/api"

// install all APIs
_ "github.com/openshift/origin/pkg/api/install"
_ "k8s.io/kubernetes/pkg/apis/core/install"
)

func makePod(name string, rc metav1.Object, namespace string, t *testing.T) kapi.Pod {
pod := kapi.Pod{
func makePod(name string, rc metav1.Object, namespace string, t *testing.T) corev1.Pod {
pod := corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Expand Down Expand Up @@ -49,8 +50,8 @@ func makeRC(name string, dc metav1.Object, namespace string, t *testing.T) *kapi
return &rc
}

func makePodRef(name, namespace string) *kapi.ObjectReference {
return &kapi.ObjectReference{
func makePodRef(name, namespace string) *corev1.ObjectReference {
return &corev1.ObjectReference{
Kind: "Pod",
Name: name,
Namespace: namespace,
Expand All @@ -63,18 +64,18 @@ func makeRCRef(name string) *metav1.OwnerReference {
}

func TestFindIdlablesForEndpoints(t *testing.T) {
endpoints := &kapi.Endpoints{
Subsets: []kapi.EndpointSubset{
endpoints := &corev1.Endpoints{
Subsets: []corev1.EndpointSubset{
{
Addresses: []kapi.EndpointAddress{
Addresses: []corev1.EndpointAddress{
{
TargetRef: makePodRef("somepod1", "somens1"),
},
{
TargetRef: makePodRef("somepod2", "somens1"),
},
{
TargetRef: &kapi.ObjectReference{
TargetRef: &corev1.ObjectReference{
Kind: "Cheese",
Name: "cheddar",
Namespace: "somens",
Expand All @@ -83,7 +84,7 @@ func TestFindIdlablesForEndpoints(t *testing.T) {
},
},
{
Addresses: []kapi.EndpointAddress{
Addresses: []corev1.EndpointAddress{
{},
{
TargetRef: makePodRef("somepod3", "somens1"),
Expand All @@ -100,7 +101,7 @@ func TestFindIdlablesForEndpoints(t *testing.T) {
},
},
{
Addresses: []kapi.EndpointAddress{
Addresses: []corev1.EndpointAddress{
{},
{
TargetRef: makePodRef("somepod1", "somens2"),
Expand All @@ -119,7 +120,7 @@ func TestFindIdlablesForEndpoints(t *testing.T) {
"somens2/somerc2": makeRC("somerc2", nil, "somens2", t),
}

pods := map[kapi.ObjectReference]kapi.Pod{
pods := map[corev1.ObjectReference]corev1.Pod{
*makePodRef("somepod1", "somens1"): makePod("somepod1", controllers["somens1/somerc1"], "somens1", t),
*makePodRef("somepod2", "somens1"): makePod("somepod2", controllers["somens1/somerc2"], "somens1", t),
*makePodRef("somepod3", "somens1"): makePod("somepod3", controllers["somens1/somerc1"], "somens1", t),
Expand All @@ -128,7 +129,7 @@ func TestFindIdlablesForEndpoints(t *testing.T) {
*makePodRef("somepod1", "somens2"): makePod("somepod5", controllers["somens2/somerc2"], "somens2", t),
}

getPod := func(ref kapi.ObjectReference) (*kapi.Pod, error) {
getPod := func(ref corev1.ObjectReference) (*corev1.Pod, error) {
if pod, ok := pods[ref]; ok {
return &pod, nil
}
Expand Down
Loading