docker k8s二次開發(一) 註冊自定義api

dota_cloud發表於2017-10-18


package main

import (
	"fmt"
	"math/rand"
	"os"
	"time"
	"wdcp-build/apiserver/app"
	"wdcp-build/apiserver/options"

	"github.com/spf13/pflag"
	"k8s.io/apiserver/pkg/util/flag"
	"k8s.io/kubernetes/pkg/util/logs"
)

func main() {
	rand.Seed(time.Now().UTC().UnixNano())

	s := options.NewServerRunOptions()
	s.AddFlags(pflag.CommandLine)

	flag.InitFlags()
	logs.InitLogs()
	defer logs.FlushLogs()

	// verflag.PrintAndExitIfRequested()

	if err := app.Run(s); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
}

package app

import (
	"wdcp-build/apiserver/options"
	"wdcp-build/pkg/master"
)

func Run(s *options.ServerRunOptions) error {
	// glog.Info("config-file>>>%s", s.ConfigFile)
	// glog.Info("pkg-mac>>>>%s", s.PackageMac)
	// glog.Info("docker-endpoints>>>%s", s.DockerEndpoints)
	// client, err := s.NewSelfClient()
	// if err != nil {
	// 	glog.Errorf("Failed to create clientset: %v", err)
	// }
	// sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute)

	config := &master.Config{
		ServerRunConfig: s,
	}

	m, err := master.New(config)
	if err != nil {
		return err
	}
	// sharedInformers.Start(wait.NeverStop)

	m.Run(s)
	return nil
}


package master

import (
	"fmt"
	"log"
	"net/http"
	"wdcp-build/apiserver/options"

	"wdcp-build/pkg/apiserver"
	"wdcp-build/pkg/util"

	"github.com/emicklei/go-restful"
	"github.com/golang/glog"
)

type Master struct {
	HandlerContainer *restful.Container
}

type Config struct {
	ServerRunConfig *options.ServerRunOptions
}

func New(c *Config) (*Master, error) {
	isExist, err := util.PathExists(c.ServerRunConfig.ConfigFile)
	if !isExist {
		return nil, err
	}

	util.RunOption, err = util.ReadFile(c.ServerRunConfig.ConfigFile)
	if err != nil {
		return nil, err
	}

	// glog.Info("RunOptions>>>>>%s", util.RunOption)

	container := restful.NewContainer()
	m := &Master{
		HandlerContainer: container,
	}
	m.InstallAPIs(c)
	return m, nil
}

func (s *Master) Run(options *options.ServerRunOptions) {
	addr := fmt.Sprintf(":%d", util.RunOption.InsecurePort)
	http := &http.Server{
		Addr:           addr,
		Handler:        s.HandlerContainer,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(http.ListenAndServe())
}

func (m *Master) InstallAPIs(c *Config) {
	for _, installer := range apiserver.APIInstallerList {
		if err := installer.InstallREST(m.HandlerContainer, c.ServerRunConfig); err != nil {
			glog.Error("%v", err)
		}
	}
}


package master

import (
	"fmt"
	"log"
	"net/http"
	"wdcp-build/apiserver/options"

	"wdcp-build/pkg/apiserver"
	"wdcp-build/pkg/util"

	"github.com/emicklei/go-restful"
	"github.com/golang/glog"
)

type Master struct {
	HandlerContainer *restful.Container
}

type Config struct {
	ServerRunConfig *options.ServerRunOptions
}

func New(c *Config) (*Master, error) {
	isExist, err := util.PathExists(c.ServerRunConfig.ConfigFile)
	if !isExist {
		return nil, err
	}

	util.RunOption, err = util.ReadFile(c.ServerRunConfig.ConfigFile)
	if err != nil {
		return nil, err
	}

	// glog.Info("RunOptions>>>>>%s", util.RunOption)

	container := restful.NewContainer()
	m := &Master{
		HandlerContainer: container,
	}
	m.InstallAPIs(c)
	return m, nil
}

func (s *Master) Run(options *options.ServerRunOptions) {
	addr := fmt.Sprintf(":%d", util.RunOption.InsecurePort)
	http := &http.Server{
		Addr:           addr,
		Handler:        s.HandlerContainer,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(http.ListenAndServe())
}

func (m *Master) InstallAPIs(c *Config) {
	for _, installer := range apiserver.APIInstallerList {
		if err := installer.InstallREST(m.HandlerContainer, c.ServerRunConfig); err != nil {
			glog.Error("%v", err)
		}
	}
}



package apiserver

import (
	"fmt"
	"time"

	"wdcp-build/apiserver/options"
	"wdcp-build/pkg/api/unversioned"

	restful "github.com/emicklei/go-restful"
)

type APIInstaller struct {
	groupVersion      string
	prefix            string
	apiMappings       []ApiMapping
	minRequestTimeout time.Duration
	serverRunConfig   *options.ServerRunOptions
}

type ApiMapping struct {
	path       string
	verb       string
	apiHandler restful.RouteFunction
}

// NewWebService creates a new restful webservice with the api installer's prefix and version.
func (a *APIInstaller) NewWebService() *restful.WebService {
	ws := new(restful.WebService)
	wsPath := a.groupVersion + a.prefix
	fmt.Println(wsPath)
	ws.Path(wsPath)
	ws.Doc("API at " + wsPath)
	ws.Consumes(restful.MIME_JSON)
	ws.Produces(restful.MIME_JSON)
	return ws
}

// Installs handlers for API resources.
func (a *APIInstaller) Install(ws *restful.WebService) (apiResources []unversioned.APIResource, errors []error) {
	errors = make([]error, 0)

	apiResource, err := a.registerResourceHandlers(ws)
	if apiResource != nil {
		apiResources = append(apiResources, *apiResource)
	}
	if err != nil {
		errors = append(errors, fmt.Errorf("error in registering resource: %s, %v", a.prefix, err))
	}
	return apiResources, errors
}

func (a *APIInstaller) registerResourceHandlers(ws *restful.WebService) (*unversioned.APIResource, error) {
	var apiResource unversioned.APIResource

	var router *restful.RouteBuilder
	for _, apiMap := range a.apiMappings {
		// fmt.Println(apiMap.verb)
		// fmt.Println(apiMap.path)
		// fmt.Println(apiMap.apiHandler)
		switch apiMap.verb {
		case unversioned.VERB_POST:
			router = ws.POST(apiMap.path).To(apiMap.apiHandler)
			ws.Route(router)
		case unversioned.VERB_GET:
			router = ws.GET(apiMap.path).To(apiMap.apiHandler)
			ws.Route(router)
		case unversioned.VERB_PUT:
			router = ws.PUT(apiMap.path).To(apiMap.apiHandler)
			ws.Route(router)
		case unversioned.VERB_DELETE:
			router = ws.DELETE(apiMap.path).To(apiMap.apiHandler)
			ws.Route(router)
		}

	}
	return &apiResource, nil
}



package apiserver

import (
	"wdcp-build/apiserver/options"
	"wdcp-build/pkg/buildengine"
	"wdcp-build/pkg/k8sengine"
	"wdcp-build/pkg/task"

	restful "github.com/emicklei/go-restful"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
)

var APIInstallerList = []APIInstaller{
	{
		groupVersion: "/v1",
		prefix:       "/test",
		apiMappings: []ApiMapping{
			{
				path:       "/{user-id}",
				verb:       "GET",
				apiHandler: buildimage.TestHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/code/branch",
		apiMappings: []ApiMapping{
			{
				path:       "",
				verb:       "POST",
				apiHandler: buildimage.BranchHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/code/version",
		apiMappings: []ApiMapping{
			{
				path:       "/{project_name}/{branch}/{task_event_uuid}",
				verb:       "GET",
				apiHandler: buildimage.CodeVersionHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/build",
		apiMappings: []ApiMapping{
			{
				path:       "",
				verb:       "POST",
				apiHandler: buildimage.BuildHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/task",
		apiMappings: []ApiMapping{
			{
				path:       "/{task_event_uuid}",
				verb:       "GET",
				apiHandler: task.TaskHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/app",
		apiMappings: []ApiMapping{
			{
				path:       "",
				verb:       "POST",
				apiHandler: k8sengine.CreateK8sHandler,
			},
			{
				path:       "",
				verb:       "DELETE",
				apiHandler: k8sengine.DeleteHandler,
			},
			{
				path:       "",
				verb:       "PUT",
				apiHandler: k8sengine.UpdateK8sHandler,
			},
			{
				path:       "/deployment/{cluster_level}/{tenant}/{project_name}",
				verb:       "GET",
				apiHandler: k8sengine.GetDeploymentHandler,
			},
			{
				path:       "/statefulset/{cluster_level}/{tenant}/{project_name}",
				verb:       "GET",
				apiHandler: k8sengine.GetStatefulSetHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/ns",
		apiMappings: []ApiMapping{
			{
				path:       "",
				verb:       "POST",
				apiHandler: k8sengine.CreateNsHandler,
			},
			{
				path:       "/{cluster_level}/{namespace}",
				verb:       "GET",
				apiHandler: k8sengine.GetNamespaceHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/vaddr",
		apiMappings: []ApiMapping{
			{
				path:       "/{cluster_level}/{tenant}/{project_name}",
				verb:       "GET",
				apiHandler: k8sengine.GetVisitAddrHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/pod",
		apiMappings: []ApiMapping{
			{
				path:       "/{cluster_level}/{tenant}/{project_name}",
				verb:       "GET",
				apiHandler: k8sengine.GetPodStatusHandler,
			},
			{
				path:       "/log/{cluster_level}/{tenant}/{project_name}/{pod_name}",
				verb:       "GET",
				apiHandler: k8sengine.GetPodLogHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/pods",
		apiMappings: []ApiMapping{
			{
				path:       "",
				verb:       "POST",
				apiHandler: k8sengine.ListPodsStatusHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/scale",
		apiMappings: []ApiMapping{
			{
				path:       "",
				verb:       "POST",
				apiHandler: k8sengine.ScaleK8sHandler,
			},
		},
	},
	{
		groupVersion: "/v1",
		prefix:       "/list",
		apiMappings: []ApiMapping{
			{
				path:       "/ns/{cluster_level}/{tenant}",
				verb:       "GET",
				apiHandler: k8sengine.ListResNamespaceHandler,
			},
			{
				path:       "/node/{cluster_level}/{tenant}",
				verb:       "GET",
				apiHandler: k8sengine.ListResNodeHandler,
			},
			{
				path:       "/deployment/{cluster_level}/{tenant}",
				verb:       "GET",
				apiHandler: k8sengine.ListResDeploymentHandler,
			},
			{
				path:       "/statefulset/{cluster_level}/{tenant}",
				verb:       "GET",
				apiHandler: k8sengine.ListResStatefulSetHandler,
			},
			{
				path:       "/service/{cluster_level}/{tenant}",
				verb:       "GET",
				apiHandler: k8sengine.ListResServiceHandler,
			},
			{
				path:       "/pod/{cluster_level}/{tenant}",
				verb:       "GET",
				apiHandler: k8sengine.ListResPodHandler,
			},
		},
	},
}

func (installer *APIInstaller) InstallREST(container *restful.Container, c *options.ServerRunOptions) error {

	ws := installer.NewWebService()

	_, registrationErrors := installer.Install(ws)

	container.Add(ws)

	return utilerrors.NewAggregate(registrationErrors)

}




相關文章