-
Notifications
You must be signed in to change notification settings - Fork 79
Support uploading to IBM Cloud #1924
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| package ibmcloud | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
| "io" | ||
|
|
||
| "github.com/IBM/ibm-cos-sdk-go/aws" | ||
| "github.com/IBM/ibm-cos-sdk-go/aws/credentials" | ||
| "github.com/IBM/ibm-cos-sdk-go/aws/credentials/ibmiam" | ||
| "github.com/IBM/ibm-cos-sdk-go/aws/session" | ||
| "github.com/IBM/ibm-cos-sdk-go/service/s3/s3manager" | ||
|
|
||
| "github.com/osbuild/images/pkg/cloud" | ||
| ) | ||
|
|
||
| var _ = cloud.Uploader(&ibmcloudUploader{}) | ||
|
|
||
| type ibmcloudUploader struct { | ||
| region string | ||
| bucketName string | ||
| imageName string | ||
| credentials *Credentials | ||
| } | ||
|
|
||
| type Credentials struct { | ||
| AuthEndpoint string | ||
|
|
||
| // Static credentials | ||
| ApiKey string | ||
| Crn string | ||
|
|
||
| // Config credentials | ||
| Filename string | ||
| Profilename string | ||
|
|
||
| // Trusted profile credentials | ||
| TrustedProfileID string | ||
| CrTokenFilePath string | ||
| ServiceInstanceID string | ||
| } | ||
|
|
||
| func NewUploader(region string, bucketName string, imageName string, credentials *Credentials) (cloud.Uploader, error) { | ||
| return &ibmcloudUploader{ | ||
| region: region, | ||
| bucketName: bucketName, | ||
| imageName: imageName, | ||
| credentials: credentials, | ||
| }, nil | ||
| } | ||
|
|
||
| func (iu *ibmcloudUploader) Check(status io.Writer) error { | ||
| return nil | ||
| } | ||
|
|
||
| func (iu *ibmcloudUploader) UploadAndRegister(r io.Reader, uploadSize uint64, status io.Writer) (err error) { | ||
| fmt.Fprintf(status, "Uploading to IBM Cloud...\n") | ||
|
|
||
| endpoint := fmt.Sprintf("s3.%s.cloud-object-storage.appdomain.cloud", iu.region) | ||
| credentials, err := iu.getCredentials() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that it would be better to call this in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO, it would be a good candidate for the |
||
| if err != nil { | ||
| return err | ||
| } | ||
| conf := aws.NewConfig(). | ||
| WithRegion(iu.region). | ||
| WithEndpoint(endpoint). | ||
| WithCredentials(credentials). | ||
| WithS3ForcePathStyle(true) | ||
|
|
||
| session, err := session.NewSession(conf) | ||
| if err != nil { | ||
| return fmt.Errorf("Failed to create a session: %w", err) | ||
| } | ||
|
|
||
| uploader := s3manager.NewUploader(session) | ||
| _, err = uploader.Upload(&s3manager.UploadInput{ | ||
| Bucket: aws.String(iu.bucketName), | ||
| Key: aws.String(iu.imageName), | ||
| Body: r, | ||
| }) | ||
| if err != nil { | ||
| return fmt.Errorf("Failed to upload: %w", err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func (iu *ibmcloudUploader) getCredentials() (*credentials.Credentials, error) { | ||
| if iu.credentials.ApiKey != "" && iu.credentials.Crn != "" { | ||
| return ibmiam.NewStaticCredentials( | ||
| aws.NewConfig(), | ||
| iu.credentials.AuthEndpoint, | ||
| iu.credentials.ApiKey, | ||
| iu.credentials.Crn, | ||
| ), nil | ||
| } | ||
| if iu.credentials.Filename != "" && iu.credentials.Profilename != "" { | ||
| return ibmiam.NewConfigCredentials( | ||
| aws.NewConfig(), | ||
| iu.credentials.Filename, | ||
| iu.credentials.Profilename, | ||
| ), nil | ||
| } | ||
| if iu.credentials.TrustedProfileID != "" && iu.credentials.CrTokenFilePath != "" && iu.credentials.ServiceInstanceID != "" { | ||
| return ibmiam.NewTrustedProfileCredentialsCR( | ||
| aws.NewConfig(), | ||
| iu.credentials.AuthEndpoint, | ||
| iu.credentials.TrustedProfileID, | ||
| iu.credentials.CrTokenFilePath, | ||
| iu.credentials.ServiceInstanceID, | ||
| ), nil | ||
| } | ||
| return nil, errors.New("No usable credentials found") | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally we would do parts of the checks from UploadAndRegister() here too, like checking for the environment. Maybe via a common helper that is then used here and in UploadAndRegister() ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per discussion in #1921 (comment) , I am skipping the check for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the check only gets called when uploading as part of a build: https://github.com/osbuild/image-builder-cli/blob/392736dac329a3f6ccc6dccd4170b4f20a8f4c1b/cmd/image-builder/main.go#L405
But not called with
image-builder upload.