Skip to content

Commit

Permalink
feat: implement HTTP API client
Browse files Browse the repository at this point in the history
The client provides methods to create schematics, Talos versions, and
extensions version.

Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
  • Loading branch information
Unix4ever committed Nov 30, 2023
1 parent 84113ca commit 01fcbf1
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2023-11-28T14:31:58Z by kres latest.
# Generated on 2023-11-30T12:42:01Z by kres latest.

name: default
concurrency:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/slack-notify.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2023-11-21T16:57:47Z by kres latest.
# Generated on 2023-11-30T12:42:01Z by kres latest.

name: slack-notify
"on":
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2023-11-30T10:18:19Z by kres 902f3bd-dirty.
# Generated on 2023-11-30T12:42:01Z by kres latest.

ARG TOOLCHAIN

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2023-11-30T10:20:41Z by kres 902f3bd-dirty.
# Generated on 2023-11-30T12:36:19Z by kres latest.

# common variables

Expand Down
11 changes: 3 additions & 8 deletions internal/frontend/http/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/siderolabs/gen/xslices"

"github.com/siderolabs/image-factory/internal/artifacts"
"github.com/siderolabs/image-factory/pkg/client"
)

// handleVersions handles list of Talos versions available.
Expand Down Expand Up @@ -49,15 +50,9 @@ func (f *Frontend) handleOfficialExtensions(ctx context.Context, w http.Response
return err
}

type extensionInfo struct {
Name string `json:"name"`
Ref string `json:"ref"`
Digest string `json:"digest"`
}

return json.NewEncoder(w).Encode(
xslices.Map(extensions, func(e artifacts.ExtensionRef) extensionInfo {
return extensionInfo{
xslices.Map(extensions, func(e artifacts.ExtensionRef) client.ExtensionInfo {
return client.ExtensionInfo{
Name: e.TaggedReference.RepositoryStr(),
Ref: e.TaggedReference.String(),
Digest: e.Digest,
Expand Down
55 changes: 13 additions & 42 deletions internal/integration/meta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,70 +8,41 @@ package integration_test

import (
"context"
"encoding/json"
"net/http"
"testing"

"github.com/siderolabs/gen/xslices"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/siderolabs/image-factory/pkg/client"
)

func getVersions(ctx context.Context, t *testing.T, baseURL string) []string {
func getVersions(ctx context.Context, t *testing.T, c *client.Client) []string {
t.Helper()

req, err := http.NewRequestWithContext(ctx, "GET", baseURL+"/versions", nil)
require.NoError(t, err)

resp, err := http.DefaultClient.Do(req)
versions, err := c.Versions(ctx)
require.NoError(t, err)

t.Cleanup(func() {
resp.Body.Close()
})

require.Equal(t, http.StatusOK, resp.StatusCode)

var versions []string

require.NoError(t, json.NewDecoder(resp.Body).Decode(&versions))

return versions
}

type extensionInfo struct {
Name string `json:"name"`
Ref string `json:"ref"`
Digest string `json:"digest"`
}

func getExtensions(ctx context.Context, t *testing.T, baseURL, talosVersion string) []extensionInfo {
func getExtensions(ctx context.Context, t *testing.T, c *client.Client, talosVersion string) []client.ExtensionInfo {
t.Helper()

req, err := http.NewRequestWithContext(ctx, "GET", baseURL+"/version/"+talosVersion+"/extensions/official", nil)
versions, err := c.ExtensionsVersions(ctx, talosVersion)
require.NoError(t, err)

resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)

t.Cleanup(func() {
resp.Body.Close()
})

require.Equal(t, http.StatusOK, resp.StatusCode)

var extensions []extensionInfo

require.NoError(t, json.NewDecoder(resp.Body).Decode(&extensions))

return extensions
return versions
}

func testMetaFrontend(ctx context.Context, t *testing.T, baseURL string) {
c, err := client.New(baseURL)
require.NoError(t, err)

t.Run("versions", func(t *testing.T) {
t.Parallel()

versions := getVersions(ctx, t, baseURL)
versions := getVersions(ctx, t, c)

assert.Greater(t, len(versions), 10)
})
Expand All @@ -88,9 +59,9 @@ func testMetaFrontend(ctx context.Context, t *testing.T, baseURL string) {
t.Run(talosVersion, func(t *testing.T) {
t.Parallel()

extensions := getExtensions(ctx, t, baseURL, talosVersion)
extensions := getExtensions(ctx, t, c, talosVersion)

names := xslices.Map(extensions, func(ext extensionInfo) string {
names := xslices.Map(extensions, func(ext client.ExtensionInfo) string {
return ext.Name
})

Expand Down
6 changes: 5 additions & 1 deletion internal/integration/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"

"github.com/siderolabs/image-factory/pkg/client"
"github.com/siderolabs/image-factory/pkg/schematic"
)

Expand Down Expand Up @@ -181,10 +182,13 @@ func testRegistryFrontend(ctx context.Context, t *testing.T, registryAddr string
registry, err := name.NewRegistry(registryAddr)
require.NoError(t, err)

c, err := client.New("http://" + registryAddr)
require.NoError(t, err)

// create a new random schematic, so that we can make sure new installer is generated
randomKernelArg := hex.EncodeToString(randomBytes(t, 32))

randomSchematicID := createSchematicGetID(ctx, t, "http://"+registryAddr,
randomSchematicID := createSchematicGetID(ctx, t, c,
schematic.Schematic{
Customization: schematic.Customization{
ExtraKernelArgs: []string{randomKernelArg},
Expand Down
58 changes: 21 additions & 37 deletions internal/integration/schematic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"io"
"net/http"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/siderolabs/image-factory/pkg/client"
"github.com/siderolabs/image-factory/pkg/schematic"
)

Expand All @@ -30,47 +30,28 @@ const (
metaSchematicID = "fe866116408a5a13dab7d5003eb57a00954ea81ebeec3fbbcd1a6d4462a00036"
)

func createSchematic(ctx context.Context, t *testing.T, baseURL string, marshalled []byte) *http.Response {
func createSchematicGetID(ctx context.Context, t *testing.T, c *client.Client, schematic schematic.Schematic) string {
t.Helper()

req, err := http.NewRequestWithContext(ctx, "POST", baseURL+"/schematics", bytes.NewReader(marshalled))
require.NoError(t, err)

resp, err := http.DefaultClient.Do(req)
id, err := c.SchematicCreate(ctx, schematic)
require.NoError(t, err)

t.Cleanup(func() {
resp.Body.Close()
})

return resp
return id
}

func createSchematicGetID(ctx context.Context, t *testing.T, baseURL string, schematic schematic.Schematic) string {
// not using the client here as we need to submit invalid yaml.
func createSchematicInvalid(ctx context.Context, t *testing.T, baseURL string, marshalled []byte) string {
t.Helper()

marshalled, err := schematic.Marshal()
req, err := http.NewRequestWithContext(ctx, "POST", baseURL+"/schematics", bytes.NewReader(marshalled))
require.NoError(t, err)

resp := createSchematic(ctx, t, baseURL, marshalled)

require.Equal(t, http.StatusCreated, resp.StatusCode)

var respBody struct {
ID string `json:"id"`
}

require.NoError(t, json.NewDecoder(resp.Body).Decode(&respBody))

return respBody.ID
}

func createSchematicInvalid(ctx context.Context, t *testing.T, baseURL string, marshalled []byte) string {
t.Helper()

resp := createSchematic(ctx, t, baseURL, marshalled)
resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)

require.Equal(t, http.StatusBadRequest, resp.StatusCode)
t.Cleanup(func() {
resp.Body.Close()
})

body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
Expand All @@ -79,12 +60,15 @@ func createSchematicInvalid(ctx context.Context, t *testing.T, baseURL string, m
}

func testSchematic(ctx context.Context, t *testing.T, baseURL string) {
c, err := client.New(baseURL)
require.NoError(t, err)

t.Run("empty", func(t *testing.T) {
assert.Equal(t, emptySchematicID, createSchematicGetID(ctx, t, baseURL, schematic.Schematic{}))
assert.Equal(t, emptySchematicID, createSchematicGetID(ctx, t, c, schematic.Schematic{}))
})

t.Run("kernel args", func(t *testing.T) {
assert.Equal(t, extraArgsSchematicID, createSchematicGetID(ctx, t, baseURL,
assert.Equal(t, extraArgsSchematicID, createSchematicGetID(ctx, t, c,
schematic.Schematic{
Customization: schematic.Customization{
ExtraKernelArgs: []string{"nolapic", "nomodeset"},
Expand All @@ -94,7 +78,7 @@ func testSchematic(ctx context.Context, t *testing.T, baseURL string) {
})

t.Run("system extensions", func(t *testing.T) {
assert.Equal(t, systemExtensionsSchematicID, createSchematicGetID(ctx, t, baseURL,
assert.Equal(t, systemExtensionsSchematicID, createSchematicGetID(ctx, t, c,
schematic.Schematic{
Customization: schematic.Customization{
SystemExtensions: schematic.SystemExtensions{
Expand All @@ -110,7 +94,7 @@ func testSchematic(ctx context.Context, t *testing.T, baseURL string) {
})

t.Run("meta", func(t *testing.T) {
assert.Equal(t, metaSchematicID, createSchematicGetID(ctx, t, baseURL,
assert.Equal(t, metaSchematicID, createSchematicGetID(ctx, t, c,
schematic.Schematic{
Customization: schematic.Customization{
Meta: []schematic.MetaValue{
Expand All @@ -125,7 +109,7 @@ func testSchematic(ctx context.Context, t *testing.T, baseURL string) {
})

t.Run("empty once again", func(t *testing.T) {
assert.Equal(t, emptySchematicID, createSchematicGetID(ctx, t, baseURL, schematic.Schematic{}))
assert.Equal(t, emptySchematicID, createSchematicGetID(ctx, t, c, schematic.Schematic{}))
})

t.Run("invalid", func(t *testing.T) {
Expand All @@ -136,7 +120,7 @@ func testSchematic(ctx context.Context, t *testing.T, baseURL string) {
// create a new random schematic, as the schematic is persisted, and we want to test uploading new config
randomKernelArg := hex.EncodeToString(randomBytes(t, 32))

assert.Len(t, createSchematicGetID(ctx, t, baseURL,
assert.Len(t, createSchematicGetID(ctx, t, c,
schematic.Schematic{
Customization: schematic.Customization{
ExtraKernelArgs: []string{randomKernelArg},
Expand Down
Loading

0 comments on commit 01fcbf1

Please sign in to comment.