Compare commits

...

4 Commits
v2.0.0 ... 2.0

Author SHA1 Message Date
kjubybot
94f222fe19 k8s: fixed state import; k8s, k8s_wg: increased create/update timeouts 2022-03-29 17:45:59 +03:00
kjubybot
a3da44f2ad k8s, k8s_wg: single worker add/delete support; github actions support 2022-03-28 16:05:29 +03:00
stSolo
ef7fa62e79 Fix README files 2022-03-25 18:48:03 +03:00
stSolo
4bb75fe0d7 Add samples for k8s, k8s_wg, edit README files 2022-03-25 18:45:37 +03:00
13 changed files with 348 additions and 36 deletions

37
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Release to registry
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Fetch all tags
run: git fetch --force --tags
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v4
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
args: release --rm-dist --release-notes CHANGELOG.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}

View File

@@ -1,14 +1,8 @@
# Visit https://goreleaser.com for documentation on how to customize this
# behavior.
before:
hooks:
# this is just an example and not a requirement for provider building/publishing
- go mod tidy
builds:
- env:
# goreleaser does not work with CGO, it could also complicate
# usage by users in CI/CD systems like Terraform Cloud where
# they are unable to install libraries.
- CGO_ENABLED=0
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
@@ -37,11 +31,9 @@ checksum:
signs:
- artifacts: checksum
args:
# if you are using this in a GitHub action or some other automated pipeline, you
# need to pass the batch flag to indicate its not interactive.
- "--batch"
- "--local-user"
- "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key
- "{{ .Env.GPG_FINGERPRINT }}"
- "--output"
- "${signature}"
- "--detach-sign"
@@ -50,7 +42,5 @@ release:
extra_files:
- glob: 'terraform-registry-manifest.json'
name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
# If you want to manually examine the release before its live, uncomment this line:
# draft: true
changelog:
skip: true
skip: false

5
CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
### Bug fixes
- k8s state import
### Minor changes
- increased k8s and k8s\_wg create/update timeouts

View File

@@ -107,8 +107,11 @@ terraform init
Более подробно о сборке провайдера можно найти по ссылке: https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers
## Примеры работы
Примеры работы можно найти на:
- Вики проекта: https://github.com/rudecs/terraform-provider-decort/wiki
- В папке `samples`
Примеры работы можно найти:
- На вики проекта: https://github.com/rudecs/terraform-provider-decort/wiki
- В папке `samples`
Схемы к terraform'у доступны:
- В папке `docs`
Хорошей работы!

View File

@@ -110,6 +110,9 @@ More details about the provider's building process: https://learn.hashicorp.com/
## Examples and Samples
- Examples: https://github.com/rudecs/terraform-provider-decort/wiki
- Samples: in repository `samples`
- Samples: see in repository `samples`
Terraform schemas in:
- See in repository `docs`
Good work!

View File

@@ -36,7 +36,7 @@ import (
var Timeout30s = time.Second * 30
var Timeout60s = time.Second * 60
var Timeout180s = time.Second * 180
var Timeout10m = time.Minute * 10
var Timeout20m = time.Minute * 20
//
// structures related to /cloudapi/rg/list API
@@ -583,12 +583,16 @@ const VinsDeleteAPI = "/restmachine/cloudapi/vins/delete"
//K8sNodeRecord represents a worker/master group
type K8sNodeRecord struct {
ID int `json:"id"`
Name string `json:"name"`
Disk int `json:"disk"`
Cpu int `json:"cpu"`
Num int `json:"num"`
Ram int `json:"ram"`
ID int `json:"id"`
Name string `json:"name"`
Disk int `json:"disk"`
Cpu int `json:"cpu"`
Num int `json:"num"`
Ram int `json:"ram"`
DetailedInfo []struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"detailedInfo"`
}
//K8sRecord represents k8s instance
@@ -614,6 +618,9 @@ const K8sDeleteAPI = "/restmachine/cloudapi/k8s/delete"
const K8sWgCreateAPI = "/restmachine/cloudapi/k8s/workersGroupAdd"
const K8sWgDeleteAPI = "/restmachine/cloudapi/k8s/workersGroupDelete"
const K8sWorkerAddAPI = "/restmachine/cloudapi/k8s/workerAdd"
const K8sWorkerDeleteAPI = "/restmachine/cloudapi/k8s/deleteWorkerFromGroup"
const K8sGetConfigAPI = "/restmachine/cloudapi/k8s/getConfig"
//Blasphemous workaround for parsing Result value

View File

@@ -58,7 +58,6 @@ func parseNode(nodeList []interface{}) K8sNodeRecord {
func nodeToResource(node K8sNodeRecord) []interface{} {
mp := make(map[string]interface{})
mp["id"] = node.ID
mp["num"] = node.Num
mp["cpu"] = node.Cpu
mp["ram"] = node.Ram
@@ -72,7 +71,6 @@ func nodeK8sSubresourceSchemaMake() map[string]*schema.Schema {
"num": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "Number of nodes to create.",
},

View File

@@ -165,13 +165,46 @@ func resourceK8sUpdate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sUpdate: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("name", d.Get("name").(string))
_, err := controller.decortAPICall("POST", K8sUpdateAPI, urlValues)
if err != nil {
return err
if d.HasChange("name") {
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("name", d.Get("name").(string))
_, err := controller.decortAPICall("POST", K8sUpdateAPI, urlValues)
if err != nil {
return err
}
}
if d.HasChange("workers") {
k8s, err := utilityK8sCheckPresence(d, m)
if err != nil {
return err
}
wg := k8s.Groups.Workers[0]
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("workersGroupId", strconv.Itoa(wg.ID))
newWorkers := parseNode(d.Get("workers").([]interface{}))
if newWorkers.Num > wg.Num {
urlValues.Add("num", strconv.Itoa(newWorkers.Num-wg.Num))
_, err := controller.decortAPICall("POST", K8sWorkerAddAPI, urlValues)
if err != nil {
return err
}
} else {
for i := wg.Num - 1; i >= newWorkers.Num; i-- {
urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID))
_, err := controller.decortAPICall("POST", K8sWorkerDeleteAPI, urlValues)
if err != nil {
return err
}
}
}
}
return nil
@@ -255,7 +288,6 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
"workers": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: nodeK8sSubresourceSchemaMake(),
@@ -314,9 +346,9 @@ func resourceK8s() *schema.Resource {
},
Timeouts: &schema.ResourceTimeout{
Create: &Timeout10m,
Create: &Timeout20m,
Read: &Timeout30s,
Update: &Timeout60s,
Update: &Timeout20m,
Delete: &Timeout60s,
Default: &Timeout60s,
},

View File

@@ -101,6 +101,41 @@ func resourceK8sWgRead(d *schema.ResourceData, m interface{}) error {
return nil
}
func resourceK8sWgUpdate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sWgUpdate: called with k8s id %d", d.Get("k8s_id").(int))
controller := m.(*ControllerCfg)
wg, err := utilityK8sWgCheckPresence(d, m)
if err != nil {
return nil
}
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("workersGroupId", d.Id())
newNum := d.Get("num").(int)
if newNum > wg.Num {
urlValues.Add("num", strconv.Itoa(newNum-wg.Num))
_, err := controller.decortAPICall("POST", K8sWorkerAddAPI, urlValues)
if err != nil {
return err
}
} else {
for i := wg.Num - 1; i >= newNum; i-- {
urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID))
_, err := controller.decortAPICall("POST", K8sWorkerDeleteAPI, urlValues)
if err != nil {
return err
}
}
}
return nil
}
func resourceK8sWgDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sWgDelete: called with k8s id %d", d.Get("k8s_id").(int))
@@ -158,7 +193,6 @@ func resourceK8sWgSchemaMake() map[string]*schema.Schema {
"num": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Default: 1,
Description: "Number of worker nodes to create.",
},
@@ -195,6 +229,7 @@ func resourceK8sWg() *schema.Resource {
Create: resourceK8sWgCreate,
Read: resourceK8sWgRead,
Update: resourceK8sWgUpdate,
Delete: resourceK8sWgDelete,
Exists: resourceK8sWgExists,
@@ -203,8 +238,9 @@ func resourceK8sWg() *schema.Resource {
},
Timeouts: &schema.ResourceTimeout{
Create: &Timeout10m,
Create: &Timeout20m,
Read: &Timeout30s,
Update: &Timeout20m,
Delete: &Timeout60s,
Default: &Timeout60s,
},

View File

@@ -38,5 +38,6 @@ Optional:
- **default** (String)
- **delete** (String)
- **read** (String)
- **update** (String)

View File

@@ -13,6 +13,8 @@
- virtual_image
- cdrom_image
- delete_images
- k8s
- k8s_wg
## Как пользоваться примерами
1. Установить terraform

View File

@@ -0,0 +1,122 @@
/*
Пример использования
Ресурсов k8s cluster
Ресурсы позволяет:
1. Создавать
2. Редактировать
3. Удалять
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
source = "terraform.local/local/decort"
version = "1.0.0"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
oauth2_url = "https://sso.digitalenergy.online"
controller_url = "https://mr4.digitalenergy.online"
app_id = ""
app_secret = ""
}
resource "decort_k8s" "cluster" {
#имя кластера
#обязательный параметр
#при изменении - обновдяет имя кластера
#тип - строка
name = "tftest"
#id resource group
#обязательный параметр
#тип - число
rg_id = 776
#id catalogue item
#обязательный параметр
#тип - число
k8sci_id = 9
#имя для первой worker group, созданной в кластере
#обязательный параметр
#тип - строка
wg_name = "workers"
#настройка мастер node или nodes
#опциональный параметр
#максимальное кол-во элементов - 1
#тип - список нод
masters {
#кол-во node
#обязательный параметр
#тип - число
num = 1
#кол-во cpu
#обязательный параметр
#тип - число
cpu = 2
#кол-во RAM в Мбайтах
#обязательный параметр
#тип - число
ram = 2048
#размер диска в Гбайтах
#обязательный параметр
#тип - число
disk = 10
}
#настройка worker node или nodes
#опциональный параметр
#максимальное кол-во элементов - 1
#тип - список нод
workers {
#кол-во node
#обязательный параметр
#тип - число
num = 1
#кол-во cpu
#обязательный параметр
#тип - число
cpu = 2
#кол-во RAM в Мбайтах
#обязательный параметр
#тип - число
ram = 2048
#размер диска в Гбайтах
#обязательный параметр
#тип - число
disk = 10
}
}
output "test_cluster" {
value = decort_k8s.cluster
}
/*
output "kubeconfig"{
value = decort_k8s.cluster.kubeconfig
}
*/

View File

@@ -0,0 +1,76 @@
/*
Пример использования
Ресурсов worker group
Ресурсы позволяет:
1. Создавать
2. Редактировать
3. Удалять
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
source = "terraform.local/local/decort"
version = "1.0.0"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
oauth2_url = "https://sso.digitalenergy.online"
controller_url = "https://mr4.digitalenergy.online"
app_id = ""
app_secret = ""
}
resource "decort_k8s_wg" "wg" {
#id экземпляра k8s
#обязательный параметр
#тип - число
k8s_id = 1234 //это значение должно быть и результат вызова decort_k8s.cluster.id
#имя worker group
#обязательный параметр
#тип - строка
name = "workers-2"
#количество worker node для создания
#опциональный параметр
#тип - число
#по - умолчанию - 1
num = 2
#количество cpu для 1 worker node
#опциональный параметр
#тип - число
#по - умолчанию - 1
cpu = 1
#количество RAM для одной worker node в Мбайтах
#опциональный параметр
#тип - число
#по-умолчанию - 1024
ram = 1024
#размер загрузочного диска для worker node, в Гбайтах
#опциональный параметр
#тип - число
#по - умолчанию - 0
#если установлен параметр 0, то размер диска будет равен размеру образа
disk = 10
}
output "test_wg" {
value = decort_k8s_wg.wg
}