mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-30 10:33:46 +00:00
* refactoring existing cluster / firewall API for better composition * add basic security groups API fix linter errors * add rules API * fix after renaming resourceVirtualEnvironmentClusterIPSet * fix linter errors * make linter happy * even more refactoring * tidy up datasources * in refactoring spree * update examples * fix firewall resource/datasource & client error handling * add ipset(s) datasource * update docs * add security group resource with rules * docs * fix security group update, TODO: rule update * fix after rebase * add rule update, extract common rule schema, refactor group * fix linter errors * bump linter for ci * make alias and ipset reusable * make security group reusable * refactor datasources * add security group datasources * fix linter errors * update docs TODO: documentation for group datasources * add sg docs, update doc index * minor cleanup * fix examples & tests * stub for firewall-level options and rules * extract firewall interface * add firewall options and rules on the cluster level TODO: issues with rule list management * refactor all resources format AGAIN, now more flat, without complex subresources * sort out hierarchy of APIs and remove duplication in API wrappers * bring back security group * finally, working rules * restore cluster firewall option * add containers support * add options * move rules back under security group, update docs * fix vm_id / container_id attrs * add examples * cleanup * more cleanup Release-As: 0.17.0-rc1
275 lines
5.8 KiB
Go
275 lines
5.8 KiB
Go
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
package proxmox
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// CloneContainer clones a container.
|
|
func (c *VirtualEnvironmentClient) CloneContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
d *VirtualEnvironmentContainerCloneRequestBody,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodPost,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/clone", url.PathEscape(nodeName), vmID),
|
|
d,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// CreateContainer creates a container.
|
|
func (c *VirtualEnvironmentClient) CreateContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
d *VirtualEnvironmentContainerCreateRequestBody,
|
|
) error {
|
|
return c.DoRequest(ctx, http.MethodPost, fmt.Sprintf("nodes/%s/lxc", url.PathEscape(nodeName)), d, nil)
|
|
}
|
|
|
|
// DeleteContainer deletes a container.
|
|
func (c *VirtualEnvironmentClient) DeleteContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodDelete,
|
|
fmt.Sprintf("nodes/%s/lxc/%d", url.PathEscape(nodeName), vmID),
|
|
nil,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// GetContainer retrieves a container.
|
|
func (c *VirtualEnvironmentClient) GetContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
) (*VirtualEnvironmentContainerGetResponseData, error) {
|
|
resBody := &VirtualEnvironmentContainerGetResponseBody{}
|
|
err := c.DoRequest(
|
|
ctx,
|
|
http.MethodGet,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/config", url.PathEscape(nodeName), vmID),
|
|
nil,
|
|
resBody,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resBody.Data == nil {
|
|
return nil, errors.New("the server did not include a data object in the response")
|
|
}
|
|
|
|
return resBody.Data, nil
|
|
}
|
|
|
|
// GetContainerStatus retrieves the status for a container.
|
|
func (c *VirtualEnvironmentClient) GetContainerStatus(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
) (*VirtualEnvironmentContainerGetStatusResponseData, error) {
|
|
resBody := &VirtualEnvironmentContainerGetStatusResponseBody{}
|
|
err := c.DoRequest(
|
|
ctx,
|
|
http.MethodGet,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/status/current", url.PathEscape(nodeName), vmID),
|
|
nil,
|
|
resBody,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resBody.Data == nil {
|
|
return nil, errors.New("the server did not include a data object in the response")
|
|
}
|
|
|
|
return resBody.Data, nil
|
|
}
|
|
|
|
// RebootContainer reboots a container.
|
|
func (c *VirtualEnvironmentClient) RebootContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
d *VirtualEnvironmentContainerRebootRequestBody,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodPost,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/status/reboot", url.PathEscape(nodeName), vmID),
|
|
d,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// ShutdownContainer shuts down a container.
|
|
func (c *VirtualEnvironmentClient) ShutdownContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
d *VirtualEnvironmentContainerShutdownRequestBody,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodPost,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/status/shutdown", url.PathEscape(nodeName), vmID),
|
|
d,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// StartContainer starts a container.
|
|
func (c *VirtualEnvironmentClient) StartContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodPost,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/status/start", url.PathEscape(nodeName), vmID),
|
|
nil,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// StopContainer stops a container immediately.
|
|
func (c *VirtualEnvironmentClient) StopContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodPost,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/status/stop", url.PathEscape(nodeName), vmID),
|
|
nil,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// UpdateContainer updates a container.
|
|
func (c *VirtualEnvironmentClient) UpdateContainer(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
d *VirtualEnvironmentContainerUpdateRequestBody,
|
|
) error {
|
|
return c.DoRequest(
|
|
ctx,
|
|
http.MethodPut,
|
|
fmt.Sprintf("nodes/%s/lxc/%d/config", url.PathEscape(nodeName), vmID),
|
|
d,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// WaitForContainerState waits for a container to reach a specific state.
|
|
//
|
|
//nolint:dupl
|
|
func (c *VirtualEnvironmentClient) WaitForContainerState(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
state string,
|
|
timeout int,
|
|
delay int,
|
|
) error {
|
|
state = strings.ToLower(state)
|
|
|
|
timeDelay := int64(delay)
|
|
timeMax := float64(timeout)
|
|
timeStart := time.Now()
|
|
timeElapsed := timeStart.Sub(timeStart)
|
|
|
|
for timeElapsed.Seconds() < timeMax {
|
|
if int64(timeElapsed.Seconds())%timeDelay == 0 {
|
|
data, err := c.GetContainerStatus(ctx, nodeName, vmID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if data.Status == state {
|
|
return nil
|
|
}
|
|
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
timeElapsed = time.Since(timeStart)
|
|
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf(
|
|
"timeout while waiting for container \"%d\" to enter the state \"%s\"",
|
|
vmID,
|
|
state,
|
|
)
|
|
}
|
|
|
|
// WaitForContainerLock waits for a container lock to be released.
|
|
//
|
|
//nolint:dupl
|
|
func (c *VirtualEnvironmentClient) WaitForContainerLock(
|
|
ctx context.Context,
|
|
nodeName string,
|
|
vmID int,
|
|
timeout int,
|
|
delay int,
|
|
ignoreErrorResponse bool,
|
|
) error {
|
|
timeDelay := int64(delay)
|
|
timeMax := float64(timeout)
|
|
timeStart := time.Now()
|
|
timeElapsed := timeStart.Sub(timeStart)
|
|
|
|
for timeElapsed.Seconds() < timeMax {
|
|
if int64(timeElapsed.Seconds())%timeDelay == 0 {
|
|
data, err := c.GetContainerStatus(ctx, nodeName, vmID)
|
|
|
|
if err != nil {
|
|
if !ignoreErrorResponse {
|
|
return err
|
|
}
|
|
} else if data.Lock == nil || *data.Lock == "" {
|
|
return nil
|
|
}
|
|
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
timeElapsed = time.Since(timeStart)
|
|
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("timeout while waiting for container \"%d\" to become unlocked", vmID)
|
|
}
|