-
Notifications
You must be signed in to change notification settings - Fork 31
Aliases: Add aliases deployment #32
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
708a344
1406a8f
ebffec1
4f8ce3f
a1e3672
7e170ad
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 |
---|---|---|
|
@@ -7,3 +7,4 @@ | |
terraform-provider-vercel | ||
.task/ | ||
Dist/ | ||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
) | ||
|
||
// CreateAliasRequest defines the request the Vercel API expects in order to create an alias. | ||
type CreateAliasRequest struct { | ||
Alias string `json:"alias"` | ||
} | ||
|
||
// CreateAlias creates an alias within Vercel. | ||
func (c *Client) CreateAlias(ctx context.Context, request CreateAliasRequest, deploymentID string, teamID string) (r AliasResponse, err error) { | ||
url := fmt.Sprintf("%s/v2/deployments/%s/aliases", c.baseURL, deploymentID) | ||
if teamID != "" { | ||
url = fmt.Sprintf("%s?teamId=%s", url, teamID) | ||
} | ||
payload := string(mustMarshal(request)) | ||
req, err := http.NewRequestWithContext( | ||
ctx, | ||
"POST", | ||
url, | ||
strings.NewReader(payload), | ||
) | ||
if err != nil { | ||
return r, err | ||
} | ||
|
||
tflog.Trace(ctx, "creating alias", map[string]interface{}{ | ||
"url": url, | ||
"payload": payload, | ||
}) | ||
err = c.doRequest(req, &r) | ||
if err != nil { | ||
return r, err | ||
} | ||
|
||
return r, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
) | ||
|
||
// DeleteAliasResponse defines the response the Vercel API returns when an alias is deleted. | ||
type DeleteAliasResponse struct { | ||
Status string `json:"status"` | ||
} | ||
|
||
// DeleteAlias deletes an alias within Vercel. | ||
func (c *Client) DeleteAlias(ctx context.Context, aliasUID string, teamID string) (r DeleteAliasResponse, err error) { | ||
url := fmt.Sprintf("%s/v2/aliases/%s", c.baseURL, aliasUID) | ||
req, err := http.NewRequest( | ||
"DELETE", | ||
url, | ||
nil, | ||
) | ||
if err != nil { | ||
return r, err | ||
} | ||
|
||
// Add query parameters | ||
q := req.URL.Query() | ||
if teamID != "" { | ||
q.Add("teamId", teamID) | ||
} | ||
req.URL.RawQuery = q.Encode() | ||
|
||
tflog.Trace(ctx, "deleting alias", map[string]interface{}{ | ||
"url": url, | ||
}) | ||
err = c.doRequest(req, &r) | ||
if err != nil { | ||
return r, fmt.Errorf("url: %s, err: %s", url, err) | ||
} | ||
|
||
return r, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
) | ||
|
||
// AliasResponse defines the response the Vercel API returns for an alias. | ||
type AliasResponse struct { | ||
UID string `json:"uid"` | ||
Alias string `json:"alias"` | ||
DeploymentId string `json:"deploymentId"` | ||
} | ||
|
||
// GetAlias retrieves information about an existing alias from vercel. | ||
func (c *Client) GetAlias(ctx context.Context, aliasID, teamID string) (r AliasResponse, err error) { | ||
url := fmt.Sprintf("%s/v3/aliases/%s", c.baseURL, aliasID) | ||
if teamID != "" { | ||
url = fmt.Sprintf("%s?teamId=%s", url, teamID) | ||
} | ||
req, err := http.NewRequestWithContext( | ||
ctx, | ||
"GET", | ||
url, | ||
nil, | ||
) | ||
if err != nil { | ||
return r, fmt.Errorf("creating request: %s", err) | ||
} | ||
tflog.Trace(ctx, "getting alias", map[string]interface{}{ | ||
"url": url, | ||
}) | ||
err = c.doRequest(req, &r) | ||
if err != nil { | ||
return r, err | ||
} | ||
return r, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package client | |
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
|
@@ -57,6 +58,10 @@ func (c *Client) doRequest(req *http.Request, v interface{}) error { | |
errorResponse.RawMessage = responseBody | ||
return errorResponse | ||
} | ||
if resp.StatusCode == 204 { | ||
//204 means "no content", we are treating it as an error | ||
return errors.New("no content") | ||
} | ||
Comment on lines
+61
to
+64
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'm not sure we can do this as other API endpoints definitely return a 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. Yeah, we were discussing this 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 believe here, it behaves as a 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. That'd be ideal. |
||
|
||
if v == nil { | ||
return nil | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "vercel_alias Resource - terraform-provider-vercel" | ||
subcategory: "" | ||
description: |- | ||
Provides an alias resource. | ||
An alias allows a deployment to be accessed through a different URL. | ||
--- | ||
|
||
# vercel_alias (Resource) | ||
|
||
Provides an alias resource. | ||
|
||
An alias allows a deployment to be accessed through a different URL. | ||
|
||
|
||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `alias` (String) The alias to be set on the deployment. It will become the subdomain of the Vercel project top level domain | ||
- `deployment_id` (String) The deployment id to alias | ||
|
||
### Optional | ||
|
||
- `team_id` (String) The team or scope id | ||
|
||
### Read-Only | ||
|
||
- `uid` (String) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package vercel | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
"github.com/hashicorp/terraform-plugin-framework/tfsdk" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
) | ||
|
||
type dataSourceAliasType struct{} | ||
|
||
// GetSchema returns the schema information for an alias data source | ||
func (r dataSourceAliasType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { | ||
return tfsdk.Schema{ | ||
Description: ` | ||
Provides information about an existing alias within Vercel. | ||
|
||
An alias allows a deployment to be accessed through a different URL. | ||
`, | ||
Attributes: map[string]tfsdk.Attribute{ | ||
"team_id": { | ||
Optional: true, | ||
Type: types.StringType, | ||
PlanModifiers: tfsdk.AttributePlanModifiers{tfsdk.RequiresReplace()}, | ||
Description: "The team ID the alias exists beneath.", | ||
}, | ||
"alias": { | ||
Required: true, | ||
Type: types.StringType, | ||
Description: "The alias or alias ID to be retrieved.", | ||
}, | ||
"deployment_id": { | ||
Computed: true, | ||
Type: types.StringType, | ||
Description: "The deployment ID.", | ||
}, | ||
"uid": { | ||
Computed: true, | ||
Type: types.StringType, | ||
Description: "The unique identifier of the alias.", | ||
}, | ||
}, | ||
}, nil | ||
} | ||
|
||
// NewDataSource instantiates a new DataSource of this DataSourceType. | ||
func (r dataSourceAliasType) NewDataSource(ctx context.Context, p tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) { | ||
return dataSourceAlias{ | ||
p: *(p.(*provider)), | ||
}, nil | ||
} | ||
|
||
type dataSourceAlias struct { | ||
p provider | ||
} | ||
|
||
// Read will read the alias information by requesting it from the Vercel API, and will update terraform | ||
// with this information. | ||
// It is called by the provider whenever data source values should be read to update state. | ||
func (r dataSourceAlias) Read(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) { | ||
var config Alias | ||
diags := req.Config.Get(ctx, &config) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
out, err := r.p.client.GetAlias(ctx, config.Alias.Value, config.TeamID.Value) | ||
if err != nil { | ||
resp.Diagnostics.AddError( | ||
"Error reading alias", | ||
fmt.Sprintf("Could not read alias %s %s, unexpected error: %s", | ||
config.TeamID.Value, | ||
config.Alias.Value, | ||
err, | ||
), | ||
) | ||
return | ||
} | ||
|
||
result := convertResponseToAlias(out, config) | ||
tflog.Trace(ctx, "read project", map[string]interface{}{ | ||
"team_id": result.TeamID.Value, | ||
"alias": result.Alias.Value, | ||
}) | ||
|
||
diags = resp.State.Set(ctx, result) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} |
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.
It's interesting that the delete endpoint does the teamId parameter differently to the create/get endpoints. 🤔
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.
Hi. I think this file was copied/modified from
deployment_delete.go
which also usesreq.URL.Query
to add the parameter. So we picked the 1 inconsistent file to use as our starting point. Every other file usesfmt.Sprintf
to do the same thing.