Skip to content

Commit

Permalink
feat(node): implement initial support to manage APT repositories (#1325)
Browse files Browse the repository at this point in the history
* feat(nodes): Initial support to manage APT repositories

> Summary

This commit implements initial support for managing APT repositories
which is (currently) limited to…

- …adding "standard" repositories to allow to configure it.
- toggling the activation status (enabled/disabled) of any configured
  repository.

+ !WARNING!
+ Note that deleting or modifying a repository in any other way is
+ (sadly) not possible (yet?)!
+ The limited functionality is due to the (current) capabilities of
+ the Proxmox VE APT repository API [1] itself.

>> Why are there two resources for one API entity?

Even though an APT repository should be seen as a single API entity, it
was required to implement standard repositories as dedicated
`proxmox_virtual_environment_apt_standard_repository`. This is because
standard repositories must be configured (added) first to the default
source list files because their activation status can be toggled. This
is handled by the HTTP `PUT` request, but the modifying request is
`POST` which would require two calls within the same Terraform execution
cycle. I tried to implement it in a single resource and it worked out
mostly after some handling some edges cases, but in the end there were
still too many situations an edge cases where it might break due to
Terraform state drifts between states. In the end the dedicated
resources are way cleaner and easier to use without no complexity and
conditional attribute juggling for practitioners.

>> Other "specialties"

Unfortunately the Proxmox VE API responses to HTTP `GET` requests with
four larger arrays which are, more or less, kind of connected to each
other, but they also somehow stand on their own. This means that there
is a `files` array that contains the `repositories` again which again
contains all repositories with their metadata of every source file. On
the other hand available standard repositories are listed in the
`standard-repos` array, but their activation status is only stored when
they have already been added through a `PUT` request. The `infos` array
is more less useless.

So in order to get the required data and store them in the state the
`importFromAPI` methods of the models must loop through all the
deep-nested arrays and act based on specific attributes like a matching
file path, comparing it to the activation status and so on.

In the end the implementation is really stable after testing it with all
possible conditions and state combinations.

@bpg if you'd like me to create a small data logic flow chart to make it
easier to understand some parts of the code let me know. I can make my
local notes "shareable" which I created to not loose track of the logic.

>> What is the way to manage the activation status of a "standard" repository?

Because the two resources are modular and scoped they can be simply
combined to manage an APT "standard" repository, e.g. toggling its
activation status. The following examples are also included in the
documentations.

```hcl
// This resource ensure that the "no-subscription" standard repository
// is added to the source list.
// It represents the `PUT` API request.
resource "proxmox_virtual_environment_apt_standard_repository" "example" {
  handle = "no-subscription"
  node   = "pve"
}

// This resource allows to actually modify the activation status of the
// standard repository as it represents the `POST`.
// Using the values from the dedicated standard repository resource
// makes sure that Terraform correctly resolves dependency order.
resource "proxmox_virtual_environment_apt_repository" "example" {
  enabled   = true
  file_path = proxmox_virtual_environment_apt_standard_repository.example.file_path
  index     = proxmox_virtual_environment_apt_standard_repository.example.index
  node      = proxmox_virtual_environment_apt_standard_repository.example.node
}
```

[1]: https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/apt/repositories

---------

Signed-off-by: Sven Greb <development@svengreb.de>
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
  • Loading branch information
svengreb and bpg authored Jul 5, 2024
1 parent cf1142e commit 357f7c7
Show file tree
Hide file tree
Showing 32 changed files with 2,813 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ linters-settings:
statements: 60
errcheck:
check-blank: true
wrapcheck:
ignorePackageGlobs:
# Prevent false-positive matches for errors from packages of the own module.
- github.com/bpg/terraform-provider-proxmox/*
linters:
enable-all: true
disable:
Expand Down
46 changes: 46 additions & 0 deletions docs/data-sources/virtual_environment_apt_repository.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
layout: page
title: proxmox_virtual_environment_apt_repository
parent: Data Sources
subcategory: Virtual Environment
description: |-
Retrieves an APT repository from a Proxmox VE cluster.
---

# Data Source: proxmox_virtual_environment_apt_repository

Retrieves an APT repository from a Proxmox VE cluster.

## Example Usage

```terraform
data "proxmox_virtual_environment_apt_repository" "example" {
file_path = "/etc/apt/sources.list"
index = 0
node = "pve"
}
output "proxmox_virtual_environment_apt_repository" {
value = data.proxmox_virtual_environment_apt_repository.example
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `file_path` (String) The absolute path of the source list file that contains this repository.
- `index` (Number) The index within the defining source list file.
- `node` (String) The name of the target Proxmox VE node.

### Read-Only

- `comment` (String) The associated comment.
- `components` (List of String) The list of components.
- `enabled` (Boolean) Indicates the activation status.
- `file_type` (String) The format of the defining source list file.
- `id` (String) The unique identifier of this APT repository data source.
- `package_types` (List of String) The list of package types.
- `suites` (List of String) The list of package distributions.
- `uris` (List of String) The list of repository URIs.
42 changes: 42 additions & 0 deletions docs/data-sources/virtual_environment_apt_standard_repository.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
layout: page
title: proxmox_virtual_environment_apt_standard_repository
parent: Data Sources
subcategory: Virtual Environment
description: |-
Retrieves an APT standard repository from a Proxmox VE cluster.
---

# Data Source: proxmox_virtual_environment_apt_standard_repository

Retrieves an APT standard repository from a Proxmox VE cluster.

## Example Usage

```terraform
data "proxmox_virtual_environment_apt_standard_repository" "example" {
handle = "no-subscription"
node = "pve"
}
output "proxmox_virtual_environment_apt_standard_repository" {
value = data.proxmox_virtual_environment_apt_standard_repository.example
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `handle` (String) The handle of the APT standard repository.
- `node` (String) The name of the target Proxmox VE node.

### Read-Only

- `description` (String) The description of the APT standard repository.
- `file_path` (String) The absolute path of the source list file that contains this standard repository.
- `id` (String) The unique identifier of this APT standard repository data source.
- `index` (Number) The index within the defining source list file.
- `name` (String) The name of the APT standard repository.
- `status` (Number) Indicates the activation status.
57 changes: 57 additions & 0 deletions docs/resources/virtual_environment_apt_repository.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
layout: page
title: proxmox_virtual_environment_apt_repository
parent: Resources
subcategory: Virtual Environment
description: |-
Manages an APT repository of a Proxmox VE node.
---

# Resource: proxmox_virtual_environment_apt_repository

Manages an APT repository of a Proxmox VE node.

## Example Usage

```terraform
resource "proxmox_virtual_environment_apt_repository" "example" {
enabled = true
file_path = "/etc/apt/sources.list"
index = 0
node = "pve"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `file_path` (String) The absolute path of the source list file that contains this repository.
- `index` (Number) The index within the defining source list file.
- `node` (String) The name of the target Proxmox VE node.

### Optional

- `enabled` (Boolean) Indicates the activation status.

### Read-Only

- `comment` (String) The associated comment.
- `components` (List of String) The list of components.
- `file_type` (String) The format of the defining source list file.
- `id` (String) The unique identifier of this APT repository resource.
- `package_types` (List of String) The list of package types.
- `suites` (List of String) The list of package distributions.
- `uris` (List of String) The list of repository URIs.

## Import

Import is supported using the following syntax:

```shell
#!/usr/bin/env sh
# An APT repository can be imported using a comma-separated list consisting of the name of the Proxmox VE node,
# the absolute source list file path, and the index in the exact same order, e.g.:
terraform import proxmox_virtual_environment_apt_repository.example pve,/etc/apt/sources.list,0
```
56 changes: 56 additions & 0 deletions docs/resources/virtual_environment_apt_standard_repository.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
layout: page
title: proxmox_virtual_environment_apt_standard_repository
parent: Resources
subcategory: Virtual Environment
description: |-
Manages an APT standard repository of a Proxmox VE node.
---

# Resource: proxmox_virtual_environment_apt_standard_repository

Manages an APT standard repository of a Proxmox VE node.

## Example Usage

```terraform
resource "proxmox_virtual_environment_apt_standard_repository" "example" {
handle = "no-subscription"
node = "pve"
}
resource "proxmox_virtual_environment_apt_repository" "example" {
enabled = true
file_path = proxmox_virtual_environment_apt_standard_repository.example.file_path
index = proxmox_virtual_environment_apt_standard_repository.example.index
node = proxmox_virtual_environment_apt_standard_repository.example.node
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `handle` (String) The handle of the APT standard repository. Must be `ceph-quincy-enterprise` | `ceph-quincy-no-subscription` | `ceph-quincy-test` | `ceph-reef-enterprise` | `ceph-reef-no-subscription` | `ceph-reef-test` | `enterprise` | `no-subscription` | `test`.
- `node` (String) The name of the target Proxmox VE node.

### Read-Only

- `description` (String) The description of the APT standard repository.
- `file_path` (String) The absolute path of the source list file that contains this standard repository.
- `id` (String) The unique identifier of this APT standard repository resource.
- `index` (Number) The index within the defining source list file.
- `name` (String) The name of the APT standard repository.
- `status` (Number) Indicates the activation status.

## Import

Import is supported using the following syntax:

```shell
#!/usr/bin/env sh
# An APT standard repository can be imported using a comma-separated list consisting of the name of the Proxmox VE node,
# and the standard repository handle in the exact same order, e.g.:
terraform import proxmox_virtual_environment_apt_standard_repository.example pve,no-subscription
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
data "proxmox_virtual_environment_apt_repository" "example" {
file_path = "/etc/apt/sources.list"
index = 0
node = "pve"
}

output "proxmox_virtual_environment_apt_repository" {
value = data.proxmox_virtual_environment_apt_repository.example
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
data "proxmox_virtual_environment_apt_standard_repository" "example" {
handle = "no-subscription"
node = "pve"
}

output "proxmox_virtual_environment_apt_standard_repository" {
value = data.proxmox_virtual_environment_apt_standard_repository.example
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
# An APT repository can be imported using a comma-separated list consisting of the name of the Proxmox VE node,
# the absolute source list file path, and the index in the exact same order, e.g.:
terraform import proxmox_virtual_environment_apt_repository.example pve,/etc/apt/sources.list,0
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resource "proxmox_virtual_environment_apt_repository" "example" {
enabled = true
file_path = "/etc/apt/sources.list"
index = 0
node = "pve"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
# An APT standard repository can be imported using a comma-separated list consisting of the name of the Proxmox VE node,
# and the standard repository handle in the exact same order, e.g.:
terraform import proxmox_virtual_environment_apt_standard_repository.example pve,no-subscription
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
resource "proxmox_virtual_environment_apt_standard_repository" "example" {
handle = "no-subscription"
node = "pve"
}

resource "proxmox_virtual_environment_apt_repository" "example" {
enabled = true
file_path = proxmox_virtual_environment_apt_standard_repository.example.file_path
index = proxmox_virtual_environment_apt_standard_repository.example.index
node = proxmox_virtual_environment_apt_standard_repository.example.node
}
Loading

0 comments on commit 357f7c7

Please sign in to comment.