Skip to content

Commit 9ff5fe7

Browse files
committed
Added vault-cli feature
1 parent b0b3184 commit 9ff5fe7

File tree

12 files changed

+279
-0
lines changed

12 files changed

+279
-0
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
"git-lfs",
2020
"go",
2121
"node",
22+
"vault-cli",
2223
"zig"
2324
]
2425
runs-on: ubuntu-latest

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Below is a list with included features, click on the link for more details.
1919
| [git-lfs](./features/src/git-lfs/README.md) | A feature which installs Git LFS. |
2020
| [go](./features/src/go/README.md) | A feature which installs Go. |
2121
| [node](./features/src/node/README.md) | A package which installs Node.js. |
22+
| [vault-cli](./features/src/vault-cli/README.md) | A feature which installs the Vault CLI. |
2223
| [zig](./features/src/zig/README.md) | A feature which installs Zig. |
2324

2425
## Usage

build/build.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var featureList = []string{
2424
"git-lfs",
2525
"go",
2626
"node",
27+
"vault-cli",
2728
"zig",
2829
}
2930

@@ -93,6 +94,17 @@ func init() {
9394
return publishFeature("node")
9495
})
9596

97+
////////// vault-cli
98+
gotaskr.Task("Feature:vault-cli:Package", func() error {
99+
return packageFeature("vault-cli")
100+
})
101+
gotaskr.Task("Feature:vault-cli:Test", func() error {
102+
return testFeature("vault-cli")
103+
})
104+
gotaskr.Task("Feature:vault-cli:Publish", func() error {
105+
return publishFeature("vault-cli")
106+
})
107+
96108
////////// zig
97109
gotaskr.Task("Feature:zig:Package", func() error {
98110
return packageFeature("zig")

features/src/vault-cli/NOTES.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## Notes
2+
3+
### System Compatibility
4+
5+
Debian, Ubuntu, Alpine
6+
7+
### Accessed Urls
8+
9+
Needs access to the following URL for downloading and resolving:
10+
* https://releases.hashicorp.com

features/src/vault-cli/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Vault CLI (vault-cli)
2+
3+
A feature which installs the Vault CLI.
4+
5+
## Example Usage
6+
7+
```json
8+
"features": {
9+
"ghcr.io/postfinance/devcontainer-features/vault-cli:0.1.0": {
10+
"version": "latest",
11+
"versionResolve": false,
12+
"downloadUrlBase": "",
13+
"downloadUrlPath": "",
14+
"versionsUrl": ""
15+
}
16+
}
17+
```
18+
19+
## Options
20+
21+
| Option | Description | Type | Default Value | Proposals |
22+
|-----|-----|-----|-----|-----|
23+
| version | The version of Vault CLI to install. | string | latest | latest, 1.18.2, 1 |
24+
| versionResolve | Whether to resolve the version automatically. | boolean | false | true, false |
25+
| downloadUrlBase | The download URL to use for Vault CLI binaries. | string | <empty> | https://mycompany.com/artifactory/hashicorp-releases-generic-remote |
26+
| downloadUrlPath | The download URL path to use for Vault CLI binaries. | string | <empty> | |
27+
| versionsUrl | The URL to fetch the available Vault CLI versions from. | string | <empty> | |
28+
29+
## Notes
30+
31+
### System Compatibility
32+
33+
Debian, Ubuntu, Alpine
34+
35+
### Accessed Urls
36+
37+
Needs access to the following URL for downloading and resolving:
38+
* https://releases.hashicorp.com
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"id": "vault-cli",
3+
"version": "0.1.0",
4+
"name": "Vault CLI",
5+
"description": "A feature which installs the Vault CLI.",
6+
"options": {
7+
"version": {
8+
"type": "string",
9+
"proposals": [
10+
"latest",
11+
"1.18.2",
12+
"1"
13+
],
14+
"default": "latest",
15+
"description": "The version of Vault CLI to install."
16+
},
17+
"versionResolve":{
18+
"type":"boolean",
19+
"default": false,
20+
"description": "Whether to resolve the version automatically."
21+
},
22+
"downloadUrlBase": {
23+
"type": "string",
24+
"default": "",
25+
"proposals": [
26+
"https://mycompany.com/artifactory/hashicorp-releases-generic-remote"
27+
],
28+
"description": "The download URL to use for Vault CLI binaries."
29+
},
30+
"downloadUrlPath": {
31+
"type": "string",
32+
"default": "",
33+
"description": "The download URL path to use for Vault CLI binaries."
34+
},
35+
"versionsUrl": {
36+
"type": "string",
37+
"default": "",
38+
"description": "The URL to fetch the available Vault CLI versions from."
39+
}
40+
}
41+
}

features/src/vault-cli/install.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
case $(uname -m | tr '[:upper:]' '[:lower:]') in
2+
x86_64*) ARCH=amd64 ;;
3+
arm*|aarch64*) ARCH=arm64 ;;
4+
*) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;;
5+
esac
6+
7+
"./installer_$ARCH" \
8+
-version="${VERSION:-"latest"}" \
9+
-versionResolve="${VERSIONRESOLVE:-false}" \
10+
-downloadUrlBase="${DOWNLOADURLBASE:-""}" \
11+
-downloadUrlPath="${DOWNLOADURLPATH:-""}" \
12+
-versionsUrl="${VERSIONSURL:-""}"
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package main
2+
3+
import (
4+
"builder/installer"
5+
"encoding/json"
6+
"flag"
7+
"fmt"
8+
"os"
9+
"os/exec"
10+
"regexp"
11+
12+
"github.com/roemer/gotaskr/execr"
13+
"github.com/roemer/gover"
14+
)
15+
16+
//////////
17+
// Configuration
18+
//////////
19+
20+
var versionRegexp *regexp.Regexp = regexp.MustCompile(`(?m:)^(\d+)\.(\d+)\.(\d+)$`)
21+
22+
//////////
23+
// Main
24+
//////////
25+
26+
func main() {
27+
if err := runMain(); err != nil {
28+
fmt.Printf("Error: %v\n", err)
29+
os.Exit(1)
30+
}
31+
}
32+
33+
func runMain() error {
34+
// Handle the flags
35+
version := flag.String("version", "latest", "")
36+
versionResolve := flag.Bool("versionResolve", false, "")
37+
downloadUrlBase := flag.String("downloadUrlBase", "", "")
38+
downloadUrlPath := flag.String("downloadUrlPath", "", "")
39+
versionsUrl := flag.String("versionsUrl", "", "")
40+
flag.Parse()
41+
42+
// Load settings from an external file
43+
if err := installer.LoadOverrides(); err != nil {
44+
return err
45+
}
46+
47+
installer.HandleOverride(downloadUrlBase, "https://releases.hashicorp.com", "vault-cli-download-url-base")
48+
installer.HandleOverride(downloadUrlPath, "/vault", "vault-cli-download-url-path")
49+
installer.HandleOverride(versionsUrl, "https://releases.hashicorp.com/vault/index.json", "vault-cli-versions-url")
50+
51+
// Create and process the feature
52+
feature := installer.NewFeature("Vault CLI", true,
53+
&vaultCliComponent{
54+
ComponentBase: installer.NewComponentBase("Vault CLI", *version, *versionResolve),
55+
DownloadUrlBase: *downloadUrlBase,
56+
DownloadUrlPath: *downloadUrlPath,
57+
VersionsUrl: *versionsUrl,
58+
})
59+
return feature.Process()
60+
}
61+
62+
//////////
63+
// Implementation
64+
//////////
65+
66+
type vaultCliComponent struct {
67+
*installer.ComponentBase
68+
DownloadUrlBase string
69+
DownloadUrlPath string
70+
VersionsUrl string
71+
}
72+
73+
func (c *vaultCliComponent) GetAllVersions() ([]*gover.Version, error) {
74+
versionFileContent, err := installer.Tools.Download.AsBytes(c.VersionsUrl)
75+
if err != nil {
76+
return nil, err
77+
}
78+
var jsonData map[string]any
79+
if err := json.Unmarshal(versionFileContent, &jsonData); err != nil {
80+
return nil, err
81+
}
82+
versionsObj, ok := jsonData["versions"].(map[string]any)
83+
if !ok {
84+
return nil, fmt.Errorf("versions not found in vault index json")
85+
}
86+
versions := []*gover.Version{}
87+
for versionString := range versionsObj {
88+
version, err := gover.ParseVersionFromRegex(versionString, versionRegexp)
89+
if err != nil {
90+
continue // skip invalid
91+
}
92+
versions = append(versions, version)
93+
}
94+
return versions, nil
95+
}
96+
97+
func (c *vaultCliComponent) InstallVersion(version *gover.Version) error {
98+
archPart, err := installer.Tools.System.MapArchitecture(map[string]string{
99+
installer.AMD64: "amd64",
100+
installer.ARM64: "arm64",
101+
})
102+
if err != nil {
103+
return err
104+
}
105+
fileName := fmt.Sprintf("vault_%s_linux_%s.zip", version.Raw, archPart)
106+
downloadUrl, err := installer.Tools.Http.BuildUrl(c.DownloadUrlBase, c.DownloadUrlPath, version.Raw, fileName)
107+
if err != nil {
108+
return err
109+
}
110+
if err := installer.Tools.Download.ToFile(downloadUrl, fileName, "Vault CLI"); err != nil {
111+
return err
112+
}
113+
// Extract it
114+
if err := installer.Tools.Compression.ExtractZip(fileName, "vault", false); err != nil {
115+
return err
116+
}
117+
// Install
118+
configureCmd := exec.Command("install", "-m", "0755", "vault/vault", "/usr/local/bin/vault")
119+
if err := execr.RunCommand(true, configureCmd); err != nil {
120+
return err
121+
}
122+
// Cleanup
123+
if err := os.Remove(fileName); err != nil {
124+
return err
125+
}
126+
if err := os.RemoveAll("vault"); err != nil {
127+
return err
128+
}
129+
return nil
130+
}

features/test/vault-cli/install.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
set -e
3+
4+
[[ -f "$(dirname "$0")/../functions.sh" ]] && source "$(dirname "$0")/../functions.sh"
5+
[[ -f "$(dirname "$0")/functions.sh" ]] && source "$(dirname "$0")/functions.sh"
6+
7+
check_command_exists vault
8+
check_version "$(vault -v)" "1.18.2"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"install": {
3+
"build": {
4+
"dockerfile": "Dockerfile",
5+
"options": [
6+
"--add-host=host.docker.internal:host-gateway"
7+
]
8+
},
9+
"features": {
10+
"./vault-cli": {
11+
"version": "1.18.2"
12+
}
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)