Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/mapt/cmd/ibmcloud/hosts/ibm-power.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,14 @@ func ibmPowerDestroy() *cobra.Command {
DebugLevel: viper.GetUint(params.DebugLevel),
Serverless: viper.IsSet(params.Serverless),
ForceDestroy: viper.IsSet(params.ForceDestroy),
KeepState: viper.IsSet(params.KeepState),
})
},
}
flagSet := pflag.NewFlagSet(params.DestroyCmdName, pflag.ExitOnError)
flagSet.Bool(params.Serverless, false, params.ServerlessDesc)
flagSet.Bool(params.ForceDestroy, false, params.ForceDestroyDesc)
flagSet.Bool(params.KeepState, false, params.KeepStateDesc)
c.PersistentFlags().AddFlagSet(flagSet)
return c
}
2 changes: 2 additions & 0 deletions cmd/mapt/cmd/ibmcloud/hosts/ibm-z.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ func ibmZDestroy() *cobra.Command {
DebugLevel: viper.GetUint(params.DebugLevel),
Serverless: viper.IsSet(params.Serverless),
ForceDestroy: viper.IsSet(params.ForceDestroy),
KeepState: viper.IsSet(params.KeepState),
})
},
}
flagSet := pflag.NewFlagSet(params.DestroyCmdName, pflag.ExitOnError)
flagSet.Bool(params.Serverless, false, params.ServerlessDesc)
flagSet.Bool(params.ForceDestroy, false, params.ForceDestroyDesc)
flagSet.Bool(params.KeepState, false, params.KeepStateDesc)
c.PersistentFlags().AddFlagSet(flagSet)
return c
}
47 changes: 47 additions & 0 deletions docs/ibmcloud/ibm-power.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ On first boot, cloud-init automatically configures the PowerVS instance for on-p
| `IBMCLOUD_ACCOUNT` | yes | IBM Cloud account ID |
| `IBMCLOUD_API_KEY` | yes | IBM Cloud API key |
| `IC_REGION` | yes | IBM Cloud region (e.g. `us-south`, `us-east`) |
| `IBMCLOUD_COS_ACCESS_KEY_ID` | only with S3 `--backed-url` | HMAC access key for IBM Cloud Object Storage |
| `IBMCLOUD_COS_SECRET_ACCESS_KEY` | only with S3 `--backed-url` | HMAC secret key for IBM Cloud Object Storage |
| `IBMCLOUD_COS_ENDPOINT` | no | COS S3 endpoint (defaults to `s3.<region>.cloud-object-storage.appdomain.cloud`) |

## Create

Expand Down Expand Up @@ -134,6 +137,34 @@ podman run -d --name ibm-power \
--otel-auth-token <uuid-token>
```

## Using IBM Cloud Object Storage as S3 backend

To store Pulumi state in IBM COS instead of a local file, create [HMAC credentials](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-uhc-hmac-credentials-main) for your COS instance and pass an `s3://` backed URL:

```bash
podman run -d --name ibm-power \
-v ${PWD}:/workspace:z \
-e IBMCLOUD_API_KEY=XXX \
-e IBMCLOUD_ACCOUNT=XXX \
-e IC_REGION=us-south \
-e IBMCLOUD_COS_ACCESS_KEY_ID=XXX \
-e IBMCLOUD_COS_SECRET_ACCESS_KEY=XXX \
quay.io/redhat-developer/mapt:v0.8.0 ibmcloud ibm-power create \
--project-name ibm-power \
--backed-url s3://my-cos-bucket \
--conn-details-output /workspace \
--workspace-id <workspace-id> \
--pi-private-subnet-id <private-subnet-id>
```

An HTTPS endpoint URL is also supported as `--backed-url`, with the bucket name in the path:

```
--backed-url https://s3.us-south.cloud-object-storage.appdomain.cloud/my-cos-bucket
```

The COS endpoint and `PULUMI_BACKEND_URL` are constructed automatically from the region and bucket name.

## Destroy

```bash
Expand All @@ -144,4 +175,20 @@ podman run -d --name ibm-power \
quay.io/redhat-developer/mapt:v0.8.0 ibmcloud ibm-power destroy \
--project-name ibm-power \
--backed-url file:///workspace
```

By default, destroy removes the Pulumi state files from the backend after a successful destroy. Use `--keep-state` to preserve them:

```bash
podman run -d --name ibm-power \
-v ${PWD}:/workspace:z \
-e IBMCLOUD_API_KEY=XXX \
-e IBMCLOUD_ACCOUNT=XXX \
-e IC_REGION=us-south \
-e IBMCLOUD_COS_ACCESS_KEY_ID=XXX \
-e IBMCLOUD_COS_SECRET_ACCESS_KEY=XXX \
quay.io/redhat-developer/mapt:v0.8.0 ibmcloud ibm-power destroy \
--project-name ibm-power \
--backed-url s3://my-cos-bucket \
--keep-state
```
46 changes: 46 additions & 0 deletions docs/ibmcloud/ibm-z.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ Two networking modes are supported:
| `IBMCLOUD_API_KEY` | yes | IBM Cloud API key |
| `IC_REGION` | yes | IBM Cloud region (e.g. `us-south`, `us-east`) |
| `IC_ZONE` | only without `--subnet-id` | Availability zone (e.g. `us-south-2`) |
| `IBMCLOUD_COS_ACCESS_KEY_ID` | only with S3 `--backed-url` | HMAC access key for IBM Cloud Object Storage |
| `IBMCLOUD_COS_SECRET_ACCESS_KEY` | only with S3 `--backed-url` | HMAC secret key for IBM Cloud Object Storage |
| `IBMCLOUD_COS_ENDPOINT` | no | COS S3 endpoint (defaults to `s3.<region>.cloud-object-storage.appdomain.cloud`) |

## Create

Expand Down Expand Up @@ -112,6 +115,33 @@ podman run -d --name ibm-z \
--otel-auth-token <uuid-token>
```

## Using IBM Cloud Object Storage as S3 backend

To store Pulumi state in IBM COS instead of a local file, create [HMAC credentials](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-uhc-hmac-credentials-main) for your COS instance and pass an `s3://` backed URL:

```bash
podman run -d --name ibm-z \
-v ${PWD}:/workspace:z \
-e IBMCLOUD_API_KEY=XXX \
-e IBMCLOUD_ACCOUNT=XXX \
-e IC_REGION=us-south \
-e IC_ZONE=us-south-2 \
-e IBMCLOUD_COS_ACCESS_KEY_ID=XXX \
-e IBMCLOUD_COS_SECRET_ACCESS_KEY=XXX \
quay.io/redhat-developer/mapt:v0.8.0 ibmcloud ibm-z create \
--project-name ibm-z \
--backed-url s3://my-cos-bucket \
--conn-details-output /workspace
```

An HTTPS endpoint URL is also supported as `--backed-url`, with the bucket name in the path:

```
--backed-url https://s3.us-south.cloud-object-storage.appdomain.cloud/my-cos-bucket
```

The COS endpoint and `PULUMI_BACKEND_URL` are constructed automatically from the region and bucket name.

## Destroy

```bash
Expand All @@ -123,3 +153,19 @@ podman run -d --name ibm-z \
--project-name ibm-z \
--backed-url file:///workspace
```

By default, destroy removes the Pulumi state files from the backend after a successful destroy. Use `--keep-state` to preserve them:

```bash
podman run -d --name ibm-z \
-v ${PWD}:/workspace:z \
-e IBMCLOUD_API_KEY=XXX \
-e IBMCLOUD_ACCOUNT=XXX \
-e IC_REGION=us-south \
-e IBMCLOUD_COS_ACCESS_KEY_ID=XXX \
-e IBMCLOUD_COS_SECRET_ACCESS_KEY=XXX \
quay.io/redhat-developer/mapt:v0.8.0 ibmcloud ibm-z destroy \
--project-name ibm-z \
--backed-url s3://my-cos-bucket \
--keep-state
```
8 changes: 6 additions & 2 deletions pkg/manager/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type Context struct {
}

type Provider interface {
Init(ctx context.Context, backedURL string) error
Init(ctx context.Context, backedURL string) (string, error)
DefaultHostingPlace() (*string, error)
}

Expand Down Expand Up @@ -110,9 +110,13 @@ func Init(ca *ContextArgs, provider Provider) (*Context, error) {
c.targetHostingPlace = *hp
}
// Manage
if err := provider.Init(ctx, ca.BackedURL); err != nil {
resolvedURL, err := provider.Init(ctx, ca.BackedURL)
if err != nil {
return nil, err
}
if resolvedURL != "" {
c.backedURL = resolvedURL
}
// Manage integrations
if err := manageIntegration(c, ca); err != nil {
return nil, err
Expand Down
7 changes: 5 additions & 2 deletions pkg/provider/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ const pulumiLocksPath = ".pulumi/locks"

type AWS struct{}

func (a *AWS) Init(ctx context.Context, backedURL string) error {
func (a *AWS) Init(ctx context.Context, backedURL string) (string, error) {
// Manage remote state requirements, if backedURL
// is on a different region we need to change to that region
// in order to interact with the state
return manageRemoteState(ctx, backedURL)
return "", manageRemoteState(ctx, backedURL)
}

func (a *AWS) DefaultHostingPlace() (*string, error) {
Expand Down Expand Up @@ -217,6 +217,9 @@ func parseS3BackedURL(mCtx *mc.Context) (*string, *string, error) {
return nil, nil, fmt.Errorf("failed to parse S3 URI: %w", err)
}
key := strings.TrimPrefix(u.Path, "/")
if key == "" {
return nil, nil, fmt.Errorf("invalid S3 URI %q: missing object key after bucket name", mCtx.BackedURL())
}
return &u.Host, &key, nil
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/provider/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ func Provider() *Azure {
return &Azure{}
}

func (a *Azure) Init(ctx context.Context, backedURL string) error {
func (a *Azure) Init(ctx context.Context, backedURL string) (string, error) {
setAZIdentityEnvs()
return nil
return "", nil
}

func (a *Azure) DefaultHostingPlace() (*string, error) {
Expand Down
5 changes: 4 additions & 1 deletion pkg/provider/ibmcloud/action/ibm-power/ibm-power.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ func Destroy(mCtxArgs *mc.ContextArgs) (err error) {
if err != nil {
return err
}
return ibmcloudp.Destroy(mCtx, stackIBMPowerVS)
if err := ibmcloudp.DestroyStack(mCtx, stackIBMPowerVS); err != nil {
return err
}
return ibmcloudp.CleanupState(mCtx)
}

func (r *pwRequest) deploy(ctx *pulumi.Context) error {
Expand Down
5 changes: 4 additions & 1 deletion pkg/provider/ibmcloud/action/ibm-z/ibm-z.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ func Destroy(mCtxArgs *mc.ContextArgs) (err error) {
if err != nil {
return err
}
return ibmcloudp.Destroy(mCtx, stackIBMS390)
if err := ibmcloudp.DestroyStack(mCtx, stackIBMS390); err != nil {
return err
}
return ibmcloudp.CleanupState(mCtx)
}

func (r *zRequest) deploy(ctx *pulumi.Context) error {
Expand Down
9 changes: 9 additions & 0 deletions pkg/provider/ibmcloud/constants/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package constants

const (
EnvIBMCloudAccount = "IBMCLOUD_ACCOUNT"
EnvIBMCloudAPIKey = "IBMCLOUD_API_KEY"
EnvIBMCosAccessKeyID = "IBMCLOUD_COS_ACCESS_KEY_ID"
EnvIBMCosSecretAccessKey = "IBMCLOUD_COS_SECRET_ACCESS_KEY"
EnvIBMCosEndpoint = "IBMCLOUD_COS_ENDPOINT"
)
5 changes: 3 additions & 2 deletions pkg/provider/ibmcloud/data/piimages.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/IBM/go-sdk-core/v5/core"
mc "github.com/redhat-developer/mapt/pkg/manager/context"
icConstants "github.com/redhat-developer/mapt/pkg/provider/ibmcloud/constants"
)

const powerURLRegex = "%s.power-iaas.cloud.ibm.com"
Expand Down Expand Up @@ -45,9 +46,9 @@ func GetImage(mCtx *mc.Context, args *PiImageArgs) (*string, error) {
func piImagesClient(mCtx *mc.Context, cloudInstanceId string) (*v.IBMPIImageClient, error) {
options := &ps.IBMPIOptions{
Authenticator: &core.IamAuthenticator{
ApiKey: os.Getenv("IBMCLOUD_API_KEY"),
ApiKey: os.Getenv(icConstants.EnvIBMCloudAPIKey),
},
UserAccount: os.Getenv("IBMCLOUD_ACCOUNT"),
UserAccount: os.Getenv(icConstants.EnvIBMCloudAccount),
Zone: os.Getenv("IC_ZONE"),
URL: powerURL(os.Getenv("IC_REGION")),
Debug: mCtx.Debug(),
Expand Down
3 changes: 2 additions & 1 deletion pkg/provider/ibmcloud/data/vpcimages.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/IBM/vpc-go-sdk/vpcv1"

"github.com/IBM/go-sdk-core/v5/core"
icConstants "github.com/redhat-developer/mapt/pkg/provider/ibmcloud/constants"
)

const (
Expand Down Expand Up @@ -64,7 +65,7 @@ func vpcService() (*vpcv1.VpcV1, error) {
}
return vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
Authenticator: &core.IamAuthenticator{
ApiKey: os.Getenv("IBMCLOUD_API_KEY"),
ApiKey: os.Getenv(icConstants.EnvIBMCloudAPIKey),
},
URL: serviceURL,
})
Expand Down
Loading