osbuild-composer: merge cloud API into main binary

This removes the osbuild-composer-cloud package, binary, systemd units,
the (unused) test binary, and the (only-run-on-RHEL) test in aws.sh.

Instead, move the cloud API into the main package, using the same
socket as the koji API, osbuild-composer-api.socket. Expose it next to
the koji API on route `/api/composer/v1`.

This is a backwards incompatible change, but only of the -cloud parts,
which have been marked as subject to change.
This commit is contained in:
Lars Karlitski 2020-10-03 09:58:39 +02:00 committed by Ondřej Budai
parent 835b556db7
commit b25a350502
14 changed files with 50 additions and 428 deletions

View file

@ -110,7 +110,6 @@ man: $(MANPAGES_TROFF)
build: build:
- mkdir bin - mkdir bin
go build -o bin/osbuild-composer ./cmd/osbuild-composer/ go build -o bin/osbuild-composer ./cmd/osbuild-composer/
go build -o bin/osbuild-composer-cloud ./cmd/osbuild-composer-cloud/
go build -o bin/osbuild-worker ./cmd/osbuild-worker/ go build -o bin/osbuild-worker ./cmd/osbuild-worker/
go build -o bin/osbuild-pipeline ./cmd/osbuild-pipeline/ go build -o bin/osbuild-pipeline ./cmd/osbuild-pipeline/
go build -o bin/osbuild-upload-azure ./cmd/osbuild-upload-azure/ go build -o bin/osbuild-upload-azure ./cmd/osbuild-upload-azure/
@ -119,7 +118,6 @@ build:
go test -c -tags=integration -o bin/osbuild-weldr-tests ./internal/client/ go test -c -tags=integration -o bin/osbuild-weldr-tests ./internal/client/
go test -c -tags=integration -o bin/osbuild-dnf-json-tests ./cmd/osbuild-dnf-json-tests/main_test.go go test -c -tags=integration -o bin/osbuild-dnf-json-tests ./cmd/osbuild-dnf-json-tests/main_test.go
go test -c -tags=integration -o bin/osbuild-image-tests ./cmd/osbuild-image-tests/ go test -c -tags=integration -o bin/osbuild-image-tests ./cmd/osbuild-image-tests/
go test -c -tags=integration -o bin/osbuild-composer-cloud-tests ./cmd/osbuild-composer-cloud-tests/main_test.go
go test -c -tags=integration -o bin/osbuild-auth-tests ./cmd/osbuild-auth-tests/ go test -c -tags=integration -o bin/osbuild-auth-tests ./cmd/osbuild-auth-tests/
.PHONY: install .PHONY: install
@ -127,7 +125,6 @@ install:
- mkdir -p /usr/libexec/osbuild-composer - mkdir -p /usr/libexec/osbuild-composer
cp bin/osbuild-composer /usr/libexec/osbuild-composer/ cp bin/osbuild-composer /usr/libexec/osbuild-composer/
cp bin/osbuild-worker /usr/libexec/osbuild-composer/ cp bin/osbuild-worker /usr/libexec/osbuild-composer/
cp bin/osbuild-composer-cloud /usr/libexec/osbuild-composer/
cp dnf-json /usr/libexec/osbuild-composer/ cp dnf-json /usr/libexec/osbuild-composer/
- mkdir -p /usr/share/osbuild-composer/repositories - mkdir -p /usr/share/osbuild-composer/repositories
cp repositories/* /usr/share/osbuild-composer/repositories cp repositories/* /usr/share/osbuild-composer/repositories

View file

@ -1,80 +0,0 @@
// +build integration
package main
import (
"context"
"net/http"
"testing"
"github.com/osbuild/osbuild-composer/internal/cloudapi"
"github.com/stretchr/testify/require"
"github.com/google/uuid"
)
func TestCloud(t *testing.T) {
client, err := cloudapi.NewClientWithResponses("http://127.0.0.1:8703/")
if err != nil {
panic(err)
}
response, err := client.ComposeWithResponse(context.Background(), cloudapi.ComposeJSONRequestBody{
Distribution: "rhel-8",
ImageRequests: []cloudapi.ImageRequest{
{
Architecture: "x86_64",
ImageType: "qcow2",
Repositories: []cloudapi.Repository{
{
Baseurl: "https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os",
},
{
Baseurl: "https://cdn.redhat.com/content/dist/rhel8/8/x86_64/appstream/os",
},
},
UploadRequests: []cloudapi.UploadRequest{
{
Options: cloudapi.AWSUploadRequestOptions{
Ec2: cloudapi.AWSUploadRequestOptionsEc2{
AccessKeyId: "access-key-id",
SecretAccessKey: "my-secret-key",
},
Region: "eu-central-1",
S3: cloudapi.AWSUploadRequestOptionsS3{
AccessKeyId: "access-key-id",
SecretAccessKey: "my-secret-key",
Bucket: "bucket",
},
},
Type: "aws",
},
},
},
},
Customizations: &cloudapi.Customizations{
Subscription: &cloudapi.Subscription {
ActivationKey: "somekey",
BaseUrl: "http://cdn.stage.redhat.com/",
ServerUrl: "subscription.rhsm.stage.redhat.com",
Organization: 00000,
Insights: true,
},
},
})
require.NoError(t, err)
require.Equalf(t, http.StatusCreated, response.StatusCode(), "Error: got non-201 status. Full response: %v", string(response.Body))
require.NotNil(t, response.JSON201)
response2, err := client.ComposeStatusWithResponse(context.Background(), response.JSON201.Id)
require.NoError(t, err)
require.Equalf(t, response2.StatusCode(), http.StatusOK, "Error: got non-200 status. Full response: %v", response2.Body)
response2, err = client.ComposeStatusWithResponse(context.Background(), "invalid-id")
require.NoError(t, err)
require.Equalf(t, response2.StatusCode(), http.StatusBadRequest, "Error: got non-400 status. Full response: %v", response2.Body)
response2, err = client.ComposeStatusWithResponse(context.Background(), uuid.New().String())
require.NoError(t, err)
require.Equalf(t, response2.StatusCode(), http.StatusNotFound, "Error: got non-404 status. Full response: %s", response2.Body)
}

View file

@ -1,149 +0,0 @@
package main
import (
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"os"
"path"
"github.com/osbuild/osbuild-composer/internal/cloudapi"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/distro/fedora31"
"github.com/osbuild/osbuild-composer/internal/distro/fedora32"
"github.com/osbuild/osbuild-composer/internal/distro/rhel8"
"github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
"github.com/osbuild/osbuild-composer/internal/worker"
"github.com/coreos/go-systemd/activation"
)
type connectionConfig struct {
CACertFile string
ServerKeyFile string
ServerCertFile string
}
func createTLSConfig(c *connectionConfig) (*tls.Config, error) {
caCertPEM, err := ioutil.ReadFile(c.CACertFile)
if err != nil {
panic(fmt.Sprintf("Failed to read root certificate %v", c.CACertFile))
}
roots := x509.NewCertPool()
ok := roots.AppendCertsFromPEM(caCertPEM)
if !ok {
panic(fmt.Sprintf("Failed to parse root certificate %v", c.CACertFile))
}
cert, err := tls.LoadX509KeyPair(c.ServerCertFile, c.ServerKeyFile)
if err != nil {
return nil, err
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: roots,
}, nil
}
func main() {
var verbose bool
flag.BoolVar(&verbose, "v", false, "Print access log")
flag.Parse()
tlsConfig, err := createTLSConfig(&connectionConfig{
CACertFile: "/etc/osbuild-composer/ca-crt.pem",
ServerKeyFile: "/etc/osbuild-composer/composer-key.pem",
ServerCertFile: "/etc/osbuild-composer/composer-crt.pem",
})
if err != nil {
log.Fatalf("TLS configuration cannot be created: %v", err.Error())
}
stateDir, ok := os.LookupEnv("STATE_DIRECTORY")
if !ok {
log.Fatal("STATE_DIRECTORY is not set. Is the service file missing StateDirectory=?")
}
cacheDirectory, ok := os.LookupEnv("CACHE_DIRECTORY")
if !ok {
log.Fatal("CACHE_DIRECTORY is not set. Is the service file missing CacheDirectory=?")
}
listeners, err := activation.ListenersWithNames()
if err != nil {
log.Fatalf("Could not get listening sockets: " + err.Error())
}
var cloudListener net.Listener
var jobListener net.Listener
if composerListeners, exists := listeners["osbuild-composer-cloud.socket"]; exists {
if len(composerListeners) != 2 {
log.Fatalf("Unexpected number of listening sockets (%d), expected 2", len(composerListeners))
}
cloudListener = composerListeners[0]
jobListener = tls.NewListener(composerListeners[1], tlsConfig)
} else {
log.Fatalf("osbuild-composer-cloud.socket doesn't exist")
}
var logger *log.Logger
if verbose {
logger = log.New(os.Stdout, "", 0)
}
queueDir := path.Join(stateDir, "jobs")
err = os.Mkdir(queueDir, 0700)
if err != nil && !os.IsExist(err) {
log.Fatalf("cannot create queue directory: %v", err)
}
distros, err := distro.NewRegistry(fedora31.New(), fedora32.New(), rhel8.New())
if err != nil {
log.Fatalf("Error loading distros: %v", err)
}
// construct job types of the form osbuild:{arch} for all arches
jobTypes := []string{"osbuild"}
jobTypesMap := map[string]bool{}
for _, name := range distros.List() {
d := distros.GetDistro(name)
for _, arch := range d.ListArches() {
jt := "osbuild:" + arch
if !jobTypesMap[jt] {
jobTypesMap[jt] = true
jobTypes = append(jobTypes, jt)
}
}
}
jobs, err := fsjobqueue.New(queueDir, jobTypes)
if err != nil {
log.Fatalf("cannot create jobqueue: %v", err)
}
rpm := rpmmd.NewRPMMD(path.Join(cacheDirectory, "rpmmd"), "/usr/libexec/osbuild-composer/dnf-json")
workerServer := worker.NewServer(logger, jobs, "")
cloudServer := cloudapi.NewServer(workerServer, rpm, distros)
go func() {
err := workerServer.Serve(jobListener)
if err != nil {
panic(err)
}
}()
err = cloudServer.Serve(cloudListener)
if err != nil {
panic(err)
}
}

View file

@ -8,9 +8,11 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
"net/http"
"os" "os"
"path" "path"
"github.com/osbuild/osbuild-composer/internal/cloudapi"
"github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue" "github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue"
"github.com/osbuild/osbuild-composer/internal/kojiapi" "github.com/osbuild/osbuild-composer/internal/kojiapi"
@ -38,9 +40,10 @@ type Composer struct {
workers *worker.Server workers *worker.Server
weldr *weldr.API weldr *weldr.API
api *cloudapi.Server
koji *kojiapi.Server koji *kojiapi.Server
weldrListener, localWorkerListener, workerListener, kojiListener net.Listener weldrListener, localWorkerListener, workerListener, apiListener net.Listener
} }
func NewComposer(config *ComposerConfigFile, stateDir, cacheDir string, logger *log.Logger) (*Composer, error) { func NewComposer(config *ComposerConfigFile, stateDir, cacheDir string, logger *log.Logger) (*Composer, error) {
@ -127,7 +130,9 @@ func (c *Composer) InitWeldr(repoPaths []string, weldrListener, localWorkerListe
return nil return nil
} }
func (c *Composer) InitKoji(cert, key string, l net.Listener) error { func (c *Composer) InitAPI(cert, key string, l net.Listener) error {
c.api = cloudapi.NewServer(c.workers, c.rpm, c.distros)
servers := make(map[string]koji.GSSAPICredentials) servers := make(map[string]koji.GSSAPICredentials)
for name, creds := range c.config.Koji.Servers { for name, creds := range c.config.Koji.Servers {
if creds.Kerberos != nil { if creds.Kerberos != nil {
@ -137,7 +142,6 @@ func (c *Composer) InitKoji(cert, key string, l net.Listener) error {
} }
} }
} }
c.koji = kojiapi.NewServer(c.logger, c.workers, c.rpm, c.distros, servers) c.koji = kojiapi.NewServer(c.logger, c.workers, c.rpm, c.distros, servers)
tlsConfig, err := createTLSConfig(&connectionConfig{ tlsConfig, err := createTLSConfig(&connectionConfig{
@ -147,10 +151,10 @@ func (c *Composer) InitKoji(cert, key string, l net.Listener) error {
AllowedDomains: c.config.Koji.AllowedDomains, AllowedDomains: c.config.Koji.AllowedDomains,
}) })
if err != nil { if err != nil {
return fmt.Errorf("Error creating TLS configuration for Koji API: %v", err) return fmt.Errorf("Error creating TLS configuration: %v", err)
} }
c.kojiListener = tls.NewListener(l, tlsConfig) c.apiListener = tls.NewListener(l, tlsConfig)
return nil return nil
} }
@ -197,9 +201,25 @@ func (c *Composer) Start() error {
}() }()
} }
if c.kojiListener != nil { if c.apiListener != nil {
go func() { go func() {
err := c.koji.Serve(c.kojiListener) const apiRoute = "/api/composer/v1"
const kojiRoute = "/api/composer-koji/v1"
mux := http.NewServeMux()
// Add a "/" here, because http.ServeMux expects the
// trailing slash for rooted subtrees, whereas the
// handler functions don't.
mux.Handle(apiRoute+"/", c.api.Handler(apiRoute))
mux.Handle(kojiRoute+"/", c.koji.Handler(kojiRoute))
s := &http.Server{
ErrorLog: c.logger,
Handler: mux,
}
err := s.Serve(c.apiListener)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -82,7 +82,7 @@ func main() {
log.Fatal("The osbuild-composer-api.socket unit is misconfigured. It should contain only one socket.") log.Fatal("The osbuild-composer-api.socket unit is misconfigured. It should contain only one socket.")
} }
err = composer.InitKoji(ServerCertFile, ServerKeyFile, l[0]) err = composer.InitAPI(ServerCertFile, ServerKeyFile, l[0])
if err != nil { if err != nil {
log.Fatalf("Error initializing koji API: %v", err) log.Fatalf("Error initializing koji API: %v", err)
} }

View file

@ -1,19 +0,0 @@
[Unit]
Description=OSBuild Composer cloud
After=multi-user.target
Requires=osbuild-composer-cloud.socket
[Service]
Type=simple
ExecStart=/usr/libexec/osbuild-composer/osbuild-composer-cloud
CacheDirectory=osbuild-composer-cloud
StateDirectory=osbuild-composer-cloud
WorkingDirectory=/usr/libexec/osbuild-composer/
Restart=on-failure
# systemd >= 240 sets this, but osbuild-composer runs on earlier versions
Environment="CACHE_DIRECTORY=/var/cache/osbuild-composer-cloud"
Environment="STATE_DIRECTORY=/var/lib/osbuild-composer-cloud"
[Install]
WantedBy=multi-user.target

View file

@ -1,10 +0,0 @@
[Unit]
Description=OSBuild Composer cloud API sockets
[Socket]
Service=osbuild-composer-cloud.service
ListenStream=8703
ListenStream=8704
[Install]
WantedBy=sockets.target

View file

@ -5,9 +5,9 @@ package cloudapi
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net"
"net/http" "net/http"
"github.com/go-chi/chi"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint" "github.com/osbuild/osbuild-composer/internal/blueprint"
@ -34,16 +34,16 @@ func NewServer(workers *worker.Server, rpmMetadata rpmmd.RPMMD, distros *distro.
return server return server
} }
// Serve serves the cloud API over the provided listener socket // Create an http.Handler() for this server, that provides the composer API at
func (server *Server) Serve(listener net.Listener) error { // the given path.
s := http.Server{Handler: Handler(server)} func (server *Server) Handler(path string) http.Handler {
r := chi.NewRouter()
err := s.Serve(listener) r.Route(path, func(r chi.Router) {
if err != nil && err != http.ErrServerClosed { HandlerFromMux(server, r)
return err })
}
return nil return r
} }
// Compose handles a new /compose POST request // Compose handles a new /compose POST request
@ -150,7 +150,7 @@ func (server *Server) Compose(w http.ResponseWriter, r *http.Request) {
return return
} }
key := fmt.Sprintf("composer-cloudapi-%s", uuid.New().String()) key := fmt.Sprintf("composer-api-%s", uuid.New().String())
t := target.NewAWSTarget(&target.AWSTargetOptions{ t := target.NewAWSTarget(&target.AWSTargetOptions{
Filename: imageType.Filename(), Filename: imageType.Filename(),
Region: awsUploadOptions.Region, Region: awsUploadOptions.Region,

View file

@ -1,5 +1,3 @@
//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen -package=api -generate types,server -o api.gen.go openapi.yml //go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen -package=api -generate types,server -o api.gen.go openapi.yml
package api package api
const BasePath = "/api/composer-koji/v1"

View file

@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"net"
"net/http" "net/http"
"net/url" "net/url"
@ -24,7 +23,7 @@ import (
// Server represents the state of the koji Server // Server represents the state of the koji Server
type Server struct { type Server struct {
server *http.Server logger *log.Logger
workers *worker.Server workers *worker.Server
rpmMetadata rpmmd.RPMMD rpmMetadata rpmmd.RPMMD
distros *distro.Registry distros *distro.Registry
@ -34,38 +33,26 @@ type Server struct {
// NewServer creates a new koji server // NewServer creates a new koji server
func NewServer(logger *log.Logger, workers *worker.Server, rpmMetadata rpmmd.RPMMD, distros *distro.Registry, kojiServers map[string]koji.GSSAPICredentials) *Server { func NewServer(logger *log.Logger, workers *worker.Server, rpmMetadata rpmmd.RPMMD, distros *distro.Registry, kojiServers map[string]koji.GSSAPICredentials) *Server {
s := &Server{ s := &Server{
logger: logger,
workers: workers, workers: workers,
rpmMetadata: rpmMetadata, rpmMetadata: rpmMetadata,
distros: distros, distros: distros,
kojiServers: kojiServers, kojiServers: kojiServers,
} }
e := echo.New()
e.Binder = binder{}
e.StdLogger = logger
api.RegisterHandlers(e.Group(api.BasePath), &apiHandlers{s})
s.server = &http.Server{
ErrorLog: logger,
Handler: e,
}
return s return s
} }
// Serve serves the koji API over the provided listener socket // Create an http.Handler() for this server, that provides the koji API at the
func (s *Server) Serve(listener net.Listener) error { // given path.
err := s.server.Serve(listener) func (s *Server) Handler(path string) http.Handler {
if err != nil && err != http.ErrServerClosed { e := echo.New()
return err e.Binder = binder{}
} e.StdLogger = s.logger
return nil api.RegisterHandlers(e.Group(path), &apiHandlers{s})
}
func (s *Server) Handler() http.Handler { return e
return s.server.Handler
} }
// apiHandlers implements api.ServerInterface - the http api route handlers // apiHandlers implements api.ServerInterface - the http api route handlers

View file

@ -35,7 +35,7 @@ func newTestKojiServer(t *testing.T) *kojiapi.Server {
func TestStatus(t *testing.T) { func TestStatus(t *testing.T) {
server := newTestKojiServer(t) server := newTestKojiServer(t)
handler := server.Handler() handler := server.Handler("/api/composer-koji/v1")
req := httptest.NewRequest("GET", "/api/composer-koji/v1/status", nil) req := httptest.NewRequest("GET", "/api/composer-koji/v1/status", nil)
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")

View file

@ -115,7 +115,6 @@ export GOFLAGS=-mod=vendor
%gobuild -o _bin/osbuild-composer %{goipath}/cmd/osbuild-composer %gobuild -o _bin/osbuild-composer %{goipath}/cmd/osbuild-composer
%gobuild -o _bin/osbuild-worker %{goipath}/cmd/osbuild-worker %gobuild -o _bin/osbuild-worker %{goipath}/cmd/osbuild-worker
%gobuild -o _bin/osbuild-composer-cloud %{goipath}/cmd/osbuild-composer-cloud
%if %{with tests} || 0%{?rhel} %if %{with tests} || 0%{?rhel}
@ -137,7 +136,6 @@ go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-composer
go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-dnf-json-tests %{goipath}/cmd/osbuild-dnf-json-tests go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-dnf-json-tests %{goipath}/cmd/osbuild-dnf-json-tests
go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-weldr-tests %{goipath}/internal/client/ go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-weldr-tests %{goipath}/internal/client/
go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-image-tests %{goipath}/cmd/osbuild-image-tests go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-image-tests %{goipath}/cmd/osbuild-image-tests
go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-composer-cloud-tests %{goipath}/cmd/osbuild-composer-cloud-tests
go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-auth-tests %{goipath}/cmd/osbuild-auth-tests go test -c -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/osbuild-auth-tests %{goipath}/cmd/osbuild-auth-tests
go build -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/cloud-cleaner %{goipath}/cmd/cloud-cleaner go build -tags=integration -ldflags="${TEST_LDFLAGS}" -o _bin/cloud-cleaner %{goipath}/cmd/cloud-cleaner
@ -169,9 +167,6 @@ install -m 0644 -vp distribution/osbuild-composer.conf %{buildroot}%{_s
install -m 0755 -vd %{buildroot}%{_localstatedir}/cache/osbuild-composer/dnf-cache install -m 0755 -vd %{buildroot}%{_localstatedir}/cache/osbuild-composer/dnf-cache
install -m 0755 -vp _bin/osbuild-composer-cloud %{buildroot}%{_libexecdir}/osbuild-composer/
install -m 0644 -vp distribution/osbuild-composer-cloud.{service,socket} %{buildroot}%{_unitdir}/
%if %{with tests} || 0%{?rhel} %if %{with tests} || 0%{?rhel}
install -m 0755 -vd %{buildroot}%{_libexecdir}/tests/osbuild-composer install -m 0755 -vd %{buildroot}%{_libexecdir}/tests/osbuild-composer
@ -179,7 +174,6 @@ install -m 0755 -vp _bin/osbuild-composer-cli-tests %{buildroot}%{_l
install -m 0755 -vp _bin/osbuild-weldr-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/ install -m 0755 -vp _bin/osbuild-weldr-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/
install -m 0755 -vp _bin/osbuild-dnf-json-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/ install -m 0755 -vp _bin/osbuild-dnf-json-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/
install -m 0755 -vp _bin/osbuild-image-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/ install -m 0755 -vp _bin/osbuild-image-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/
install -m 0755 -vp _bin/osbuild-composer-cloud-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/
install -m 0755 -vp _bin/osbuild-auth-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/ install -m 0755 -vp _bin/osbuild-auth-tests %{buildroot}%{_libexecdir}/tests/osbuild-composer/
install -m 0755 -vp test/cmd/* %{buildroot}%{_libexecdir}/tests/osbuild-composer/ install -m 0755 -vp test/cmd/* %{buildroot}%{_libexecdir}/tests/osbuild-composer/
install -m 0755 -vp _bin/cloud-cleaner %{buildroot}%{_libexecdir}/osbuild-composer/ install -m 0755 -vp _bin/cloud-cleaner %{buildroot}%{_libexecdir}/osbuild-composer/
@ -286,34 +280,12 @@ systemctl stop "osbuild-worker@*.service" "osbuild-remote-worker@*.service"
# restart all the worker services # restart all the worker services
%systemd_postun_with_restart "osbuild-worker@*.service" "osbuild-remote-worker@*.service" %systemd_postun_with_restart "osbuild-worker@*.service" "osbuild-remote-worker@*.service"
%package cloud
Summary: The osbuild-composer cloud api
Requires: systemd
%description cloud
The cloud api for osbuild-composer
%files cloud
%{_libexecdir}/osbuild-composer/osbuild-composer-cloud
%{_unitdir}/osbuild-composer-cloud.socket
%{_unitdir}/osbuild-composer-cloud.service
%post cloud
%systemd_post osbuild-composer-cloud.socket osbuild-composer-cloud.service
%preun cloud
%systemd_preun osbuild-composer-cloud.socket osbuild-composer-cloud.service
%postun cloud
%systemd_postun_with_restart osbuild-composer-cloud.socket osbuild-composer-cloud.service
%if %{with tests} || 0%{?rhel} %if %{with tests} || 0%{?rhel}
%package tests %package tests
Summary: Integration tests Summary: Integration tests
Requires: %{name} = %{version}-%{release} Requires: %{name} = %{version}-%{release}
Requires: %{name}-koji = %{version}-%{release} Requires: %{name}-koji = %{version}-%{release}
Requires: %{name}-cloud = %{version}-%{release}
Requires: composer-cli Requires: composer-cli
Requires: createrepo_c Requires: createrepo_c
Requires: genisoimage Requires: genisoimage

Binary file not shown.

View file

@ -275,7 +275,7 @@ $AWS_CMD ec2 delete-snapshot --snapshot-id "${SNAPSHOT_ID}"
# Use the return code of the smoke test to determine if we passed or failed. # Use the return code of the smoke test to determine if we passed or failed.
# On rhel continue with the cloudapi test # On rhel continue with the cloudapi test
if [[ $RESULTS == 1 ]] && [[ $ID != rhel ]]; then if [[ $RESULTS == 1 ]]; then
greenprint "💚 Success" greenprint "💚 Success"
exit 0 exit 0
elif [[ $RESULTS != 1 ]]; then elif [[ $RESULTS != 1 ]]; then
@ -283,98 +283,4 @@ elif [[ $RESULTS != 1 ]]; then
exit 1 exit 1
fi fi
CLOUD_REQUEST_FILE=${TEMPDIR}/image_request.json
REPOSITORY_RHEL=repositories/rhel-8.json
if [[ $VERSION_ID == 8.3 ]]; then
REPOSITORY_RHEL=repositories/rhel-8-beta.json
fi
sudo systemctl stop osbuild-worker*
sudo systemctl start osbuild-remote-worker@localhost:8704
BASE_URL=$(jq -r '.x86_64[0].baseurl' "$REPOSITORY_RHEL")
APPSTREAM_URL=$(jq -r '.x86_64[1].baseurl' "$REPOSITORY_RHEL")
SNAPSHOT_NAME=$(cat /proc/sys/kernel/random/uuid)
tee "$CLOUD_REQUEST_FILE" > /dev/null << EOF
{
"distribution": "rhel-8",
"image_requests": [
{
"architecture": "x86_64",
"image_type": "qcow2",
"repositories": [
{
"baseurl": "${BASE_URL}",
"rhsm": true
},
{
"baseurl": "${APPSTREAM_URL}",
"rhsm": true
}
],
"upload_requests": [
{
"type": "aws",
"options": {
"region": "${AWS_REGION}",
"s3": {
"access_key_id": "${AWS_ACCESS_KEY_ID}",
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}",
"bucket": "${AWS_BUCKET}"
},
"ec2": {
"access_key_id": "${AWS_ACCESS_KEY_ID}",
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}",
"snapshot_name": "${SNAPSHOT_NAME}"
}
}
}
]
}
]
}
EOF
COMPOSE_ID=$(curl -sS -H 'Content-Type: application/json' -X POST -d @"$CLOUD_REQUEST_FILE" http://localhost:8703/compose | jq -r '.id')
# Wait for the compose to finish.
greenprint "⏱ Waiting for cloud compose to finish: ${COMPOSE_ID}"
for LOOP_COUNTER in {0..40}; do
COMPOSE_STATUS=$(curl -sS http://localhost:8703/compose/"$COMPOSE_ID" | jq -r '.status')
echo "Cloud compose $COMPOSE_ID status: $COMPOSE_STATUS"
if [[ $COMPOSE_STATUS == FAILED ]]; then
echo "Something went wrong with the cloudapi compose. 😢"
exit 1
elif [[ $COMPOSE_STATUS != RUNNING ]] && [[ $COMPOSE_STATUS != WAITING ]]; then
break
fi
sleep 30
done
# Find the image that we made in AWS.
greenprint "🔍 Search for created AMI"
$AWS_CMD ec2 describe-images \
--owners self \
--filters Name=name,Values="$SNAPSHOT_NAME" \
| tee "$AMI_DATA" > /dev/null
AMI_IMAGE_ID=$(jq -r '.Images[].ImageId' "$AMI_DATA")
SNAPSHOT_ID=$(jq -r '.Images[].BlockDeviceMappings[].Ebs.SnapshotId' "$AMI_DATA")
# Delete the image without running it
greenprint "🧼 Cleaning up composer cloud image"
$AWS_CMD ec2 deregister-image --image-id "$AMI_IMAGE_ID"
$AWS_CMD ec2 delete-snapshot --snapshot-id "$SNAPSHOT_ID"
# Use the return code of the smoke test to determine if we passed or failed.
if [[ $RESULTS == 1 ]]; then
greenprint "💚 Success"
else
greenprint "❌ Failed"
exit 1
fi
exit 0 exit 0