Skip to content

Commit

Permalink
Merge pull request #10 from mittwald/feature/cronjob
Browse files Browse the repository at this point in the history
Add support for "mittwald_cronjob" resource
  • Loading branch information
martin-helmich authored Nov 27, 2023
2 parents 1251d65 + c0e5a10 commit 310e300
Show file tree
Hide file tree
Showing 17 changed files with 714 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This provider offers the following resources:
- [`mittwald_project`](./docs/resources/project.md)
- [`mittwald_app`](./docs/resources/app.md)
- [`mittwald_mysql_database`](./docs/resources/mysql_database.md)
- [`mittwald_cronjob`](./docs/resources/cronjob.md)

and the following data sources:

Expand All @@ -27,7 +28,6 @@ Coming soon:

- `mittwald_mysql_user`
- `mittwald_redis_database`
- `mittwald_cronjob`
- `mittwald_ssh_user`
- `mittwald_ingress`
- `mittwald_dns_zone`
Expand Down
7 changes: 7 additions & 0 deletions api/mittwaldv2/client_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ type ClientBuilder interface {
Project() ProjectClient
App() AppClient
Database() DatabaseClient
Cronjob() CronjobClient
}

type clientBuilder struct {
Expand All @@ -27,3 +28,9 @@ func (b *clientBuilder) App() AppClient {
client: b.internalClient,
}
}

func (b *clientBuilder) Cronjob() CronjobClient {
return &cronjobClient{
client: b.internalClient,
}
}
70 changes: 70 additions & 0 deletions api/mittwaldv2/client_cronjob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package mittwaldv2

import (
"context"
"fmt"
"github.com/google/uuid"
)

type CronjobClient interface {
GetCronjob(ctx context.Context, cronjobID string) (*DeMittwaldV1CronjobCronjob, error)
CreateCronjob(ctx context.Context, projectID string, body CronjobCreateCronjobJSONRequestBody) (string, error)
UpdateCronjob(ctx context.Context, cronjobID string, body CronjobUpdateCronjobJSONRequestBody) error
DeleteCronjob(ctx context.Context, cronjobID string) error
}

type cronjobClient struct {
client ClientWithResponsesInterface
}

func (c *cronjobClient) GetCronjob(ctx context.Context, cronjobID string) (*DeMittwaldV1CronjobCronjob, error) {
resp, err := c.client.CronjobGetCronjobWithResponse(ctx, uuid.MustParse(cronjobID))
if err != nil {
return nil, fmt.Errorf("error getting cronjob: %w", err)
}

if resp.JSON200 == nil {
return nil, errUnexpectedStatus(resp.StatusCode(), resp.Body)
}

return resp.JSON200, nil
}

func (c *cronjobClient) CreateCronjob(ctx context.Context, projectID string, body CronjobCreateCronjobJSONRequestBody) (string, error) {
resp, err := c.client.CronjobCreateCronjobWithResponse(ctx, uuid.MustParse(projectID), body)
if err != nil {
return "", fmt.Errorf("error creating cronjob: %w", err)
}

if resp.JSON201 == nil {
return "", errUnexpectedStatus(resp.StatusCode(), resp.Body)
}

return resp.JSON201.Id.String(), nil
}

func (c *cronjobClient) DeleteCronjob(ctx context.Context, cronjobID string) error {
resp, err := c.client.CronjobDeleteCronjobWithResponse(ctx, uuid.MustParse(cronjobID))
if err != nil {
return fmt.Errorf("error deleting cronjob: %w", err)
}

if resp.StatusCode() != 204 {
return errUnexpectedStatus(resp.StatusCode(), resp.Body)
}

return nil
}

func (c *cronjobClient) UpdateCronjob(ctx context.Context, cronjobID string, body CronjobUpdateCronjobJSONRequestBody) error {
resp, err := c.client.CronjobUpdateCronjobWithResponse(ctx, uuid.MustParse(cronjobID), body)
if err != nil {
return fmt.Errorf("error updating cronjob: %w", err)
}

if resp.JSON200 == nil {
return errUnexpectedStatus(resp.StatusCode(), resp.Body)
}

return nil
}
14 changes: 14 additions & 0 deletions api/mittwaldv2/mittwald.additional.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package mittwaldv2

import "encoding/json"

// These types were apparently not generated by oapi-codegen, so we need to
// define them ourselves.

Expand All @@ -11,3 +13,15 @@ type AppPatchInstallationSystemSoftwareItem = struct {
UpdatePolicy *DeMittwaldV1AppSystemSoftwareUpdatePolicy `json:"updatePolicy,omitempty"`
}
type AppPatchInstallationSystemSoftware = map[string]AppPatchInstallationSystemSoftwareItem

func (t *CronjobUpdateCronjobJSONBody_Destination) FromDeMittwaldV1CronjobCronjobUrl(v DeMittwaldV1CronjobCronjobUrl) error {
b, err := json.Marshal(v)
t.union = b
return err
}

func (t *CronjobUpdateCronjobJSONBody_Destination) FromDeMittwaldV1CronjobCronjobCommand(v DeMittwaldV1CronjobCronjobCommand) error {
b, err := json.Marshal(v)
t.union = b
return err
}
70 changes: 70 additions & 0 deletions docs/resources/cronjob.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "mittwald_cronjob Resource - terraform-provider-mittwald"
subcategory: ""
description: |-
This resource models a cron job.
---

# mittwald_cronjob (Resource)

This resource models a cron job.

## Example Usage

```terraform
resource "mittwald_cronjob" "demo" {
project_id = mittwald_project.foobar.id
app_id = mittwald_app.wordpress.id
interval = "*/5 * * * *"
description = "Demo Cronjob"
destination = {
command = {
interpreter = "php"
path = "/html"
arguments = ["-r", "echo 'Hello World';"]
}
}
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `app_id` (String) The ID of the app the cron job belongs to
- `description` (String) Description for your cron job
- `destination` (Attributes) Models the action to be executed by the cron job. Exactly one of `url` or `command` must be set. (see [below for nested schema](#nestedatt--destination))
- `interval` (String) The interval of the cron job; this should be a cron expression
- `project_id` (String) The ID of the project the cron job belongs to

### Optional

- `email` (String) The email address to send the cron job's output to

### Read-Only

- `id` (String) The generated cron job ID

<a id="nestedatt--destination"></a>
### Nested Schema for `destination`

Optional:

- `command` (Attributes) (see [below for nested schema](#nestedatt--destination--command))
- `url` (String) The URL that should be requested by the cron job

<a id="nestedatt--destination--command"></a>
### Nested Schema for `destination.command`

Required:

- `interpreter` (String) The interpreter to use for the command. Must be a valid path to an executable within the project environment (typically, `/bin/bash` or `/usr/bin/php` should work).
- `path` (String) The path to the file to run. Must be a valid path to an executable file within the project environment.

Optional:

- `parameters` (List of String) A list of parameters to pass to the command. Each parameter must be a valid string.
15 changes: 15 additions & 0 deletions examples/resources/mittwald_cronjob/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "mittwald_cronjob" "demo" {
project_id = mittwald_project.foobar.id
app_id = mittwald_app.wordpress.id

interval = "*/5 * * * *"
description = "Demo Cronjob"

destination = {
command = {
interpreter = "php"
path = "/html"
arguments = ["-r", "echo 'Hello World';"]
}
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.21

require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/alessio/shellescape v1.4.2
github.com/getkin/kin-openapi v0.120.0
github.com/google/uuid v1.4.0
github.com/hashicorp/terraform-plugin-docs v0.16.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjA
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0=
github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
Expand Down
2 changes: 2 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/mittwald/terraform-provider-mittwald/internal/provider/datasource/projectdatasource"
"github.com/mittwald/terraform-provider-mittwald/internal/provider/datasource/systemsoftwaredatasource"
"github.com/mittwald/terraform-provider-mittwald/internal/provider/resource/appresource"
"github.com/mittwald/terraform-provider-mittwald/internal/provider/resource/cronjobresource"
"github.com/mittwald/terraform-provider-mittwald/internal/provider/resource/mysqldatabaseresource"
"github.com/mittwald/terraform-provider-mittwald/internal/provider/resource/projectresource"
"os"
Expand Down Expand Up @@ -97,6 +98,7 @@ func (p *MittwaldProvider) Resources(_ context.Context) []func() resource.Resour
projectresource.New,
appresource.New,
mysqldatabaseresource.New,
cronjobresource.New,
}
}

Expand Down
20 changes: 20 additions & 0 deletions internal/provider/providerutil/err_diag.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ func ErrorToDiag(err error) func(d *diag.Diagnostics, summary string) {
}
}

type WrappedError[T any] struct {
diag *diag.Diagnostics
summary string
}

func (w *WrappedError[T]) Do(err error) {
if err != nil {
w.diag.AddError(w.summary, err.Error())
}
}

func (w *WrappedError[T]) DoVal(res T, err error) T {
w.Do(err)
return res
}

func Try[T any](d *diag.Diagnostics, summary string) *WrappedError[T] {
return &WrappedError[T]{d, summary}
}

func EmbedDiag[T any](resultValue T, resultDiag diag.Diagnostics) func(outDiag *diag.Diagnostics) T {
return func(out *diag.Diagnostics) T {
out.Append(resultDiag...)
Expand Down
11 changes: 11 additions & 0 deletions internal/provider/providerutil/uuid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package providerutil

import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework/diag"
)

func ParseUUID(in string, d *diag.Diagnostics) uuid.UUID {
return Try[uuid.UUID](d, "Invalid app ID").
DoVal(uuid.Parse(in))
}
Loading

0 comments on commit 310e300

Please sign in to comment.