https://github.com/koding/kloud-provider-example
https://github.com/koding/kloud-provider-example
Last synced: 10 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/koding/kloud-provider-example
- Owner: koding
- License: apache-2.0
- Created: 2016-09-12T13:32:31.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2016-10-06T00:59:53.000Z (about 9 years ago)
- Last Synced: 2025-01-20T10:11:30.472Z (11 months ago)
- Language: Go
- Size: 17.6 KB
- Stars: 1
- Watchers: 5
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
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
- [go1.6+](https://golang.org/dl/)
## Installation
A new Kloud provider can be added by simply clonning your provider plugin into `kloud/provider` directory and rebuilding Kloud.
```bash
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](./example.go).
The [Koding repository](https://github.com/koding/koding) contains more examples of Kloud providers:
- [AWS](https://github.com/koding/koding/tree/master/go/src/koding/kites/kloud/provider/aws)
- [Vagrant](https://github.com/koding/koding/tree/master/go/src/koding/kites/kloud/provider/vagrant)
- [Digital Ocean](https://github.com/koding/koding/tree/master/go/src/koding/kites/kloud/provider/do)
# 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:
```bash
~ $ 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](./example.go#L18-L105))
The content of this file is:
```go
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](./example.go#L92-L104))
And its contents:
```go
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:
```go
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](./example.go#L71-L91), [here](./example.go#L134-L155) and [here](./example.go#L191-L216).
- `stack.go` defines a Stack struct which implements the `provider.Stack` interface
The stub definition looks like:
```go
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](./example.go#L223-L236), [here](./example.go#L238-L247) and [here](./example.go#L249-L338).
- and `machine.go`, which defines \*Machine for controlling single remote machine
The stub:
```go
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](./example.go#L157-L189) and [an example of AWS implementation](https://github.com/koding/koding/blob/358a070fd24700cee4a39dc556ad79164f3b9918/go/src/koding/kites/kloud/provider/aws/machine.go#L42-L68).
## 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:
- https://github.com/koding/koding/issues/9127
- https://github.com/koding/koding/issues/8903