diff --git a/Makefile b/Makefile index b07ffab58..d6f0786a5 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,6 @@ man: $(MANPAGES_TROFF) build: - mkdir bin 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-pipeline ./cmd/osbuild-pipeline/ 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-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-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/ .PHONY: install @@ -127,7 +125,6 @@ install: - mkdir -p /usr/libexec/osbuild-composer cp bin/osbuild-composer /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/ - mkdir -p /usr/share/osbuild-composer/repositories cp repositories/* /usr/share/osbuild-composer/repositories diff --git a/cmd/osbuild-composer-cloud-tests/main_test.go b/cmd/osbuild-composer-cloud-tests/main_test.go deleted file mode 100644 index 55923719f..000000000 --- a/cmd/osbuild-composer-cloud-tests/main_test.go +++ /dev/null @@ -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) -} diff --git a/cmd/osbuild-composer-cloud/main.go b/cmd/osbuild-composer-cloud/main.go deleted file mode 100644 index 6becccf82..000000000 --- a/cmd/osbuild-composer-cloud/main.go +++ /dev/null @@ -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) - } -} diff --git a/cmd/osbuild-composer/composer.go b/cmd/osbuild-composer/composer.go index 2b6c4e619..a126b410c 100644 --- a/cmd/osbuild-composer/composer.go +++ b/cmd/osbuild-composer/composer.go @@ -8,9 +8,11 @@ import ( "io/ioutil" "log" "net" + "net/http" "os" "path" + "github.com/osbuild/osbuild-composer/internal/cloudapi" "github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue" "github.com/osbuild/osbuild-composer/internal/kojiapi" @@ -38,9 +40,10 @@ type Composer struct { workers *worker.Server weldr *weldr.API + api *cloudapi.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) { @@ -127,7 +130,9 @@ func (c *Composer) InitWeldr(repoPaths []string, weldrListener, localWorkerListe 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) for name, creds := range c.config.Koji.Servers { 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) tlsConfig, err := createTLSConfig(&connectionConfig{ @@ -147,10 +151,10 @@ func (c *Composer) InitKoji(cert, key string, l net.Listener) error { AllowedDomains: c.config.Koji.AllowedDomains, }) 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 } @@ -197,9 +201,25 @@ func (c *Composer) Start() error { }() } - if c.kojiListener != nil { + if c.apiListener != nil { 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 { panic(err) } diff --git a/cmd/osbuild-composer/main.go b/cmd/osbuild-composer/main.go index 9956d82e0..a22b2943a 100644 --- a/cmd/osbuild-composer/main.go +++ b/cmd/osbuild-composer/main.go @@ -82,7 +82,7 @@ func main() { 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 { log.Fatalf("Error initializing koji API: %v", err) } diff --git a/distribution/osbuild-composer-cloud.service b/distribution/osbuild-composer-cloud.service deleted file mode 100644 index cf5e0d98a..000000000 --- a/distribution/osbuild-composer-cloud.service +++ /dev/null @@ -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 diff --git a/distribution/osbuild-composer-cloud.socket b/distribution/osbuild-composer-cloud.socket deleted file mode 100644 index e73dfc6d6..000000000 --- a/distribution/osbuild-composer-cloud.socket +++ /dev/null @@ -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 diff --git a/internal/cloudapi/server.go b/internal/cloudapi/server.go index 8bfd909e9..9b3569108 100644 --- a/internal/cloudapi/server.go +++ b/internal/cloudapi/server.go @@ -5,9 +5,9 @@ package cloudapi import ( "encoding/json" "fmt" - "net" "net/http" + "github.com/go-chi/chi" "github.com/google/uuid" "github.com/osbuild/osbuild-composer/internal/blueprint" @@ -34,16 +34,16 @@ func NewServer(workers *worker.Server, rpmMetadata rpmmd.RPMMD, distros *distro. return server } -// Serve serves the cloud API over the provided listener socket -func (server *Server) Serve(listener net.Listener) error { - s := http.Server{Handler: Handler(server)} +// Create an http.Handler() for this server, that provides the composer API at +// the given path. +func (server *Server) Handler(path string) http.Handler { + r := chi.NewRouter() - err := s.Serve(listener) - if err != nil && err != http.ErrServerClosed { - return err - } + r.Route(path, func(r chi.Router) { + HandlerFromMux(server, r) + }) - return nil + return r } // Compose handles a new /compose POST request @@ -150,7 +150,7 @@ func (server *Server) Compose(w http.ResponseWriter, r *http.Request) { return } - key := fmt.Sprintf("composer-cloudapi-%s", uuid.New().String()) + key := fmt.Sprintf("composer-api-%s", uuid.New().String()) t := target.NewAWSTarget(&target.AWSTargetOptions{ Filename: imageType.Filename(), Region: awsUploadOptions.Region, diff --git a/internal/kojiapi/api/api.go b/internal/kojiapi/api/api.go index 4f4e8dccf..b5f2978c4 100644 --- a/internal/kojiapi/api/api.go +++ b/internal/kojiapi/api/api.go @@ -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 package api - -const BasePath = "/api/composer-koji/v1" diff --git a/internal/kojiapi/server.go b/internal/kojiapi/server.go index 9c7a549d7..ec3b927d6 100644 --- a/internal/kojiapi/server.go +++ b/internal/kojiapi/server.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "log" - "net" "net/http" "net/url" @@ -24,7 +23,7 @@ import ( // Server represents the state of the koji Server type Server struct { - server *http.Server + logger *log.Logger workers *worker.Server rpmMetadata rpmmd.RPMMD distros *distro.Registry @@ -34,38 +33,26 @@ type Server struct { // 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 { s := &Server{ + logger: logger, workers: workers, rpmMetadata: rpmMetadata, distros: distros, 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 } -// Serve serves the koji API over the provided listener socket -func (s *Server) Serve(listener net.Listener) error { - err := s.server.Serve(listener) - if err != nil && err != http.ErrServerClosed { - return err - } +// Create an http.Handler() for this server, that provides the koji API at the +// given path. +func (s *Server) Handler(path string) http.Handler { + e := echo.New() + e.Binder = binder{} + e.StdLogger = s.logger - return nil -} + api.RegisterHandlers(e.Group(path), &apiHandlers{s}) -func (s *Server) Handler() http.Handler { - return s.server.Handler + return e } // apiHandlers implements api.ServerInterface - the http api route handlers diff --git a/internal/kojiapi/server_test.go b/internal/kojiapi/server_test.go index 78c4096c7..85b052000 100644 --- a/internal/kojiapi/server_test.go +++ b/internal/kojiapi/server_test.go @@ -35,7 +35,7 @@ func newTestKojiServer(t *testing.T) *kojiapi.Server { func TestStatus(t *testing.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.Header.Set("Content-Type", "application/json") diff --git a/osbuild-composer.spec b/osbuild-composer.spec index b403df090..e375e3f28 100644 --- a/osbuild-composer.spec +++ b/osbuild-composer.spec @@ -115,7 +115,6 @@ export GOFLAGS=-mod=vendor %gobuild -o _bin/osbuild-composer %{goipath}/cmd/osbuild-composer %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} @@ -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-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-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 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 -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} 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-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-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 test/cmd/* %{buildroot}%{_libexecdir}/tests/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 %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} %package tests Summary: Integration tests Requires: %{name} = %{version}-%{release} Requires: %{name}-koji = %{version}-%{release} -Requires: %{name}-cloud = %{version}-%{release} Requires: composer-cli Requires: createrepo_c Requires: genisoimage diff --git a/osbuild-image-tests b/osbuild-image-tests deleted file mode 100755 index a323263c7..000000000 Binary files a/osbuild-image-tests and /dev/null differ diff --git a/test/cmd/aws.sh b/test/cmd/aws.sh index fe09525e8..9c7fe1d39 100755 --- a/test/cmd/aws.sh +++ b/test/cmd/aws.sh @@ -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. # On rhel continue with the cloudapi test -if [[ $RESULTS == 1 ]] && [[ $ID != rhel ]]; then +if [[ $RESULTS == 1 ]]; then greenprint "๐Ÿ’š Success" exit 0 elif [[ $RESULTS != 1 ]]; then @@ -283,98 +283,4 @@ elif [[ $RESULTS != 1 ]]; then exit 1 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