github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/master/thirdparty_controller.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package master
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"k8s.io/kubernetes/pkg/api"
    24  	expapi "k8s.io/kubernetes/pkg/apis/extensions"
    25  	thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresource/etcd"
    26  	"k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata"
    27  	"k8s.io/kubernetes/pkg/runtime"
    28  	"k8s.io/kubernetes/pkg/util/sets"
    29  )
    30  
    31  const thirdpartyprefix = "/apis"
    32  
    33  func makeThirdPartyPath(group string) string {
    34  	if len(group) == 0 {
    35  		return thirdpartyprefix
    36  	}
    37  	return thirdpartyprefix + "/" + group
    38  }
    39  
    40  // resourceInterface is the interface for the parts of the master that know how to add/remove
    41  // third party resources.  Extracted into an interface for injection for testing.
    42  type resourceInterface interface {
    43  	// Remove a third party resource based on the RESTful path for that resource
    44  	RemoveThirdPartyResource(path string) error
    45  	// Install a third party resource described by 'rsrc'
    46  	InstallThirdPartyResource(rsrc *expapi.ThirdPartyResource) error
    47  	// Is a particular third party resource currently installed?
    48  	HasThirdPartyResource(rsrc *expapi.ThirdPartyResource) (bool, error)
    49  	// List all currently installed third party resources
    50  	ListThirdPartyResources() []string
    51  }
    52  
    53  // ThirdPartyController is a control loop that knows how to synchronize ThirdPartyResource objects with
    54  // RESTful resources which are present in the API server.
    55  type ThirdPartyController struct {
    56  	master                     resourceInterface
    57  	thirdPartyResourceRegistry *thirdpartyresourceetcd.REST
    58  }
    59  
    60  // Synchronize a single resource with RESTful resources on the master
    61  func (t *ThirdPartyController) SyncOneResource(rsrc *expapi.ThirdPartyResource) error {
    62  	// TODO: we also need to test if the existing installed resource matches the resource we are sync-ing.
    63  	// Currently, if there is an older, incompatible resource installed, we won't remove it.  We should detect
    64  	// older, incompatible resources and remove them before testing if the resource exists.
    65  	hasResource, err := t.master.HasThirdPartyResource(rsrc)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	if !hasResource {
    70  		return t.master.InstallThirdPartyResource(rsrc)
    71  	}
    72  	return nil
    73  }
    74  
    75  // Synchronize all resources with RESTful resources on the master
    76  func (t *ThirdPartyController) SyncResources() error {
    77  	list, err := t.thirdPartyResourceRegistry.List(api.NewDefaultContext(), nil)
    78  	if err != nil {
    79  		return err
    80  	}
    81  	return t.syncResourceList(list)
    82  }
    83  
    84  func (t *ThirdPartyController) syncResourceList(list runtime.Object) error {
    85  	existing := sets.String{}
    86  	switch list := list.(type) {
    87  	case *expapi.ThirdPartyResourceList:
    88  		// Loop across all schema objects for third party resources
    89  		for ix := range list.Items {
    90  			item := &list.Items[ix]
    91  			// extract the api group and resource kind from the schema
    92  			_, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(item)
    93  			if err != nil {
    94  				return err
    95  			}
    96  			// place it in the set of resources that we expect, so that we don't delete it in the delete pass
    97  			existing.Insert(makeThirdPartyPath(group))
    98  			// ensure a RESTful resource for this schema exists on the master
    99  			if err := t.SyncOneResource(item); err != nil {
   100  				return err
   101  			}
   102  		}
   103  	default:
   104  		return fmt.Errorf("expected a *ThirdPartyResourceList, got %#v", list)
   105  	}
   106  	// deletion phase, get all installed RESTful resources
   107  	installed := t.master.ListThirdPartyResources()
   108  	for _, installedAPI := range installed {
   109  		found := false
   110  		// search across the expected restful resources to see if this resource belongs to one of the expected ones
   111  		for _, apiPath := range existing.List() {
   112  			if installedAPI == apiPath || strings.HasPrefix(installedAPI, apiPath+"/") {
   113  				found = true
   114  				break
   115  			}
   116  		}
   117  		// not expected, delete the resource
   118  		if !found {
   119  			if err := t.master.RemoveThirdPartyResource(installedAPI); err != nil {
   120  				return err
   121  			}
   122  		}
   123  	}
   124  
   125  	return nil
   126  }