diff --git a/CHANGELOG.md b/CHANGELOG.md index f94f905..7a3e9d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 1.3.0 (unreleased) +- Added support for `container.port_mappings.port_mapping.name`, `port_definitions.port_definition.[name|labels]`, `health_checks.health_check.port`, `volumes.volume.external` - Added support for `disk`, `gpus`, `max_launch_delay_seconds` and `port_definitions` configuration - Added support for `unreachable_strategy` configuration - Added support for `kill_selection` configuration diff --git a/docker-compose.yml b/docker-compose.yml index 71449a9..9eb81d9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,3 +83,4 @@ marathon: - MARATHON_DECLINE_OFFER_DURATION=3600000 - MARATHON_MESOS_AUTHENTICATION_PRINCIPAL=marathon - MARATHON_MESOS_ROLE=public + command: --enable_features external_volumes diff --git a/marathon/resource_marathon_app.go b/marathon/resource_marathon_app.go index 33e0d61..918d213 100644 --- a/marathon/resource_marathon_app.go +++ b/marathon/resource_marathon_app.go @@ -189,6 +189,10 @@ func resourceMarathonApp() *schema.Resource { Type: schema.TypeMap, Optional: true, }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, }, }, }, @@ -222,6 +226,26 @@ func resourceMarathonApp() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "external": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "options": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "provider": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, }, }, }, @@ -332,6 +356,10 @@ func resourceMarathonApp() *schema.Resource { Default: 0, Optional: true, }, + "port": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + }, "timeout_seconds": &schema.Schema{ Type: schema.TypeInt, Default: 20, @@ -425,6 +453,14 @@ func resourceMarathonApp() *schema.Resource { Default: "tcp", Optional: true, }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "labels": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + }, }, }, }, @@ -475,6 +511,11 @@ func resourceMarathonApp() *schema.Resource { Default: "YOUNGEST_FIRST", ForceNew: false, }, + "user": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: false, + }, "uris": &schema.Schema{ Type: schema.TypeList, Optional: true, @@ -682,6 +723,7 @@ func setSchemaFieldsForApp(app *marathon.Application, d *schema.ResourceData) { // pmMap["service_port"] = portMapping.ServicePort pmMap["protocol"] = portMapping.Protocol pmMap["labels"] = portMapping.Labels + pmMap["name"] = portMapping.Name portMappings[idx] = pmMap } dockerMap["port_mappings"] = []interface{}{map[string]interface{}{"port_mapping": portMappings}} @@ -698,13 +740,13 @@ func setSchemaFieldsForApp(app *marathon.Application, d *schema.ResourceData) { volumeMap["container_path"] = volume.ContainerPath volumeMap["host_path"] = volume.HostPath volumeMap["mode"] = volume.Mode + volumeMap["external"] = volume.External volumes[idx] = volumeMap } containerMap["volumes"] = []interface{}{map[string]interface{}{"volume": volumes}} } else { - containerMap["volumes"] = make([]interface{}, 0) + containerMap["volumes"] = nil } - d.Set("container", &[]interface{}{containerMap}) } d.SetPartial("container") @@ -757,6 +799,7 @@ func setSchemaFieldsForApp(app *marathon.Application, d *schema.ResourceData) { hMap["max_consecutive_failures"] = healthCheck.MaxConsecutiveFailures hMap["path"] = healthCheck.Path hMap["port_index"] = healthCheck.PortIndex + hMap["port"] = healthCheck.Port hMap["protocol"] = healthCheck.Protocol hMap["timeout_seconds"] = healthCheck.TimeoutSeconds healthChecks[idx] = hMap @@ -794,6 +837,8 @@ func setSchemaFieldsForApp(app *marathon.Application, d *schema.ResourceData) { hMap := make(map[string]interface{}) hMap["port"] = portDefinition.Port hMap["protocol"] = portDefinition.Protocol + hMap["name"] = portDefinition.Name + hMap["labels"] = portDefinition.Labels portDefinitions[idx] = hMap } d.Set("port_definitions", &[]interface{}{map[string]interface{}{"port_definition": portDefinitions}}) @@ -824,6 +869,9 @@ func setSchemaFieldsForApp(app *marathon.Application, d *schema.ResourceData) { d.Set("kill_selection", app.KillSelection) d.SetPartial("kill_selection") + d.Set("user", app.User) + d.SetPartial("user") + d.Set("uris", app.Uris) d.SetPartial("uris") @@ -1029,6 +1077,9 @@ func mutateResourceToApplication(d *schema.ResourceData) *marathon.Application { if val, ok := pmMap["service_port"]; ok { portMappings[i].ServicePort = val.(int) } + if val, ok := pmMap["name"]; ok { + portMappings[i].Name = val.(string) + } labelsMap := d.Get(fmt.Sprintf("container.0.docker.0.port_mappings.0.port_mapping.%d.labels", i)).(map[string]interface{}) labels := make(map[string]string, len(labelsMap)) @@ -1061,6 +1112,29 @@ func mutateResourceToApplication(d *schema.ResourceData) *marathon.Application { if val, ok := volumeMap["mode"]; ok { volumes[i].Mode = val.(string) } + + if volumeMap["external"] != nil { + externalMap := d.Get(fmt.Sprintf("container.0.volumes.0.volume.%d.external.0", i)).(map[string]interface{}) + if len(externalMap) > 0 { + external := new(marathon.ExternalVolume) + if val, ok := externalMap["name"]; ok { + external.Name = val.(string) + } + if val, ok := externalMap["provider"]; ok { + external.Provider = val.(string) + } + if val, ok := externalMap["options"]; ok { + optionsMap := val.(map[string]interface{}) + options := make(map[string]string, len(optionsMap)) + + for key, value := range optionsMap { + options[key] = value.(string) + } + external.Options = &options + } + volumes[i].External = external + } + } } container.Volumes = &volumes } @@ -1163,6 +1237,13 @@ func mutateResourceToApplication(d *schema.ResourceData) *marathon.Application { } } + if prop, ok := mapStruct["port"]; ok { + prop := prop.(int) + if prop > 0 { + healthCheck.Port = &prop + } + } + if prop, ok := mapStruct["timeout_seconds"]; ok { healthCheck.TimeoutSeconds = prop.(int) } @@ -1245,6 +1326,17 @@ func mutateResourceToApplication(d *schema.ResourceData) *marathon.Application { portDefinition.Protocol = prop.(string) } + if prop, ok := mapStruct["name"]; ok { + portDefinition.Name = prop.(string) + } + + labelsMap := d.Get(fmt.Sprintf("port_definitions.0.port_definition.%d.labels", i)).(map[string]interface{}) + labels := make(map[string]string, len(labelsMap)) + for key, value := range labelsMap { + labels[key] = value.(string) + } + portDefinition.Labels = &labels + portDefinitions[i] = *portDefinition } @@ -1293,6 +1385,11 @@ func mutateResourceToApplication(d *schema.ResourceData) *marathon.Application { application.KillSelection = v } + if v, ok := d.GetOk("user"); ok { + v := v.(string) + application.User = v + } + if v, ok := d.GetOk("uris.#"); ok { uris := make([]string, v.(int)) diff --git a/test/example.tf b/test/example.tf index a7a285a..0b70047 100644 --- a/test/example.tf +++ b/test/example.tf @@ -32,6 +32,7 @@ resource "marathon_app" "app-create-example" { container_port = 161 host_port = 0 protocol = "udp" + name = "port161" } } } @@ -44,8 +45,14 @@ resource "marathon_app" "app-create-example" { } volume { container_path = "/etc/b" - host_path = "/var/data/b" mode = "RW" + external { + name = "external-volume" + provider = "dvdi" + options { + "dvdi/driver" = "rexray" + } + } } } }