Skip to content
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

azurerm_media_streaming_live_event - support for stream_options property #20254

Merged
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
141 changes: 117 additions & 24 deletions internal/services/media/media_streaming_live_event_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (

func resourceMediaLiveEvent() *pluginsdk.Resource {
return &pluginsdk.Resource{
Create: resourceMediaLiveEventCreateUpdate,
Create: resourceMediaLiveEventCreate,
Read: resourceMediaLiveEventRead,
Update: resourceMediaLiveEventCreateUpdate,
Update: resourceMediaLiveEventUpdate,
Delete: resourceMediaLiveEventDelete,

Timeouts: &pluginsdk.ResourceTimeout{
Expand Down Expand Up @@ -203,6 +203,8 @@ func resourceMediaLiveEvent() *pluginsdk.Resource {
ValidateFunc: validation.StringInSlice([]string{
string(liveevents.LiveEventEncodingTypeNone),
string(liveevents.LiveEventEncodingTypePremiumOneZeroEightZerop),
string(liveevents.LiveEventEncodingTypePassthroughBasic),
string(liveevents.LiveEventEncodingTypePassthroughStandard),
string(liveevents.LiveEventEncodingTypeStandard),
}, false),
Default: string(liveevents.LiveEventEncodingTypeNone),
Expand Down Expand Up @@ -332,6 +334,16 @@ func resourceMediaLiveEvent() *pluginsdk.Resource {
},
},

"stream_options": {
Type: pluginsdk.TypeList,
Optional: true,
ForceNew: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validation.StringInSlice(liveevents.PossibleValuesForStreamOptionsFlag(), false),
},
},

"transcription_languages": {
Type: pluginsdk.TypeList,
Optional: true,
Expand All @@ -352,26 +364,24 @@ func resourceMediaLiveEvent() *pluginsdk.Resource {
}
}

func resourceMediaLiveEventCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
func resourceMediaLiveEventCreate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Media.V20220801Client.LiveEvents
subscriptionID := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

id := liveevents.NewLiveEventID(subscriptionID, d.Get("resource_group_name").(string), d.Get("media_services_account_name").(string), d.Get("name").(string))
if d.IsNewResource() {
existing, err := client.Get(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for presence of existing %s: %+v", id, err)
}
}

existing, err := client.Get(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return tf.ImportAsExistsError("azurerm_media_live_event", id.ID())
return fmt.Errorf("checking for presence of existing %s: %+v", id, err)
}
}

if !response.WasNotFound(existing.HttpResponse) {
return tf.ImportAsExistsError("azurerm_media_live_event", id.ID())
}

t := d.Get("tags").(map[string]interface{})

payload := liveevents.LiveEvent{
Expand Down Expand Up @@ -409,6 +419,10 @@ func resourceMediaLiveEventCreateUpdate(d *pluginsdk.ResourceData, meta interfac
payload.Properties.Preview = expandPreview(preview.([]interface{}))
}

if streamOptions, ok := d.GetOk("stream_options"); ok {
payload.Properties.StreamOptions = expandStreamOptions(streamOptions.([]interface{}))
}

if transcriptionLanguages, ok := d.GetOk("transcription_languages"); ok {
payload.Properties.Transcriptions = expandTranscriptions(transcriptionLanguages.([]interface{}))
}
Expand All @@ -417,25 +431,77 @@ func resourceMediaLiveEventCreateUpdate(d *pluginsdk.ResourceData, meta interfac
payload.Properties.UseStaticHostname = utils.Bool(useStaticHostName.(bool))
}

if d.IsNewResource() {
options := liveevents.CreateOperationOptions{
AutoStart: autoStart,
}
if err := client.CreateThenPoll(ctx, id, payload, options); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}
} else {
// TODO: split this into a separate update method
if err := client.UpdateThenPoll(ctx, id, payload); err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}
options := liveevents.CreateOperationOptions{
AutoStart: autoStart,
}
if err := client.CreateThenPoll(ctx, id, payload, options); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

d.SetId(id.ID())

return resourceMediaLiveEventRead(d, meta)
}

func resourceMediaLiveEventUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Media.V20220801Client.LiveEvents
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := liveevents.ParseLiveEventID(d.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, *id)
if err != nil {
return fmt.Errorf("retrieving %s: %+v", id, err)
}

if resp.Model == nil || resp.Model.Properties == nil {
return fmt.Errorf("unexpected null model of %s", id)
}
existing := resp.Model

if d.HasChange("input") {
existing.Properties.Input = expandLiveEventInput(d.Get("input").([]interface{}))
}

if d.HasChange("cross_site_access_policy") {
existing.Properties.CrossSiteAccessPolicies = expandLiveEventCrossSiteAccessPolicies(d.Get("cross_site_access_policy").([]interface{}))
}

if d.HasChange("description") {
existing.Properties.Description = utils.String(d.Get("description").(string))
}

if d.HasChange("encoding") {
existing.Properties.Encoding = expandEncoding(d.Get("encoding").([]interface{}))
}

if d.HasChange("hostname_prefix") {
existing.Properties.HostnamePrefix = utils.String(d.Get("hostname_prefix").(string))
}

if d.HasChange("preview") {
existing.Properties.Preview = expandPreview(d.Get("preview").([]interface{}))
}

if d.HasChange("transcription_languages") {
existing.Properties.Transcriptions = expandTranscriptions(d.Get("transcription_languages").([]interface{}))
}

if d.HasChange("tags") {
existing.Tags = tags.Expand(d.Get("tags").(map[string]interface{}))
}

if err := client.UpdateThenPoll(ctx, *id, *existing); err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}

return resourceMediaLiveEventRead(d, meta)
}

func resourceMediaLiveEventRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Media.V20220801Client.LiveEvents
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
Expand Down Expand Up @@ -488,6 +554,11 @@ func resourceMediaLiveEventRead(d *pluginsdk.ResourceData, meta interface{}) err
return fmt.Errorf("flattening `preview`: %s", err)
}

streamOptions := flattenStreamOptions(props.StreamOptions)
if err := d.Set("stream_options", streamOptions); err != nil {
return fmt.Errorf("flattening `stream_options`: %s", err)
}

transcriptions := flattenTranscriptions(props.Transcriptions)
if err := d.Set("transcription_languages", transcriptions); err != nil {
return fmt.Errorf("flattening `transcription_languages`: %s", err)
Expand Down Expand Up @@ -688,6 +759,15 @@ func expandLiveEventCrossSiteAccessPolicies(input []interface{}) *liveevents.Cro
CrossDomainPolicy: &crossDomainPolicy,
}
}

func expandStreamOptions(input []interface{}) *[]liveevents.StreamOptionsFlag {
streamOptions := make([]liveevents.StreamOptionsFlag, 0)
for _, v := range input {
streamOptions = append(streamOptions, liveevents.StreamOptionsFlag(v.(string)))
}
return &streamOptions
}

func expandTranscriptions(input []interface{}) *[]liveevents.LiveEventTranscription {
transcriptions := make([]liveevents.LiveEventTranscription, 0)
for _, v := range input {
Expand Down Expand Up @@ -888,6 +968,19 @@ func flattenLiveEventCrossSiteAccessPolicies(input *liveevents.CrossSiteAccessPo
}
}

func flattenStreamOptions(input *[]liveevents.StreamOptionsFlag) []interface{} {
if input == nil {
return make([]interface{}, 0)
}

streamOptions := make([]interface{}, 0)
for _, v := range *input {
streamOptions = append(streamOptions, string(v))
}

return streamOptions
}

func flattenTranscriptions(input *[]liveevents.LiveEventTranscription) []string {
if input == nil {
return make([]string, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@ func TestAccLiveEvent_requiresImport(t *testing.T) {
})
}

func TestAccLiveEvent_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_media_live_event", "test")
r := LiveEventResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.complete(data),
Check: acceptance.ComposeAggregateTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.update(data),
Check: acceptance.ComposeAggregateTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
})
}

func TestAccLiveEvent_complete(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_media_live_event", "test")
r := LiveEventResource{}
Expand Down Expand Up @@ -121,6 +142,53 @@ resource "azurerm_media_live_event" "import" {
`, r.basic(data))
}

func (r LiveEventResource) update(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_media_live_event" "test" {
name = "Event-1"
resource_group_name = azurerm_resource_group.test.name
media_services_account_name = azurerm_media_services_account.test.name
location = azurerm_resource_group.test.location
description = "Updated Description"

input {
streaming_protocol = "RTMP"
ip_access_control_allow {
name = "Test"
address = "0.0.0.0"
subnet_prefix_length = 4
}
}

encoding {
type = "Standard"
preset_name = "Default720p"
stretch_mode = "AutoSize"
key_frame_interval = "PT2S"
}

preview {
ip_access_control_allow {
name = "Allow"
address = "0.0.0.0"
subnet_prefix_length = 4
}
}

use_static_hostname = true
hostname_prefix = "special-event-update"
stream_options = ["LowLatency"]
transcription_languages = ["en-GB"]

tags = {
env = "test"
}
}
`, r.template(data))
}

func (r LiveEventResource) complete(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
Expand Down Expand Up @@ -158,6 +226,7 @@ resource "azurerm_media_live_event" "test" {

use_static_hostname = true
hostname_prefix = "special-event"
stream_options = ["LowLatency"]
transcription_languages = ["en-US"]
}
`, r.template(data))
Expand Down
3 changes: 3 additions & 0 deletions website/docs/r/media_live_event.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ resource "azurerm_media_live_event" "example" {
}
}

stream_options = ["LowLatency"]
use_static_hostname = true
hostname_prefix = "special-event"
transcription_languages = ["en-US"]
Expand Down Expand Up @@ -102,6 +103,8 @@ The following arguments are supported:

* `preview` - (Optional) A `preview` block as defined below.

* `stream_options` - (Optional) A list of options to use for the LiveEvent. Possible values are `Default`, `LowLatency`, `LowLatencyV2`. Please see more at this [document](https://learn.microsoft.com/en-us/azure/media-services/latest/live-event-latency-reference#lowlatency-and-lowlatencyv2-options). Changing this forces a new resource to be created.

* `tags` - (Optional) A mapping of tags which should be assigned to the Live Event.

* `transcription_languages` - (Optional) Specifies a list of languages (locale) to be used for speech-to-text transcription – it should match the spoken language in the audio track. The value should be in `BCP-47` format (e.g: `en-US`). [See the Microsoft Documentation for more information about the live transcription feature and the list of supported languages](https://go.microsoft.com/fwlink/?linkid=2133742 ).
Expand Down