feat(dev): add Docker development CLI (#6495)
This commit is contained in:
1 parent
d58a47b776
commit
018f84f80d
27 files changed
+4048
-7
No files matched your search
@@ -0,0 +1,125 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestContainerHostPort(t *testing.T) {
|
||||
c := Container{Ports: "0.0.0.0:7576->7575/tcp, [::]:7576->7575/tcp"}
|
||||
if got := c.HostPort(); got != "7576" {
|
||||
t.Fatalf("HostPort() = %q, want 7576", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsPortConflict(t *testing.T) {
|
||||
for _, message := range []string{
|
||||
"Bind for 0.0.0.0:7575 failed: port is already allocated",
|
||||
"driver failed programming external connectivity on endpoint",
|
||||
} {
|
||||
if !IsPortConflict(errors.New(message)) {
|
||||
t.Fatalf("expected port conflict for %q", message)
|
||||
}
|
||||
}
|
||||
if IsPortConflict(errors.New("manifest unknown")) {
|
||||
t.Fatal("manifest error classified as port conflict")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseUsedDockerPortsPreservesLineBoundaries(t *testing.T) {
|
||||
ports := parseUsedDockerPorts([]byte("6379/tcp\n0.0.0.0:7575->7575/tcp, [::]:7575->7575/tcp\n0.0.0.0:8000-8002->8000-8002/tcp\n"))
|
||||
for _, port := range []int{7575, 8000, 8001, 8002} {
|
||||
if !ports[port] {
|
||||
t.Fatalf("port %d was not detected", port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindFreePortRejectsOutOfRangeStart(t *testing.T) {
|
||||
if port := FindFreePort(65536); port != 0 {
|
||||
t.Fatalf("port = %d, want 0", port)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDevelopmentEncryptionKeyUsesEnvironmentOverride(t *testing.T) {
|
||||
want := strings.Repeat("a", 64)
|
||||
t.Setenv(developmentEncryptionKeyEnv, want)
|
||||
got, err := developmentEncryptionKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got != want {
|
||||
t.Fatalf("key = %q, want environment value", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPersistedDevelopmentEncryptionKeyIsReused(t *testing.T) {
|
||||
configDir := t.TempDir()
|
||||
first, err := persistedDevelopmentEncryptionKey(configDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
second, err := persistedDevelopmentEncryptionKey(configDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if first != second {
|
||||
t.Fatal("persisted key changed between reads")
|
||||
}
|
||||
decoded, err := hex.DecodeString(first)
|
||||
if err != nil || len(decoded) != 32 {
|
||||
t.Fatalf("generated key is not 32 bytes: %q", first)
|
||||
}
|
||||
info, err := os.Stat(filepath.Join(configDir, "homarr-dev", "secret-encryption-key"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if info.Mode().Perm() != 0o600 {
|
||||
t.Fatalf("key permissions = %o, want 600", info.Mode().Perm())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPersistedDevelopmentEncryptionKeyRejectsInvalidValue(t *testing.T) {
|
||||
configDir := t.TempDir()
|
||||
dir := filepath.Join(configDir, "homarr-dev")
|
||||
if err := os.Mkdir(dir, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "secret-encryption-key"), []byte("invalid\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := persistedDevelopmentEncryptionKey(configDir); err == nil {
|
||||
t.Fatal("expected invalid persisted key to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPersistedDevelopmentEncryptionKeyConcurrentCreation(t *testing.T) {
|
||||
configDir := t.TempDir()
|
||||
type result struct {
|
||||
key string
|
||||
err error
|
||||
}
|
||||
results := make(chan result, 20)
|
||||
for range 20 {
|
||||
go func() {
|
||||
key, err := persistedDevelopmentEncryptionKey(configDir)
|
||||
results <- result{key: key, err: err}
|
||||
}()
|
||||
}
|
||||
var first string
|
||||
for range 20 {
|
||||
result := <-results
|
||||
if result.err != nil {
|
||||
t.Fatal(result.err)
|
||||
}
|
||||
if first == "" {
|
||||
first = result.key
|
||||
} else if result.key != first {
|
||||
t.Fatal("concurrent callers received different keys")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user