Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,26 @@ Acceptance tests need an authentication token and an Online.net server which wil
The server will be modified, using a production system is not adviced. All used servers must support RPNv2.
It will look for:

| Environment Variable | Description | Example |
|----------------------|------------------------------------------------------------------------------|-------------|
| `ONLINE_SERVER_ID` | ID of a dedicated server (only the numeric part) | `46952` |
| `ONLINE_SERVER_ID_2` | ID of a 2nd dedicated server (only the numeric part) | `46953` |
| `ONLINE_FAILVOVER_IP` | An available failover IP | `81.23.14.1`|
| `ONLINE_TOKEN` | Online.net auth token received from https://console.online.net/en/api/access | |
| Environment Variable | Description | Example |
|----------------------|-----------------------------------------------------------------------------------|-------------|
| `ONLINE_SERVER_ID` | ID of a dedicated server (only the numeric part) | `46952` |
| `ONLINE_SERVER_ID_2` | ID of a 2nd dedicated server (only the numeric part) | `46953` |
| `ONLINE_FAILVOVER_IP`| An available failover IP | `81.23.14.1`|
| `ONLINE_TOKEN` | Online.net auth token received from https://console.online.net/en/api/access | |
| `ONLINE_SSHUUID_1` | One of ssh uuid listed from https://console.online.net/en/account/ssh-keys | |
| `ONLINE_TEMPLATE_REF`| One of template uuid listed from https://console.online.net/en/template/partition | |

```sh
$ make testacc
```

You can also run a dedicated acceptance test, here an example:

```sh
$ make test-compile TEST=./provider
$ ONLINE_TOKEN=<token> ONLINE_SERVER_ID=<id> TF_ACC=1 ./provider.test -test.run TestDataOperatingSystemAcceptance -test.v
```

## License

Mozilla Public License Version 2.0, see [LICENSE](/LICENSE)
Expand Down
36 changes: 36 additions & 0 deletions docs/server_install_example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Install Online Server

Here a full example to setup a Online server with your ssh keys.
You can put a wrong OS information to get an error message
with the available OS for your server. Then you can find or
create the `partitioning_template_ref` field from the
[template page](https://console.online.net/en/template).

```HCL
provider "online" {
}

variable "server_id" {
type = string
}

data "online_operating_system" "os" {
server_id = var.server_id
name = "centos"
version = "CentOS 7.6"
}

data "online_ssh_keys" "keys" {
}

resource "online_server" "nicofonk" {
server_id = var.server_id
hostname = "online-server"
os_id = "${data.online_operating_system.os.os_id}"
user_login = "user1"
user_password = "userpassword"
root_password = "rootpassword"
partitioning_template_ref = "13e84239-f208-4374-9ac2-8737a46211c6"
ssh_keys = "${data.online_ssh_keys.keys.ssh_keys}"
}
```
58 changes: 58 additions & 0 deletions online/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type responseType int
const (
serverEndPoint = "https://api.online.net/api/v1/server"
rpnv2EndPoint = "https://api.online.net/api/v1/rpn/v2"
userEndPoint = "https://api.online.net/api/v1/user"

responseBoolean responseType = iota
responseJSON
Expand All @@ -26,6 +27,8 @@ const (
type Client interface {
Server(id int) (*Server, error)
SetServer(s *Server) error
InstallServer(id int, s *ServerInstall) error
ListOperatingSystems(id int) (*OperatingSystems, error)

BootRescueMode(serverID int, image string) (*RescueCredentials, error)
BootNormalMode(serverID int) error
Expand All @@ -41,6 +44,8 @@ type Client interface {
RPNv2ByName(name string) (*RPNv2, error)
SetRPNv2(r *RPNv2, wait time.Duration) error
DeleteRPNv2(id int, wait time.Duration) error

ListSSHKeys() (*SSHKeys, error)
}

func NewClient(token string) Client {
Expand Down Expand Up @@ -165,6 +170,46 @@ func (c *client) Server(id int) (*Server, error) {
return s, json.Unmarshal(js, s)
}

func (c *client) InstallServer(id int, s *ServerInstall) error {
target := fmt.Sprintf("%s/install/%d", serverEndPoint, id)

keys, err := json.Marshal(s.SSHKeys)
if err != nil {
return err
}

_, err = c.doPOST(target, map[string]string{
"hostname": s.Hostname,
"os_id": s.OS_ID,
"user_login": s.UserLogin,
"user_password": s.UserPassword,
"root_password": s.RootPassword,
"partitioning_template_ref": s.PartitioningTemplateRef,
"ssh_keys": string(keys),
})
if err != nil {
return err
}

return nil
}

func (c *client) ListOperatingSystems(id int) (*OperatingSystems, error) {
target := fmt.Sprintf("%s/operatingSystems/%d", serverEndPoint, id)

js, err := c.doGET(target)
if err != nil {
return nil, err
}

systems := &OperatingSystems{}
err = json.Unmarshal(js, systems)
if err != nil {
return nil, err
}
return systems, nil
}

func (c *client) ListRPNv2() ([]*RPNv2, error) {
js, err := c.doGET(rpnv2EndPoint)
if err != nil {
Expand Down Expand Up @@ -449,3 +494,16 @@ Unexpected:
func (e *ErrorResponse) Error() string {
return fmt.Sprintf("%s (code: %d)", e.Message, e.Code)
}

func (c *client) ListSSHKeys() (*SSHKeys, error) {
target := fmt.Sprintf("%s/key/ssh", userEndPoint)

// XXX: add pagination support
js, err := c.doGET(target)
if err != nil {
return nil, err
}

var keys SSHKeys
return &keys, json.Unmarshal(js, &keys)
}
18 changes: 18 additions & 0 deletions online/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ func (o *OnlineClientMock) SetServer(s *online.Server) error {
return args.Error(0)
}

// InstallServer is a mock call
func (o *OnlineClientMock) InstallServer(id int, s *online.ServerInstall) error {
args := o.Called(id, s)
return args.Error(0)
}

// ListOperatingSystems is a mock call
func (o *OnlineClientMock) ListOperatingSystems(id int) (*online.OperatingSystems, error) {
args := o.Called(id)
return args.Get(0).(*online.OperatingSystems), args.Error(1)
}

// GetRescueImages is a mock call
func (o *OnlineClientMock) GetRescueImages(serverID int) ([]string, error) {
args := o.Called(serverID)
Expand Down Expand Up @@ -89,3 +101,9 @@ func (o *OnlineClientMock) DeleteMACFailoverIP(address string) error {
args := o.Called(address)
return args.Error(0)
}

// ListSSHKeys is a mock call
func (o *OnlineClientMock) ListSSHKeys() (*online.SSHKeys, error) {
args := o.Called()
return args.Get(0).(*online.SSHKeys), args.Error(1)
}
30 changes: 30 additions & 0 deletions online/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type Server struct {
OS interface{} `json:"os"`
Power string `json:"power"`
BootMode string `json:"boot_mode"`
InstallStatus string `json:"install_status"`
LastReboot string `json:"last_reboot"`
AntiDDOS bool `json:"anti_ddos"`
HardwareWatch bool `json:"hardware_watch"`
Expand Down Expand Up @@ -44,11 +45,32 @@ type Server struct {
} `json:"bmc"`
}

type ServerInstall struct {
Hostname string `json:"hostname"`
OS_ID string `json:"os_id"`
UserLogin string `json:"user_login"`
UserPassword string `json:"user_password"`
RootPassword string `json:"root_password"`
PartitioningTemplateRef string `json:"partitioning_template_ref"`
SSHKeys []string `json:"ssh_keys"`
}

type OS struct {
Name string `json:"name"`
Version string `json:"version"`
}

type OperatingSystem struct {
OS
ID int `json:"id"`
Type string `json:"type"`
Arch string `json:"arch"`
Release string `json:"release"`
EndOfLife string `json:"end_of_life"`
}

type OperatingSystems []OperatingSystem

type InterfaceType string

const (
Expand Down Expand Up @@ -81,3 +103,11 @@ func (s *Server) InterfaceByType(t InterfaceType) *Interface {

return nil
}

type SSHKey struct {
UUID string `json:"uuid_ref"`
Description string `json:"description"`
Fingerprint string `json:"fingerprint"`
}

type SSHKeys []SSHKey
65 changes: 65 additions & 0 deletions provider/data_operating_systems.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package provider

import (
"encoding/json"
"fmt"

"github.com/src-d/terraform-provider-online/online"

"github.com/hashicorp/terraform/helper/schema"
)

func dataOperatingSystem() *schema.Resource {
return &schema.Resource{
Read: dataOperatingSystemRead,
Schema: map[string]*schema.Schema{
"server_id": {
Type: schema.TypeInt,
Required: true,
Description: "server id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "exact name of the desired system",
},
"version": {
Type: schema.TypeString,
Required: true,
Description: "version name of the desired system",
},
"os_id": {
Type: schema.TypeInt,
Computed: true,
Description: "identifier of the desired system",
},
},
}
}

func dataOperatingSystemRead(d *schema.ResourceData, meta interface{}) error {
c := meta.(online.Client)

serverID := d.Get("server_id").(int)
name := d.Get("name").(string)
version := d.Get("version").(string)

systems, err := c.ListOperatingSystems(serverID)
if err != nil {
return err
}

for _, os := range *systems {
if os.Version == version && os.Name == name {
d.Set("os_id", os.ID)
d.SetId(fmt.Sprintf("%d", os.ID))
return nil
}
}

b, err := json.Marshal(systems)
if err != nil {
return err
}
return fmt.Errorf("unable to find OS: %s %s, available ones are %s", name, version, b)
}
75 changes: 75 additions & 0 deletions provider/data_operating_systems_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package provider

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/src-d/terraform-provider-online/online"
)

func TestDataOperatingSystem(t *testing.T) {
onlineClientMock.On("ListOperatingSystems", 123).Return(&online.OperatingSystems{online.OperatingSystem{
OS: online.OS{
Name: "centos",
Version: "CentOS 7.6",
},
ID: 305,
Type: "server",
Release: "2014-07-06T22:00:00.000Z",
Arch: "64 bits",
}}, nil)
resource.Test(t, resource.TestCase{
Providers: testMockProviders,
IsUnitTest: true,
Steps: []resource.TestStep{
{
ImportStateVerify: false,
Config: `
data "online_operating_system" "test" {
name = "centos"
version = "CentOS 7.6"
server_id = 123
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.online_operating_system.test", "os_id", "305"),
),
},
{
ImportStateVerify: false,
Config: `
data "online_operating_system" "test" {
name = "centos"
version = "CentOS 666"
server_id = 123
}
`,
ExpectError: regexp.MustCompile("unable to find OS"),
},
},
})
}

func TestDataOperatingSystemAcceptance(t *testing.T) {
resource.Test(t, resource.TestCase{
Providers: testAccProviders,
IsUnitTest: false,
Steps: []resource.TestStep{
{
ImportStateVerify: false,
Config: fmt.Sprintf(`
data "online_operating_system" "test" {
name = "centos"
version = "CentOS 7.6"
server_id = %s
}
`, TestServerID),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.online_operating_system.test", "os_id", "305"),
),
},
},
})
}
Loading