Skip to content

Commit

Permalink
Merge pull request #6 from opentofu/standalone
Browse files Browse the repository at this point in the history
Fixing bug with standalone mode
  • Loading branch information
Janos authored Jul 30, 2024
2 parents ded9c57 + 55d2b8e commit 76c6857
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 151 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
*~
tofu
tofu.exe
fake
fake.exe
22 changes: 15 additions & 7 deletions downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,20 @@ func New(opts ...ConfigOpt) (Downloader, error) {
}
}

key, err := crypto.NewKeyFromArmored(cfg.GPGKey)
keyRing, err := createKeyRing(cfg.GPGKey)
if err != nil {
return nil, err
}

return &downloader{
cfg,
tpl,
keyRing,
}, nil
}

func createKeyRing(armoredKey string) (*crypto.KeyRing, error) {
key, err := crypto.NewKeyFromArmored(armoredKey)
if err != nil {
return nil, &InvalidConfigurationError{
Message: "Failed to decode GPG key",
Expand All @@ -61,12 +74,7 @@ func New(opts ...ConfigOpt) (Downloader, error) {
if err != nil {
return nil, &InvalidConfigurationError{Message: "Cannot create keyring", Cause: err}
}

return &downloader{
cfg,
tpl,
keyRing,
}, nil
return keyRing, nil
}

type downloader struct {
Expand Down
26 changes: 9 additions & 17 deletions mockmirror/fake.go → internal/helloworld/fake.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0

package mockmirror
package helloworld

import (
"errors"
Expand All @@ -12,18 +12,14 @@ import (
"testing"
)

func buildFake(t *testing.T) []byte {
_, filename, _, _ := runtime.Caller(1)
fakeDir := path.Join(path.Dir(filename), "fake")
if err := os.MkdirAll(fakeDir, 0755); err != nil {
t.Fatalf("Failed to create fake dir (%v)", err)
}
binaryPath := path.Join(fakeDir, "fake")
if contents, err := os.ReadFile(binaryPath); err == nil {
return contents
// Build creates a hello-world binary for the current platform you can use to test.
func Build(t *testing.T) []byte {
fakeName := "fake"
if runtime.GOOS == "windows" {
fakeName += ".exe"
}

dir := path.Join(os.TempDir(), "fake")
dir := path.Join(os.TempDir(), fakeName)
if err := os.MkdirAll(dir, 0700); err != nil {
t.Fatal(err)
}
Expand All @@ -37,7 +33,7 @@ func buildFake(t *testing.T) []byte {
t.Fatal()
}

cmd := exec.Command("go", "build", "-ldflags", "-s -w", "-o", "fake")
cmd := exec.Command("go", "build", "-ldflags", "-s -w", "-o", fakeName)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = dir
Expand All @@ -50,14 +46,10 @@ func buildFake(t *testing.T) []byte {
}
}

contents, err := os.ReadFile(path.Join(dir, "fake"))
contents, err := os.ReadFile(path.Join(dir, fakeName))
if err != nil {
t.Fatalf("Failed to read compiled fake (%v)", err)
}

if err := os.WriteFile(binaryPath, contents, 0700); err != nil { //nolint:gosec //This needs to be executable.
t.Fatalf("Failed to create fake binary at %s (%v)", binaryPath, err)
}
return contents
}

Expand Down
124 changes: 0 additions & 124 deletions internal/tools/mockmirror-build-fake/main.go

This file was deleted.

17 changes: 17 additions & 0 deletions mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"fmt"
"net/http"
"time"

"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/opentofu/tofudl/branding"
)

// NewMirror creates a new mirror, optionally acting as a pull-through cache when passing a pullThroughDownloader.
Expand All @@ -17,10 +20,20 @@ func NewMirror(config MirrorConfig, storage MirrorStorage, pullThroughDownloader
"no storage and no pull-through downloader passed to NewMirror, cannot create a working mirror",
)
}
if config.GPGKey == "" {
config.GPGKey = branding.DefaultGPGKey
}

keyRing, err := createKeyRing(config.GPGKey)
if err != nil {
return nil, err
}

return &mirror{
storage,
pullThroughDownloader,
config,
keyRing,
}, nil
}

Expand Down Expand Up @@ -57,10 +70,14 @@ type MirrorConfig struct {
// ArtifactCacheTimeout is the time the cached artifacts should be considered valid. A duration of 0 means that
// artifacts should not be cached. A duration of -1 means that artifacts should be cached indefinitely.
ArtifactCacheTimeout time.Duration `json:"artifact_cache_timeout"`

// GPGKey is the ASCII-armored key to verify downloaded artifacts against. This is only needed in standalone mode.
GPGKey string `json:"gpg_key"`
}

type mirror struct {
storage MirrorStorage
pullThroughDownloader Downloader
config MirrorConfig
keyRing *crypto.KeyRing
}
2 changes: 1 addition & 1 deletion mirror_download_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import (
)

func (m *mirror) DownloadVersion(ctx context.Context, version VersionWithArtifacts, platform Platform, architecture Architecture) ([]byte, error) {
return downloadVersion(ctx, version, platform, architecture, m.DownloadArtifact, m.pullThroughDownloader.VerifyArtifact)
return downloadVersion(ctx, version, platform, architecture, m.DownloadArtifact, m.VerifyArtifact)
}
51 changes: 51 additions & 0 deletions mirror_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ package tofudl_test

import (
"context"
"runtime"
"testing"
"time"

"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/opentofu/tofudl"
"github.com/opentofu/tofudl/branding"
"github.com/opentofu/tofudl/internal/helloworld"
"github.com/opentofu/tofudl/mockmirror"
)

Expand Down Expand Up @@ -92,3 +96,50 @@ func TestMirroringE2E(t *testing.T) {
t.Fatal("Empty artifact!")
}
}

func TestMirrorStandalone(t *testing.T) {
binaryContents := helloworld.Build(t)

ctx := context.Background()
key, err := crypto.GenerateKey(branding.ProductName+" Test", "[email protected]", "rsa", 2048)
if err != nil {
t.Fatal(err)
}
pubKey, err := key.GetArmoredPublicKey()
if err != nil {
t.Fatal(err)
}
builder, err := tofudl.NewReleaseBuilder(key)
if err != nil {
t.Fatal(err)
}
if err := builder.PackageBinary(tofudl.PlatformAuto, tofudl.ArchitectureAuto, binaryContents, nil); err != nil {
t.Fatalf("failed to package binary (%v)", err)
}

mirrorStorage, err := tofudl.NewFilesystemStorage(t.TempDir())
if err != nil {
t.Fatalf("failed to set up TofuDL mirror")
}
downloader, err := tofudl.NewMirror(
tofudl.MirrorConfig{
GPGKey: pubKey,
},
mirrorStorage,
nil,
)
if err != nil {
t.Fatal(err)
}
if err := builder.Build(ctx, "1.9.0", downloader); err != nil {
t.Fatal(err)
}
_, err = downloader.Download(ctx)
if err != nil {
t.Fatal(err)
}
// Make sure all file handles are closed.
if runtime.GOOS == "windows" {
runtime.GC()
}
}
5 changes: 4 additions & 1 deletion mirror_verify_artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
package tofudl

func (m *mirror) VerifyArtifact(artifactName string, artifactContents []byte, sumsFileContents []byte, signatureFileContent []byte) error {
return m.pullThroughDownloader.VerifyArtifact(artifactName, artifactContents, sumsFileContents, signatureFileContent)
if m.pullThroughDownloader != nil {
return m.pullThroughDownloader.VerifyArtifact(artifactName, artifactContents, sumsFileContents, signatureFileContent)
}
return verifyArtifact(m.keyRing, artifactName, artifactContents, sumsFileContents, signatureFileContent)
}
3 changes: 2 additions & 1 deletion mockmirror/mockmirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import (
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/opentofu/tofudl"
"github.com/opentofu/tofudl/branding"
"github.com/opentofu/tofudl/internal/helloworld"
)

// New returns a mirror serving a fake archive signed with a GPG key for testing purposes.
func New(
t *testing.T,
) Mirror {
return NewFromBinary(t, buildFake(t))
return NewFromBinary(t, helloworld.Build(t))
}

// NewFromBinary returns a mirror serving a binary passed and signed with a GPG key for testing purposes.
Expand Down

0 comments on commit 76c6857

Please sign in to comment.