Refactor tenant client
Deal with tenantID provided case Change-Id: Ia01028d21fe258a97175fcc8ce103cc82df37291
This commit is contained in:
parent
e2f1a14c1d
commit
a0de58d447
@ -13,6 +13,7 @@ import (
|
||||
kubestacktypes "git.openstack.org/openstack/stackube/pkg/kubestack/types"
|
||||
"git.openstack.org/openstack/stackube/pkg/openstack"
|
||||
"git.openstack.org/openstack/stackube/pkg/util"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
@ -92,10 +93,16 @@ func initOpenstack(stdinData []byte) (OpenStack, string, error) {
|
||||
if n.KubestackConfig == "" {
|
||||
return OpenStack{}, "", fmt.Errorf("kubestack-config not specified")
|
||||
}
|
||||
openStackClient, err := openstack.NewClient(n.KubestackConfig)
|
||||
|
||||
if n.KubernetesConfig == "" {
|
||||
return OpenStack{}, "", fmt.Errorf("kubernetes-config not specified")
|
||||
}
|
||||
|
||||
openStackClient, err := openstack.NewClient(n.KubestackConfig, n.KubernetesConfig)
|
||||
if err != nil {
|
||||
return OpenStack{}, "", err
|
||||
}
|
||||
|
||||
os := OpenStack{
|
||||
Client: *openStackClient,
|
||||
}
|
||||
|
@ -44,8 +44,7 @@ func startControllers(kubeconfig, cloudconfig string) error {
|
||||
|
||||
// Creates a new RBAC controller
|
||||
rm, err := rbacmanager.New(kubeconfig,
|
||||
tc.GetTenantClient(),
|
||||
nc.GetNetworkClient(),
|
||||
tc.GetKubeCRDClient(),
|
||||
*systemCIDR,
|
||||
*systemGateway,
|
||||
)
|
||||
@ -92,7 +91,7 @@ func verifyClientSetting() error {
|
||||
return fmt.Errorf("Init kubernetes clientset failed: %v", err)
|
||||
}
|
||||
|
||||
_, err = openstack.NewClient(*cloudconfig)
|
||||
_, err = openstack.NewClient(*cloudconfig, *kubeconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Init openstack client failed: %v", err)
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ EOF'
|
||||
|
||||
function install_master {
|
||||
sed -i "s/KEYSTONE_HOST/${SERVICE_HOST}/g" ${STACKUBE_ROOT}/kubeadm.yaml
|
||||
sudo kubeadm init kubeadm init --pod-network-cidr ${CLUSTER_CIDR} --config ${STACKUBE_ROOT}/kubeadm.yaml
|
||||
sudo kubeadm init --pod-network-cidr ${CLUSTER_CIDR} --config ${STACKUBE_ROOT}/kubeadm.yaml
|
||||
# Enable schedule pods on the master for testing.
|
||||
sudo cp /etc/kubernetes/admin.conf $HOME/
|
||||
sudo chown $(id -u):$(id -g) $HOME/admin.conf
|
||||
|
@ -1,29 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
)
|
||||
|
||||
func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
if err := crv1.AddToScheme(scheme); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
config := *cfg
|
||||
config.GroupVersion = &crv1.SchemeGroupVersion
|
||||
config.APIPath = "/apis"
|
||||
config.ContentType = runtime.ContentTypeJSON
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)}
|
||||
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return client, scheme, nil
|
||||
}
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
"git.openstack.org/openstack/stackube/pkg/auth-controller/rbacmanager/rbac"
|
||||
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
|
||||
"git.openstack.org/openstack/stackube/pkg/util"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@ -15,7 +16,6 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/pkg/api"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
@ -28,16 +28,14 @@ type Controller struct {
|
||||
kclient *kubernetes.Clientset
|
||||
nsInf cache.SharedIndexInformer
|
||||
queue workqueue.RateLimitingInterface
|
||||
tenantClient *rest.RESTClient
|
||||
networkClient *rest.RESTClient
|
||||
kubeCRDClient *crdClient.CRDClient
|
||||
systemCIDR string
|
||||
systemGateway string
|
||||
}
|
||||
|
||||
// New creates a new RBAC controller.
|
||||
func New(kubeconfig string,
|
||||
tenantClient *rest.RESTClient,
|
||||
networkClient *rest.RESTClient,
|
||||
kubeCRDClient *crdClient.CRDClient,
|
||||
systemCIDR string,
|
||||
systemGateway string,
|
||||
) (*Controller, error) {
|
||||
@ -53,8 +51,7 @@ func New(kubeconfig string,
|
||||
o := &Controller{
|
||||
kclient: client,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "rbacmanager"),
|
||||
tenantClient: tenantClient,
|
||||
networkClient: networkClient,
|
||||
kubeCRDClient: kubeCRDClient,
|
||||
systemCIDR: systemCIDR,
|
||||
systemGateway: systemGateway,
|
||||
}
|
||||
@ -157,7 +154,8 @@ func (c *Controller) handleNamespaceAdd(obj interface{}) {
|
||||
func (c *Controller) initSystemReservedTenantNetwork() error {
|
||||
tenant := &crv1.Tenant{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: util.SystemTenant,
|
||||
Name: util.SystemTenant,
|
||||
Namespace: util.SystemTenant,
|
||||
},
|
||||
Spec: crv1.TenantSpec{
|
||||
UserName: util.SystemTenant,
|
||||
@ -165,13 +163,8 @@ func (c *Controller) initSystemReservedTenantNetwork() error {
|
||||
},
|
||||
}
|
||||
|
||||
err := c.tenantClient.Post().
|
||||
Namespace(util.SystemTenant).
|
||||
Resource(crv1.TenantResourcePlural).
|
||||
Body(tenant).
|
||||
Do().Error()
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed to create system Tenant: %v", err)
|
||||
if err := c.kubeCRDClient.AddTenant(tenant); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// NOTE(harry): we do not support update Network, so although configurable,
|
||||
@ -179,7 +172,8 @@ func (c *Controller) initSystemReservedTenantNetwork() error {
|
||||
// that system network. We may need to document this.
|
||||
network := &crv1.Network{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: util.SystemNetwork,
|
||||
Name: util.SystemNetwork,
|
||||
Namespace: util.SystemTenant,
|
||||
},
|
||||
Spec: crv1.NetworkSpec{
|
||||
CIDR: c.systemCIDR,
|
||||
@ -188,13 +182,8 @@ func (c *Controller) initSystemReservedTenantNetwork() error {
|
||||
}
|
||||
|
||||
// network controller will always check if Tenant is ready so we will not wait here
|
||||
err = c.networkClient.Post().
|
||||
Resource(crv1.NetworkResourcePlural).
|
||||
Namespace(util.SystemTenant).
|
||||
Body(network).
|
||||
Do().Error()
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed to create system Network: %v", err)
|
||||
if err := c.kubeCRDClient.AddNetwork(network); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -4,41 +4,32 @@ import (
|
||||
"fmt"
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
crdClient "git.openstack.org/openstack/stackube/pkg/auth-controller/client/auth"
|
||||
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
|
||||
"git.openstack.org/openstack/stackube/pkg/openstack"
|
||||
|
||||
"git.openstack.org/openstack/stackube/pkg/util"
|
||||
"github.com/golang/glog"
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
apismetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// TenantController manages lify cycle of Tenant.
|
||||
// TenantController manages life cycle of Tenant.
|
||||
type TenantController struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
tenantClient *rest.RESTClient
|
||||
tenantScheme *runtime.Scheme
|
||||
kubeCRDClient *crdClient.CRDClient
|
||||
openstackClient *openstack.Client
|
||||
}
|
||||
|
||||
// NewTenantController creates a new tenant controller.
|
||||
func NewTenantController(kubeconfig, cloudconfig string) (*TenantController, error) {
|
||||
// Create OpenStack client from config
|
||||
openStackClient, err := openstack.NewClient(cloudconfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init openstack client failed: %v", err)
|
||||
}
|
||||
|
||||
// Create the client config. Use kubeconfig if given, otherwise assume in-cluster.
|
||||
config, err := buildConfig(kubeconfig)
|
||||
config, err := util.NewClusterConfig(kubeconfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build kubeconfig: %v", err)
|
||||
}
|
||||
@ -58,15 +49,14 @@ func NewTenantController(kubeconfig, cloudconfig string) (*TenantController, err
|
||||
return nil, fmt.Errorf("failed to create kubernetes client: %v", err)
|
||||
}
|
||||
|
||||
// make a new config for our extension's API group, using the first config as a baseline
|
||||
tenantClient, tenantScheme, err := crdClient.NewClient(config)
|
||||
// Create OpenStack client from config
|
||||
openStackClient, err := openstack.NewClient(cloudconfig, kubeconfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create client for CRD: %v", err)
|
||||
return nil, fmt.Errorf("init openstack client failed: %v", err)
|
||||
}
|
||||
|
||||
c := &TenantController{
|
||||
tenantClient: tenantClient,
|
||||
tenantScheme: tenantScheme,
|
||||
kubeCRDClient: openStackClient.CRDClient,
|
||||
k8sClient: k8sClient,
|
||||
openstackClient: openStackClient,
|
||||
}
|
||||
@ -78,15 +68,8 @@ func NewTenantController(kubeconfig, cloudconfig string) (*TenantController, err
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func buildConfig(kubeconfig string) (*rest.Config, error) {
|
||||
if kubeconfig != "" {
|
||||
return clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||
}
|
||||
return rest.InClusterConfig()
|
||||
}
|
||||
|
||||
func (c *TenantController) GetTenantClient() *rest.RESTClient {
|
||||
return c.tenantClient
|
||||
func (c *TenantController) GetKubeCRDClient() *crdClient.CRDClient {
|
||||
return c.kubeCRDClient
|
||||
}
|
||||
|
||||
// Run the controller.
|
||||
@ -94,7 +77,7 @@ func (c *TenantController) Run(stopCh <-chan struct{}) error {
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
source := cache.NewListWatchFromClient(
|
||||
c.tenantClient,
|
||||
c.kubeCRDClient.Client,
|
||||
crv1.TenantResourcePlural,
|
||||
apiv1.NamespaceAll,
|
||||
fields.Everything())
|
||||
@ -116,11 +99,11 @@ func (c *TenantController) Run(stopCh <-chan struct{}) error {
|
||||
|
||||
func (c *TenantController) onAdd(obj interface{}) {
|
||||
tenant := obj.(*crv1.Tenant)
|
||||
glog.V(3).Infof("Tenant controller received new object %v\n", tenant)
|
||||
glog.V(3).Infof("Tenant controller received new object %#v\n", tenant)
|
||||
|
||||
copyObj, err := c.tenantScheme.Copy(tenant)
|
||||
copyObj, err := c.kubeCRDClient.Scheme.Copy(tenant)
|
||||
if err != nil {
|
||||
glog.Errorf("ERROR creating a deep copy of tenant object: %v\n", err)
|
||||
glog.Errorf("ERROR creating a deep copy of tenant object: %#v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -138,7 +121,7 @@ func (c *TenantController) onDelete(obj interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Tenant controller received deleted tenant %v\n", tenant)
|
||||
glog.V(3).Infof("Tenant controller received deleted tenant %#v\n", tenant)
|
||||
|
||||
deleteOptions := &apismetav1.DeleteOptions{
|
||||
TypeMeta: apismetav1.TypeMeta{
|
||||
|
@ -11,12 +11,12 @@ import (
|
||||
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||
)
|
||||
|
||||
func (c *TenantController) syncTenant(tenant *crv1.Tenant) error {
|
||||
func (c *TenantController) syncTenant(tenant *crv1.Tenant) {
|
||||
roleBinding := rbac.GenerateClusterRoleBindingByTenant(tenant.Name)
|
||||
_, err := c.k8sClient.Rbac().ClusterRoleBindings().Create(roleBinding)
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
glog.Errorf("Failed create ClusterRoleBinding for tenant %s: %v", tenant.Name, err)
|
||||
return err
|
||||
return
|
||||
}
|
||||
glog.V(4).Infof("Created ClusterRoleBindings %s-namespace-creater for tenant %s", tenant.Name, tenant.Name)
|
||||
if tenant.Spec.TenantID != "" {
|
||||
@ -24,29 +24,30 @@ func (c *TenantController) syncTenant(tenant *crv1.Tenant) error {
|
||||
err = c.openstackClient.CreateUser(tenant.Spec.UserName, tenant.Spec.Password, tenant.Spec.TenantID)
|
||||
if err != nil && !openstack.IsAlreadyExists(err) {
|
||||
glog.Errorf("Failed create user %s: %v", tenant.Spec.UserName, err)
|
||||
return err
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Create tenant if the tenant not exist in keystone
|
||||
tenantID, err := c.openstackClient.CreateTenant(tenant.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
glog.Errorf("Failed create tenant %s: %v", tenant, err)
|
||||
return
|
||||
}
|
||||
// Create user with the spec username and password in the created tenant
|
||||
err = c.openstackClient.CreateUser(tenant.Spec.UserName, tenant.Spec.Password, tenantID)
|
||||
if err != nil {
|
||||
return err
|
||||
glog.Errorf("Failed create user %s: %v", tenant.Spec.UserName, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Create namespace which name is the same as the tenant's name
|
||||
err = c.createNamespace(tenant.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
glog.Errorf("Failed create namespace %s: %v", tenant.Name, err)
|
||||
return
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Created namespace %s for tenant %s", tenant.Name, tenant.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *TenantController) createClusterRoles() error {
|
||||
@ -76,7 +77,6 @@ func (c *TenantController) createNamespace(namespace string) error {
|
||||
func (c *TenantController) deleteNamespace(namespace string) error {
|
||||
err := c.k8sClient.CoreV1().Namespaces().Delete(namespace, apismetav1.NewDeleteOptions(0))
|
||||
if err != nil {
|
||||
glog.Errorf("Failed delete namespace %s: %v", namespace, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
113
pkg/kubecrd/crdclient.go
Normal file
113
pkg/kubecrd/crdclient.go
Normal file
@ -0,0 +1,113 @@
|
||||
package kubecrd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
type CRDClient struct {
|
||||
Client *rest.RESTClient
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
func NewCRDClient(cfg *rest.Config) (*CRDClient, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
if err := crv1.AddToScheme(scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := *cfg
|
||||
config.GroupVersion = &crv1.SchemeGroupVersion
|
||||
config.APIPath = "/apis"
|
||||
config.ContentType = runtime.ContentTypeJSON
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)}
|
||||
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CRDClient{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateNetwork updates Network CRD object by given object
|
||||
func (c *CRDClient) UpdateNetwork(network *crv1.Network) {
|
||||
err := c.Client.Put().
|
||||
Name(network.Name).
|
||||
Namespace(network.Namespace).
|
||||
Resource(crv1.NetworkResourcePlural).
|
||||
Body(network).
|
||||
Do().
|
||||
Error()
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("ERROR updating network: %v\n", err)
|
||||
} else {
|
||||
glog.V(3).Infof("UPDATED network: %#v\n", network)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTenant updates Network CRD object by given object
|
||||
func (c *CRDClient) UpdateTenant(tenant *crv1.Tenant) {
|
||||
err := c.Client.Put().
|
||||
Name(tenant.Name).
|
||||
Namespace(tenant.Namespace).
|
||||
Resource(crv1.TenantResourcePlural).
|
||||
Body(tenant).
|
||||
Do().
|
||||
Error()
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("ERROR updating tenant: %v\n", err)
|
||||
} else {
|
||||
glog.V(3).Infof("UPDATED tenant: %#v\n", tenant)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CRDClient) GetTenant(tenantName string) (*crv1.Tenant, error) {
|
||||
tenant := crv1.Tenant{}
|
||||
// tenant always has same name and namespace
|
||||
err := c.Client.Get().
|
||||
Resource(crv1.TenantResourcePlural).
|
||||
Namespace(tenantName).
|
||||
Name(tenantName).
|
||||
Do().Into(&tenant)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tenant, nil
|
||||
}
|
||||
|
||||
func (c *CRDClient) AddTenant(tenant *crv1.Tenant) error {
|
||||
err := c.Client.Post().
|
||||
Namespace(tenant.GetNamespace()).
|
||||
Resource(crv1.TenantResourcePlural).
|
||||
Body(tenant).
|
||||
Do().Error()
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed to create Tenant: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CRDClient) AddNetwork(network *crv1.Network) error {
|
||||
err := c.Client.Post().
|
||||
Resource(crv1.NetworkResourcePlural).
|
||||
Namespace(network.GetNamespace()).
|
||||
Body(network).
|
||||
Do().Error()
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed to create Network: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package client
|
||||
package kubecrd
|
||||
|
||||
import (
|
||||
"reflect"
|
@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package kubecrd
|
||||
|
||||
import (
|
||||
"reflect"
|
@ -8,7 +8,8 @@ import (
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
KubestackConfig string `json:"kubestack-config"`
|
||||
KubestackConfig string `json:"kubestack-config"`
|
||||
KubernetesConfig string `json:"kubernetes-config"`
|
||||
}
|
||||
|
||||
// K8sArgs is the valid CNI_ARGS used for Kubernetes
|
||||
|
@ -1,29 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
)
|
||||
|
||||
func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
if err := crv1.AddToScheme(scheme); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
config := *cfg
|
||||
config.GroupVersion = &crv1.SchemeGroupVersion
|
||||
config.APIPath = "/apis"
|
||||
config.ContentType = runtime.ContentTypeJSON
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)}
|
||||
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return client, scheme, nil
|
||||
}
|
@ -7,14 +7,11 @@ import (
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
crdClient "git.openstack.org/openstack/stackube/pkg/network-controller/client"
|
||||
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
|
||||
osDriver "git.openstack.org/openstack/stackube/pkg/openstack"
|
||||
"git.openstack.org/openstack/stackube/pkg/util"
|
||||
|
||||
@ -23,20 +20,19 @@ import (
|
||||
|
||||
// Watcher is an network of watching on resource create/update/delete events
|
||||
type NetworkController struct {
|
||||
networkClient *rest.RESTClient
|
||||
networkScheme *runtime.Scheme
|
||||
kubeCRDClient *crdClient.CRDClient
|
||||
driver *osDriver.Client
|
||||
}
|
||||
|
||||
func (c *NetworkController) GetNetworkClient() *rest.RESTClient {
|
||||
return c.networkClient
|
||||
func (c *NetworkController) GetKubeCRDClient() *crdClient.CRDClient {
|
||||
return c.kubeCRDClient
|
||||
}
|
||||
|
||||
func (c *NetworkController) Run(stopCh <-chan struct{}) error {
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
source := cache.NewListWatchFromClient(
|
||||
c.networkClient,
|
||||
c.kubeCRDClient.Client,
|
||||
crv1.NetworkResourcePlural,
|
||||
apiv1.NamespaceAll,
|
||||
fields.Everything())
|
||||
@ -57,22 +53,9 @@ func (c *NetworkController) Run(stopCh <-chan struct{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildConfig(kubeconfig string) (*rest.Config, error) {
|
||||
if kubeconfig != "" {
|
||||
return clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||
}
|
||||
return rest.InClusterConfig()
|
||||
}
|
||||
|
||||
func NewNetworkController(kubeconfig, openstackConfigFile string) (*NetworkController, error) {
|
||||
// Create OpenStack client from config
|
||||
openstack, err := osDriver.NewClient(openstackConfigFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Couldn't initialize openstack: %#v", err)
|
||||
}
|
||||
|
||||
// Create the client config. Use kubeconfig if given, otherwise assume in-cluster.
|
||||
config, err := buildConfig(kubeconfig)
|
||||
config, err := util.NewClusterConfig(kubeconfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build kubeconfig: %v", err)
|
||||
}
|
||||
@ -87,15 +70,14 @@ func NewNetworkController(kubeconfig, openstackConfigFile string) (*NetworkContr
|
||||
return nil, fmt.Errorf("failed to create CRD to kube-apiserver: %v", err)
|
||||
}
|
||||
|
||||
// make a new config for our extension's API group, using the first config as a baseline
|
||||
networkClient, networkScheme, err := crdClient.NewClient(config)
|
||||
// Create OpenStack client from config
|
||||
openstack, err := osDriver.NewClient(openstackConfigFile, kubeconfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create client for CRD: %v", err)
|
||||
return nil, fmt.Errorf("Couldn't initialize openstack: %#v", err)
|
||||
}
|
||||
|
||||
networkController := &NetworkController{
|
||||
networkClient: networkClient,
|
||||
networkScheme: networkScheme,
|
||||
kubeCRDClient: openstack.CRDClient,
|
||||
driver: openstack,
|
||||
}
|
||||
return networkController, nil
|
||||
@ -109,7 +91,7 @@ func (c *NetworkController) onAdd(obj interface{}) {
|
||||
// NEVER modify objects from the store. It's a read-only, local cache.
|
||||
// You can use networkScheme.Copy() to make a deep copy of original object and modify this copy
|
||||
// Or create a copy manually for better performance
|
||||
copyObj, err := c.networkScheme.Copy(network)
|
||||
copyObj, err := c.GetKubeCRDClient().Scheme.Copy(network)
|
||||
if err != nil {
|
||||
glog.Errorf("ERROR creating a deep copy of network object: %v\n", err)
|
||||
return
|
||||
|
@ -26,18 +26,21 @@ func (c *NetworkController) addNetworkToDriver(kubeNetwork *crv1.Network) {
|
||||
if err != nil || tenantID == "" {
|
||||
err = wait.Poll(2*time.Second, 10*time.Second, func() (bool, error) {
|
||||
tenantID, err = c.driver.GetTenantIDFromName(kubeNetwork.GetNamespace())
|
||||
if err != nil || tenantID == "" {
|
||||
glog.V(5).Infof("failed to fetch tenantID for tenantName: %v, retrying\n", tenantName)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to fetch tenantID for tenantName: %v, error: %v retrying\n", tenantName, err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if tenantID == "" {
|
||||
glog.V(5).Infof("tenantID is empty for tenantName: %v, retrying\n", tenantName)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
if err != nil || tenantID == "" {
|
||||
glog.Errorf("failed to fetch tenantID for tenantName: %v, abort! \n", tenantName)
|
||||
glog.Errorf("failed to fetch tenantID for tenantName: %v, error: %v abort! \n", tenantName, err)
|
||||
return
|
||||
} else {
|
||||
glog.V(3).Infof("Got tenantID: %v for tenantName: %v", tenantID, tenantName)
|
||||
}
|
||||
|
||||
networkName := util.BuildNetworkName(tenantName, kubeNetwork.GetName())
|
||||
@ -69,7 +72,7 @@ func (c *NetworkController) addNetworkToDriver(kubeNetwork *crv1.Network) {
|
||||
if !check {
|
||||
glog.Warningf("[NetworkController]: tenantID %s doesn't exist in network provider", driverNetwork.TenantID)
|
||||
kubeNetwork.Status.State = crv1.NetworkFailed
|
||||
c.updateNetwork(kubeNetwork)
|
||||
c.kubeCRDClient.UpdateNetwork(kubeNetwork)
|
||||
return
|
||||
}
|
||||
|
||||
@ -104,22 +107,5 @@ func (c *NetworkController) addNetworkToDriver(kubeNetwork *crv1.Network) {
|
||||
}
|
||||
|
||||
kubeNetwork.Status.State = newNetworkStatus
|
||||
c.updateNetwork(kubeNetwork)
|
||||
}
|
||||
|
||||
// updateNetwork updates Network CRD object by given object
|
||||
func (c *NetworkController) updateNetwork(network *crv1.Network) {
|
||||
err := c.networkClient.Put().
|
||||
Name(network.Name).
|
||||
Namespace(network.Namespace).
|
||||
Resource(crv1.NetworkResourcePlural).
|
||||
Body(network).
|
||||
Do().
|
||||
Error()
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("ERROR updating network status: %v\n", err)
|
||||
} else {
|
||||
glog.V(3).Infof("UPDATED network status: %#v\n", network)
|
||||
}
|
||||
c.kubeCRDClient.UpdateNetwork(kubeNetwork)
|
||||
}
|
||||
|
@ -5,8 +5,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
|
||||
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
|
||||
drivertypes "git.openstack.org/openstack/stackube/pkg/openstack/types"
|
||||
"git.openstack.org/openstack/stackube/pkg/util"
|
||||
|
||||
"github.com/docker/distribution/uuid"
|
||||
"github.com/golang/glog"
|
||||
"github.com/gophercloud/gophercloud"
|
||||
@ -21,6 +24,7 @@ import (
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
|
||||
gcfg "gopkg.in/gcfg.v1"
|
||||
)
|
||||
|
||||
@ -51,6 +55,7 @@ type Client struct {
|
||||
ExtNetID string
|
||||
PluginName string
|
||||
IntegrationBridge string
|
||||
CRDClient *crdClient.CRDClient
|
||||
}
|
||||
|
||||
type PluginOpts struct {
|
||||
@ -79,7 +84,7 @@ func toAuthOptions(cfg Config) gophercloud.AuthOptions {
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(config string) (*Client, error) {
|
||||
func NewClient(config string, kubeConfig string) (*Client, error) {
|
||||
var opts gophercloud.AuthOptions
|
||||
cfg, err := readConfig(config)
|
||||
if err != nil {
|
||||
@ -118,6 +123,16 @@ func NewClient(config string) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create CRD client
|
||||
k8sConfig, err := util.NewClusterConfig(kubeConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build kubeconfig: %v", err)
|
||||
}
|
||||
kubeCRDClient, err := crdClient.NewCRDClient(k8sConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create client for CRD: %v", err)
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Identity: identity,
|
||||
Provider: provider,
|
||||
@ -126,6 +141,7 @@ func NewClient(config string) (*Client, error) {
|
||||
ExtNetID: cfg.Global.ExtNetID,
|
||||
PluginName: cfg.Plugin.PluginName,
|
||||
IntegrationBridge: cfg.Plugin.IntegrationBridge,
|
||||
CRDClient: kubeCRDClient,
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
@ -147,8 +163,22 @@ func (c *Client) GetTenantIDFromName(tenantName string) (string, error) {
|
||||
if util.IsSystemNamespace(tenantName) {
|
||||
tenantName = util.SystemTenant
|
||||
}
|
||||
|
||||
// If tenantID is specified, return it directly
|
||||
var (
|
||||
tenant *crv1.Tenant
|
||||
err error
|
||||
)
|
||||
if tenant, err = c.CRDClient.GetTenant(tenantName); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if tenant.Spec.TenantID != "" {
|
||||
return tenant.Spec.TenantID, nil
|
||||
}
|
||||
|
||||
// Otherwise, fetch tenantID from OpenStack
|
||||
var tenantID string
|
||||
err := tenants.List(c.Identity, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
err = tenants.List(c.Identity, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
tenantList, err1 := tenants.ExtractTenants(page)
|
||||
if err1 != nil {
|
||||
return false, err1
|
||||
@ -164,6 +194,9 @@ func (c *Client) GetTenantIDFromName(tenantName string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Got tenantID: %v for tenantName: %v", tenantID, tenantName)
|
||||
|
||||
return tenantID, nil
|
||||
}
|
||||
|
||||
|
@ -14,13 +14,18 @@ import (
|
||||
)
|
||||
|
||||
func NewClusterConfig(kubeConfig string) (*rest.Config, error) {
|
||||
cfg, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if kubeConfig != "" {
|
||||
cfg, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.QPS = 100
|
||||
cfg.Burst = 100
|
||||
return cfg, nil
|
||||
|
||||
} else {
|
||||
return rest.InClusterConfig()
|
||||
}
|
||||
cfg.QPS = 100
|
||||
cfg.Burst = 100
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func WaitForCRDReady(clientset apiextensionsclient.Interface, crdName string) error {
|
||||
|
Loading…
x
Reference in New Issue
Block a user