-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
564 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "clevercloud_docker Resource - terraform-provider-clevercloud" | ||
subcategory: "" | ||
description: |- | ||
Manage Docker https:// applications. | ||
See Docker product https://www.clever-cloud.com/doc/getting-started/by-language/docker/ specification. | ||
--- | ||
|
||
# clevercloud_docker (Resource) | ||
|
||
Manage [Docker](https://) applications. | ||
|
||
See [Docker product](https://www.clever-cloud.com/doc/getting-started/by-language/docker/) specification. | ||
|
||
|
||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `biggest_flavor` (String) Biggest intance flavor, if different from smallest, enable autoscaling | ||
- `max_instance_count` (Number) Maximum instance count, if different from min value, enable autoscaling | ||
- `min_instance_count` (Number) Minimum instance count | ||
- `name` (String) Application name | ||
- `smallest_flavor` (String) Smallest instance flavor | ||
|
||
### Optional | ||
|
||
- `additional_vhosts` (List of String) Add custom hostname in addition to the default one, see [documentation](https://www.clever-cloud.com/doc/administrate/domain-names/) | ||
- `app_folder` (String) Folder in which the application is located (inside the git repository) | ||
- `build_flavor` (String) Use dedicated instance with given flavor for build step | ||
- `container_port` (Number) Set to custom HTTP port if your Docker container runs on custom port | ||
- `container_port_tcp` (Number) Set to custom TCP port if your Docker container runs on custom port. | ||
- `daemon_socket_mount` (Boolean) Set to true to access the host Docker socket from inside your container | ||
- `dependencies` (Set of String) A list of application or addons requires to run this application. | ||
Can be either app_xxx or postgres_yyy ID format | ||
- `deployment` (Block, Optional) (see [below for nested schema](#nestedblock--deployment)) | ||
- `description` (String) Application description | ||
- `dockerfile` (String) The name of the Dockerfile to build | ||
- `enable_ipv6` (Boolean) Activate the support of IPv6 with an IPv6 subnet int the docker daemon | ||
- `environment` (Map of String, Sensitive) Environment variables injected into the application | ||
- `hooks` (Block, Optional) (see [below for nested schema](#nestedblock--hooks)) | ||
- `redirect_https` (Boolean) Redirect client from plain to TLS port | ||
- `region` (String) Geographical region where the database will be deployed | ||
- `registry_password` (String) The password of your username | ||
- `registry_url` (String) The server of your private registry (optional). Docker’s public registry | ||
- `registry_user` (String) The username to login to a private registry | ||
- `sticky_sessions` (Boolean) Enable sticky sessions, use it when your client sessions are instances scoped | ||
|
||
### Read-Only | ||
|
||
- `deploy_url` (String) Git URL used to push source code | ||
- `id` (String) Unique identifier generated during application creation | ||
- `vhost` (String) Default vhost to access your app | ||
|
||
<a id="nestedblock--deployment"></a> | ||
### Nested Schema for `deployment` | ||
|
||
Optional: | ||
|
||
- `commit` (String) Deploy application on the given commit/tag | ||
- `repository` (String) | ||
|
||
|
||
<a id="nestedblock--hooks"></a> | ||
### Nested Schema for `hooks` | ||
|
||
Optional: | ||
|
||
- `post_build` (String) [CC_POST_BUILD_HOOK](https://www.clever-cloud.com/doc/develop/build-hooks/#post-build-cc_post_build_hook) | ||
- `pre_build` (String) [CC_PRE_BUILD_HOOK](https://www.clever-cloud.com/doc/develop/build-hooks/#pre-build-cc_pre_build_hook) | ||
- `pre_run` (String) [CC_PRE_RUN_HOOK](https://www.clever-cloud.com/doc/develop/build-hooks/#pre-run-cc_pre_run_hook) | ||
- `run_failed` (String) [CC_RUN_FAILED_HOOK](https://www.clever-cloud.com/doc/develop/build-hooks/#run-succeeded-cc_run_succeeded_hook-or-failed-cc_run_failed_hook) | ||
- `run_succeed` (String) [CC_RUN_SUCCEEDED_HOOK](https://www.clever-cloud.com/doc/develop/build-hooks/#run-succeeded-cc_run_succeeded_hook-or-failed-cc_run_failed_hook) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package docker | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"go.clever-cloud.dev/client" | ||
) | ||
|
||
type ResourceDocker struct { | ||
cc *client.Client | ||
org string | ||
} | ||
|
||
func NewResourceDocker() func() resource.Resource { | ||
return func() resource.Resource { | ||
return &ResourceDocker{} | ||
} | ||
} | ||
|
||
func (r *ResourceDocker) Metadata(ctx context.Context, req resource.MetadataRequest, res *resource.MetadataResponse) { | ||
res.TypeName = req.ProviderTypeName + "_docker" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Manage [Docker](https://) applications. | ||
|
||
See [Docker product](https://www.clever-cloud.com/doc/getting-started/by-language/docker/) specification. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
package docker | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
"go.clever-cloud.com/terraform-provider/pkg" | ||
"go.clever-cloud.com/terraform-provider/pkg/application" | ||
"go.clever-cloud.com/terraform-provider/pkg/provider" | ||
"go.clever-cloud.com/terraform-provider/pkg/tmp" | ||
) | ||
|
||
// Weird behaviour, but TF can ask for a Resource without having configured a Provider (maybe for Meta and Schema) | ||
// So we need to handle the case there is no ProviderData | ||
func (r *ResourceDocker) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
tflog.Debug(ctx, "ResourceDocker.Configure()") | ||
|
||
// Prevent panic if the provider has not been configured. | ||
if req.ProviderData == nil { | ||
return | ||
} | ||
|
||
provider, ok := req.ProviderData.(provider.Provider) | ||
if ok { | ||
r.cc = provider.Client() | ||
r.org = provider.Organization() | ||
} | ||
|
||
tflog.Debug(ctx, "AFTER CONFIGURED", map[string]interface{}{"cc": r.cc == nil, "org": r.org}) | ||
} | ||
|
||
// Create a new resource | ||
func (r *ResourceDocker) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
plan := Docker{} | ||
|
||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
instance := application.LookupInstance(ctx, r.cc, "docker", "Docker", resp.Diagnostics) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
vhosts := []string{} | ||
resp.Diagnostics.Append(plan.AdditionalVHosts.ElementsAs(ctx, &vhosts, false)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
environment := plan.toEnv(ctx, resp.Diagnostics) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
createAppReq := application.CreateReq{ | ||
Client: r.cc, | ||
Organization: r.org, | ||
Application: tmp.CreateAppRequest{ | ||
Name: plan.Name.ValueString(), | ||
Deploy: "git", | ||
Description: plan.Description.ValueString(), | ||
InstanceType: instance.Type, | ||
InstanceVariant: instance.Variant.ID, | ||
InstanceVersion: instance.Version, | ||
BuildFlavor: plan.BuildFlavor.ValueString(), | ||
MinFlavor: plan.SmallestFlavor.ValueString(), | ||
MaxFlavor: plan.BiggestFlavor.ValueString(), | ||
MinInstances: plan.MinInstanceCount.ValueInt64(), | ||
MaxInstances: plan.MaxInstanceCount.ValueInt64(), | ||
StickySessions: plan.StickySessions.ValueBool(), | ||
ForceHttps: application.FromForceHTTPS(plan.RedirectHTTPS.ValueBool()), | ||
Zone: plan.Region.ValueString(), | ||
CancelOnPush: false, | ||
}, | ||
Environment: environment, | ||
VHosts: vhosts, | ||
Deployment: plan.toDeployment(), | ||
} | ||
|
||
createAppRes, diags := application.CreateApp(ctx, createAppReq) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
tflog.Debug(ctx, "BUILD FLAVOR RES"+createAppRes.Application.BuildFlavor.Name, map[string]interface{}{}) | ||
plan.ID = pkg.FromStr(createAppRes.Application.ID) | ||
plan.DeployURL = pkg.FromStr(createAppRes.Application.DeployURL) | ||
plan.VHost = pkg.FromStr(createAppRes.Application.Vhosts[0].Fqdn) | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} | ||
|
||
// Read resource information | ||
func (r *ResourceDocker) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
var state Docker | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
appPHP, diags := application.ReadApp(ctx, r.cc, r.org, state.ID.ValueString()) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
if appPHP.AppIsDeleted { | ||
resp.State.RemoveResource(ctx) | ||
return | ||
} | ||
|
||
state.Name = pkg.FromStr(appPHP.App.Name) | ||
state.Description = pkg.FromStr(appPHP.App.Description) | ||
state.MinInstanceCount = pkg.FromI(int64(appPHP.App.Instance.MinInstances)) | ||
state.MaxInstanceCount = pkg.FromI(int64(appPHP.App.Instance.MaxInstances)) | ||
state.SmallestFlavor = pkg.FromStr(appPHP.App.Instance.MinFlavor.Name) | ||
state.BiggestFlavor = pkg.FromStr(appPHP.App.Instance.MaxFlavor.Name) | ||
state.Region = pkg.FromStr(appPHP.App.Zone) | ||
state.DeployURL = pkg.FromStr(appPHP.App.DeployURL) | ||
|
||
if appPHP.App.SeparateBuild { | ||
state.BuildFlavor = pkg.FromStr(appPHP.App.BuildFlavor.Name) | ||
} else { | ||
state.BuildFlavor = types.StringNull() | ||
} | ||
|
||
vhosts := pkg.Map(appPHP.App.Vhosts, func(vhost tmp.Vhost) string { | ||
return vhost.Fqdn | ||
}) | ||
hasDefaultVHost := pkg.HasSome(vhosts, func(vhost string) bool { | ||
return pkg.VhostCleverAppsRegExp.MatchString(vhost) | ||
}) | ||
if hasDefaultVHost { | ||
cleverapps := *pkg.First(vhosts, func(vhost string) bool { | ||
return pkg.VhostCleverAppsRegExp.MatchString(vhost) | ||
}) | ||
state.VHost = pkg.FromStr(cleverapps) | ||
} else { | ||
state.VHost = types.StringNull() | ||
} | ||
|
||
vhostsWithoutDefault := pkg.Filter(vhosts, func(vhost string) bool { | ||
ok := pkg.VhostCleverAppsRegExp.MatchString(vhost) | ||
return !ok | ||
}) | ||
if len(vhostsWithoutDefault) > 0 { | ||
state.AdditionalVHosts = pkg.FromListString(vhostsWithoutDefault) | ||
} else { | ||
state.AdditionalVHosts = types.ListNull(types.StringType) | ||
} | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, state)...) | ||
} | ||
|
||
// Update resource | ||
func (r *ResourceDocker) Update(ctx context.Context, req resource.UpdateRequest, res *resource.UpdateResponse) { | ||
// TODO | ||
} | ||
|
||
// Delete resource | ||
func (r *ResourceDocker) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var state Docker | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
tflog.Debug(ctx, "DOCKER DELETE", map[string]interface{}{"state": state}) | ||
|
||
res := tmp.DeleteApp(ctx, r.cc, r.org, state.ID.ValueString()) | ||
if res.IsNotFoundError() { | ||
resp.State.RemoveResource(ctx) | ||
return | ||
} | ||
if res.HasError() { | ||
resp.Diagnostics.AddError("failed to delete app", res.Error().Error()) | ||
return | ||
} | ||
|
||
resp.State.RemoveResource(ctx) | ||
} | ||
|
||
// Import resource | ||
func (r *ResourceDocker) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
// Save the import identifier in the id attribute | ||
// and call Read() to fill fields | ||
attr := path.Root("id") | ||
resource.ImportStatePassthroughID(ctx, attr, req, resp) | ||
} |
Oops, something went wrong.