Sitelet https://github.com/koding/kloud-provider-example
Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

kloud-provider-example

This repository is an example of custom Kloud provider plugin.

Kloud is a backend behind Koding that is responsible for bootstrapping, building and destroying user stacks and managing access to each machine instance within those stacks.

Requirements

Installation

A new Kloud provider can be added by simply clonning your provider plugin into kloud/provider directory and rebuilding Kloud.

koding $ git clone git@github.com:kloud/kloud-provider-example go/src/koding/kites/kloud/provider/example
koding $ ./go/build.sh

Plugins

A Kloud provider is responsible for composing a single Terraform template from multiple data sources:

  • stack template
  • credentials
  • bootstrapped resources

A single Kloud provider validates credentials provided by a user, bootstraps a stack by creating provider-specific, persistant resources and provisions a Klient service for each instance built within a stack. The Klient service is used to connect remote machine to Koding allowing for webterm sessions in the browser, machine-sharing with other Koding users and starting / stopping the machine itself.

Example plugin

This repository contains a documented example of a Kloud provider plugin - example.go.

The Koding repository contains more examples of Kloud providers:

Quick start

Go services in Koding repository use currently project-based GOPATH, that's why ensure you point your GOPATH to the go directory inside Koding repository:

~ $ export GOPATH=~/github.com/koding/koding/go

A project structure of your Kloud provider may look like the following:

your/
├── your.go        <-- registers *provider.Provider
├── machine.go     <-- defines *Machine struct
├── schema.go      <-- defines *Credential, *Bootstrap and *Metadata structs
└── stack.go       <-- defines *Stack struct
  • example.go registers provider definition (like this one)

The content of this file is:

package your

import (
	"koding/kites/kloud/stack"
	"koding/kites/kloud/stack/provider"
)

var p = &provider.Provider{
	Name:         "your",
	ResourceName: "instance",
	
	// Machine type is defined in machine.go
	Machine: func(bm *provider.BaseMachine) (provider.Machine, error) {
		return &Machine{BaseMachine: bm}, nil
	},
	
	// Stack type is defined in stack.go
	Stack: func(bs *provider.BaseStack) (provider.Stack, error) {
		return &Stack{BaseStack: bs}, nil
	},
	
	// Schema value is defined in schema.go 
	Schema: Schema,
}

func init() {
	provider.Register(p)
}
  • schema.go defines models which are used to persist provider data (like this one)

And its contents:

package your

import "koding/kites/kloud/stack/provider"

var Schema = &provider.Schema{
	NewCredential: func() interface{} { return &Credential{} },
	NewBootstrap:  func() interface{} { return &Bootstrap{} },
	NewMetadata:   func(*stack.Machine) interface{} { &Metadata{} },
}

type Credential struct {
	User string
	Pass string
}

type Bootstrap struct {
	PersistentResourceName string
}

type Metadata struct {
	MachineRegion string
	MachineCNAME  string
}

If any of the schema types implement the following interface:

type Validator interface {
	Valid() error
}

the Valid() method is going to be called after reading the value from Koding database / safe store in order to validate it.

More details on schema can be found here, here and here.

  • stack.go defines a Stack struct which implements the provider.Stack interface

The stub definition looks like:

package your

import (
	"errors"

	"koding/kites/kloud/stack"
	"koding/kites/kloud/stack/provider"
)

var errNotImplemented = errors.New("not implemented")

type Stack struct {
	*provider.BaseStack
}

func (*Stack) VerifyCredential(*stack.Credential) error {
	return errNotImplemented
}

func (*Stack) BootstrapTemplates(*stack.Credential) ([]*stack.Template, error) {
	return nil, errNotImplemented
}

func (*Stack) ApplyTemplate(*stack.Credential) (*stack.Template, error) {
	return nil, errNotImplemented
}

More details on expected behavior of each method can be found here, here and here.

  • and machine.go, which defines *Machine for controlling single remote machine

The stub:

package your

import (
	"errors"

	"koding/kites/kloud/machinestate"
	"koding/kites/kloud/stack/provider"

	"golang.org/x/net/context"
)

var errNotImplemented = errors.New("not implemented")

type Machine struct {
	*provider.BaseMachine
}

func (*Machine) Start(context.Context) (metadata interface{}, err error) {
	return nil, errNotImplemented
}

func (*Machine) Stop(context.Context) (metadata interface{}, err error) {
	return nil, errNotImplemented
}

func (*Machine) Info(context.Context) (state machinestate.State, metadata interface{}, err error) {
	return 0, nil, errNotImplemented
}

More details here and an example of AWS implementation.

Final notes

The *provider.BaseMachine and *provider.BaseStack API should be considered not stable, thus a subject to change. Usually it means a rename here and there or new fields that remove the boilerplate even further.

Relavant issues:

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages