Add support for OCI upload provider

Signed-off-by: Roy Golan <rgolan@redhat.com>
This commit is contained in:
Roy Golan 2021-11-18 09:52:25 +02:00 committed by Sanne Raymaekers
parent d9051c23e6
commit bee932e222
18 changed files with 495 additions and 4 deletions

View file

@ -0,0 +1,104 @@
package main
import (
"crypto/rand"
"fmt"
"github.com/osbuild/osbuild-composer/internal/upload/oci"
"github.com/spf13/cobra"
"io/ioutil"
"math"
"math/big"
"os"
)
var (
tenancy string
region string
userID string
privateKeyFile string
fingerprint string
bucketName string
bucketNamespace string
fileName string
objectName string
compartment string
)
var uploadCmd = &cobra.Command{
Example: "This tool uses the $HOME/.oci/config file to create the OCI client and can be\noverridden using CLI flags.",
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
uploader, err := uploaderFromConfig()
if err != nil {
return err
}
file, err := os.Open(fileName)
if err != nil {
return err
}
defer file.Close()
imageID, err := uploader.Upload(objectName, bucketName, bucketNamespace, file, compartment, fileName)
if err != nil {
return fmt.Errorf("failed to upload the image: %v", err)
}
fmt.Printf("Image %s was uploaded and created successfully\n", imageID)
return nil
},
}
func main() {
i, _ := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
uploadCmd.Flags().StringVarP(&tenancy, "tenancy", "t", "", "target tenancy")
uploadCmd.Flags().StringVarP(&region, "region", "r", "", "target region")
uploadCmd.Flags().StringVarP(&userID, "user-id", "u", "", "user OCI ID")
uploadCmd.Flags().StringVarP(&bucketName, "bucket-name", "b", "", "target OCI bucket name")
uploadCmd.Flags().StringVarP(&bucketNamespace, "bucket-namespace", "", "", "target OCI bucket namespace")
uploadCmd.Flags().StringVarP(&fileName, "filename", "f", "", "image file to upload")
uploadCmd.Flags().StringVarP(&objectName, "object-name", "o", fmt.Sprintf("osbuild-upload-%v", i), "the target name of the uploaded object in the bucket")
uploadCmd.Flags().StringVarP(&privateKeyFile, "private-key", "p", "", "private key for authenticating OCI API requests")
uploadCmd.Flags().StringVarP(&fingerprint, "fingerprint", "", "", "the private key's fingerprint")
uploadCmd.Flags().StringVarP(&compartment, "compartment-id", "c", "", "the compartment ID of the target image")
_ = uploadCmd.MarkFlagRequired("bucket-name")
_ = uploadCmd.MarkFlagRequired("bucket-namespace")
_ = uploadCmd.MarkFlagRequired("compartment-id")
_ = uploadCmd.MarkFlagRequired("filename")
if err := uploadCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func uploaderFromConfig() (oci.Uploader, error) {
if privateKeyFile != "" {
if tenancy == "" || region == "" || userID == "" || fingerprint == "" {
return nil, fmt.Errorf("when suppling a private key the following args are mandatory as well:" +
" fingerprint, tenancy, region, and user-id")
}
pk, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
return nil, fmt.Errorf("failed to read private key file %w", err)
}
uploader, err := oci.NewClient(
&oci.ClientParams{
Tenancy: tenancy,
User: userID,
Region: region,
PrivateKey: string(pk),
Fingerprint: fingerprint,
})
if err != nil {
return nil, fmt.Errorf("failed to create an OCI client %w", err)
}
return uploader, nil
}
fmt.Printf("Creating an uploader from default config\n")
uploader, err := oci.NewClient(nil)
if err != nil {
return nil, err
}
return uploader, nil
}

View file

@ -2,12 +2,18 @@ package main
import (
"context"
"crypto/rand"
"fmt"
"io/ioutil"
"log"
"math"
"math/big"
"os"
"path"
"strings"
"github.com/osbuild/osbuild-composer/internal/upload/oci"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
@ -517,6 +523,49 @@ func (impl *OSBuildJobImpl) Run(job worker.Job) error {
ImageName: args.Targets[0].ImageName,
}))
osbuildJobResult.Success = true
osbuildJobResult.UploadStatus = "success"
case *target.OCITargetOptions:
// create an ociClient uploader with a valid storage client
var ociClient oci.Client
ociClient, err = oci.NewClient(&oci.ClientParams{
User: options.User,
Region: options.Region,
Tenancy: options.Tenancy,
Fingerprint: options.Fingerprint,
PrivateKey: options.PrivateKey,
})
if err != nil {
appendTargetError(osbuildJobResult, fmt.Errorf("failed to create an OCI uploder: %w", err))
return nil
}
log.Print("[OCI] 🔑 Logged in OCI")
log.Print("[OCI] ⬆ Uploading the image")
file, err := os.Open(path.Join(outputDirectory, exportPath, options.FileName))
if err != nil {
appendTargetError(osbuildJobResult, fmt.Errorf("failed to create an OCI uploder: %w", err))
return nil
}
defer file.Close()
i, _ := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
imageID, err := ociClient.Upload(
fmt.Sprintf("osbuild-upload-%d", i),
options.Bucket,
options.Namespace,
file,
options.Compartment,
args.Targets[0].ImageName,
)
if err != nil {
appendTargetError(osbuildJobResult, fmt.Errorf("failed to upload the image: %w", err))
return nil
}
log.Print("[OCI] 🎉 Image uploaded and registered!")
osbuildJobResult.TargetResults = append(
osbuildJobResult.TargetResults,
target.NewOCITargetResult(&target.OCITargetResultOptions{ImageID: imageID}),
)
osbuildJobResult.Success = true
osbuildJobResult.UploadStatus = "success"
default: