Skip to content

Commit

Permalink
feat(live): add a new resource to generate a sign URL
Browse files Browse the repository at this point in the history
  • Loading branch information
ruwenqiang123 committed Dec 20, 2024
1 parent fe52479 commit bd9f9c1
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 0 deletions.
80 changes: 80 additions & 0 deletions docs/resources/live_url_authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
subcategory: "Live"
layout: "huaweicloud"
page_title: "HuaweiCloud: huaweicloud_live_url_authentication"
description: |-
Manages an URL authentication resource within HuaweiCloud.
---

# huaweicloud_live_url_authentication

Manages an URL authentication resource within HuaweiCloud.

-> The current resource is a one-time resource, and destroying this resource will not change the current status.

-> Before creating the resource, you need to cofiguration the URL validation first (creating
the URL validation resource first).
[documentation](https://support.huaweicloud.com/iLive-live/live_01_0049.html)

## Example Usage

```hcl
variable "domain_name" {}
variable "type" {}
variable "stream_name" {}
variable "app_name" {}
resource "huaweicloud_live_url_authentication" "test" {
domain_name = var.domain_name
type = var.type
stream_name = var.stream_name
app_name = var.app_name
}
```

## Argument Reference

The following arguments are supported:

* `region` - (Optional, String, ForceNew) Specifies the region in which to create the resource.
If omitted, the provider-level region will be used.
Changing this parameter will create a new resource.

* `domain_name` - (Required, String, ForceNew) Specifies the domain name to which the URL validation belongs.
Including the ingest domain name and streaming domain name.
Changing this parameter will create a new resource.

* `type` - (Required, String, ForceNew) Specifies the type of the domain name.
The valid values are as follow:
+ **push**: Indicates ingest domain name.
+ **pull**: Indicates streaming domain name.

Changing this parameter will create a new resource.

* `stream_name` - (Required, String, ForceNew) Specifies the stream name.
Changing this parameter will create a new resource.

* `app_name` - (Required, String, ForceNew) Specifies the application name.
Changing this parameter will create a new resource.

* `check_level` - (Optional, Int, ForceNew) Specifies the check level.
Changing this parameter will create a new resource.
The valid values are as follows:
+ **3**: Indicates only checks the LiveID matches or not but not the validity of the signed URL.
+ **5**: Indicates checks the LiveID matches or not and the validity of timestamp.

-> 1.If the value of the `auth_type` in the URL validation is set to **c_aes**, this parameter is mandatory.
<br/>2.The value of the LiveID consists of `app_name` and `stream_name`: <app_name>/<stream_name>.

* `start_time` - (Optional, String, ForceNew) Specifies the start time of the valid access time defined by the user.
Changing this parameter will create a new resource.
The time is in UTC, the format is **yyyy-mm-ddThh:mm:ssZ**. e.g. **2024-06-01T15:03:01Z**
If this parameter is not specified or is left empty, the current time is used by default.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The resource ID, UUID format.

* `key_chain` - The generated signed URLs.
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,7 @@ func Provider() *schema.Provider {
"huaweicloud_live_referer_validation": live.ResourceRefererValidation(),
"huaweicloud_live_snapshot": live.ResourceLiveSnapshot(),
"huaweicloud_live_transcoding": live.ResourceTranscoding(),
"huaweicloud_live_url_authentication": live.ResourceUrlAuthentication(),
"huaweicloud_live_url_validation": live.ResourceUrlValidation(),
"huaweicloud_live_channel": live.ResourceChannel(),
"huaweicloud_live_https_certificate": live.ResourceHTTPSCertificate(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package live

import (
"fmt"
"testing"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
)

func TestAccUrlAuthentication_basic(t *testing.T) {
var (
rName1 = "huaweicloud_live_url_authentication.test"
rName2 = "huaweicloud_live_url_authentication.try"
ingestDomainName = fmt.Sprintf("%s.huaweicloud.com", acceptance.RandomAccResourceNameWithDash())
streamDomainName = fmt.Sprintf("%s.huaweicloud.com", acceptance.RandomAccResourceNameWithDash())
startTime = time.Now().UTC().Add(24 * time.Hour).Format("2006-01-02T15:04:05Z")
)
// Avoid CheckDestroy because this resource is a one-time action resource and there is nothing in the destroy method.
// lintignore:AT001
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acceptance.TestAccPreCheck(t)
},
ProviderFactories: acceptance.TestAccProviderFactories,
Steps: []resource.TestStep{
{
// The action resource do not need to be checked and no processing is performed in the Read method.
Config: testAccUrlAuthentication_ingest(ingestDomainName, startTime),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(rName1, "key_chain.#", "1"),
),
},
{
// The action resource do not need to be checked and no processing is performed in the Read method.
Config: testAccUrlAuthentication_stream(streamDomainName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(rName2, "key_chain.#", "3"),
),
},
},
})
}

func testAccUrlAuthentication_ingest(name, startTime string) string {
return fmt.Sprintf(`
resource "huaweicloud_live_domain" "test" {
name = "%[1]s"
type = "push"
}
resource "huaweicloud_live_url_validation" "test" {
domain_name = huaweicloud_live_domain.test.name
key = "IbBIzklRGCyMEd18oPV9sxAuuwNIzT81"
auth_type = "c_aes"
timeout = 1000
}
resource "huaweicloud_live_url_authentication" "test" {
domain_name = huaweicloud_live_domain.test.name
type = "push"
app_name = "live1"
stream_name = "tf-test"
check_level = 3
start_time = "%[2]s"
depends_on = [huaweicloud_live_url_validation.test]
}
`, name, startTime)
}

func testAccUrlAuthentication_stream(name string) string {
return fmt.Sprintf(`
resource "huaweicloud_live_domain" "try" {
name = "%s"
type = "pull"
}
resource "huaweicloud_live_url_validation" "try" {
domain_name = huaweicloud_live_domain.try.name
key = "IbBIzklRGCyMEd18oPV9sxAuuwNIzT81"
auth_type = "d_sha256"
timeout = 800
}
resource "huaweicloud_live_url_authentication" "try" {
domain_name = huaweicloud_live_domain.try.name
type = "pull"
app_name = "live2"
stream_name = "tf-try"
depends_on = [huaweicloud_live_url_validation.try]
}
`, name)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package live

import (
"context"
"strings"

"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/chnsz/golangsdk"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
)

// @API Live POST /v1/{project_id}/auth/chain
func ResourceUrlAuthentication() *schema.Resource {
return &schema.Resource{
CreateContext: resourceUrlAuthenticationCreate,
ReadContext: resourceUrlAuthenticationRead,
DeleteContext: resourceUrlAuthenticationDelete,

Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"domain_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Specifies the domain name to which the URL validation belongs.`,
},
"type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Specifies the type of the domain name.`,
},
"stream_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Specifies the stream name.`,
},
"app_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Specifies the application name.`,
},
"check_level": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Description: `Specifies the check level.`,
},
"start_time": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Specifies the start time of the valid access time defined by the user.`,
},
"key_chain": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: `The generated signed URLs.`,
},
},
}
}

func buildSignUrlBodyParams(d *schema.ResourceData) map[string]interface{} {
return map[string]interface{}{
"domain": d.Get("domain_name"),
"domain_type": d.Get("type"),
"stream": d.Get("stream_name"),
"app": d.Get("app_name"),
"check_level": utils.ValueIgnoreEmpty(d.Get("check_level")),
"start_time": utils.ValueIgnoreEmpty(d.Get("start_time")),
}
}

func resourceUrlAuthenticationCreate(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var (
cfg = meta.(*config.Config)
region = cfg.GetRegion(d)
httpUrl = "v1/{project_id}/auth/chain"
)

client, err := cfg.NewServiceClient("live", region)
if err != nil {
return diag.Errorf("error creating Live client: %s", err)
}

createPath := client.Endpoint + httpUrl
createPath = strings.ReplaceAll(createPath, "{project_id}", client.ProjectID)

createOpt := golangsdk.RequestOpts{
KeepResponseBody: true,
JSONBody: utils.RemoveNil(buildSignUrlBodyParams(d)),
}

resp, err := client.Request("POST", createPath, &createOpt)
if err != nil {
return diag.Errorf("error creating sign URL: %s", err)
}

resourceId, err := uuid.GenerateUUID()
if err != nil {
return diag.Errorf("unable to generate ID: %s", err)
}

d.SetId(resourceId)

respBody, err := utils.FlattenResponse(resp)
if err != nil {
return diag.FromErr(err)
}

keyChain := utils.PathSearch("keychain", respBody, make([]interface{}, 0)).([]interface{})
if len(keyChain) == 0 {
return diag.Errorf("err creating sign URL, not found 'key_chain' in API response")
}

var mErr *multierror.Error
mErr = multierror.Append(
mErr,
d.Set("key_chain", keyChain),
)

return diag.FromErr(mErr.ErrorOrNil())
}

func resourceUrlAuthenticationRead(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics {
// This resource is only a one-time action resource for generating a signer URL
return nil
}

func resourceUrlAuthenticationDelete(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics {
// This resource is only a one-time action resource for generating a signer URL
return nil
}

0 comments on commit bd9f9c1

Please sign in to comment.