You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1076 lines
32 KiB

  1. //
  2. // ecs: This package provides types and functions to interact with the AWS EC2 Container Service API
  3. //
  4. // Depends on https://github.com/goamz/goamz
  5. //
  6. // Author Boyan Dimitrov <boyann@gmail.com>
  7. //
  8. package ecs
  9. import (
  10. "encoding/xml"
  11. "fmt"
  12. "log"
  13. "net/http"
  14. "net/http/httputil"
  15. "net/url"
  16. "strconv"
  17. "strings"
  18. "time"
  19. "github.com/goamz/goamz/aws"
  20. )
  21. const debug = false
  22. var timeNow = time.Now
  23. // ECS contains the details of the AWS region to perform operations against.
  24. type ECS struct {
  25. aws.Auth
  26. aws.Region
  27. }
  28. // New creates a new ECS Client.
  29. func New(auth aws.Auth, region aws.Region) *ECS {
  30. return &ECS{auth, region}
  31. }
  32. // ----------------------------------------------------------------------------
  33. // Request dispatching logic.
  34. // Error encapsulates an error returned by the AWS ECS API.
  35. //
  36. // See http://goo.gl/VZGuC for more details.
  37. type Error struct {
  38. // HTTP status code (200, 403, ...)
  39. StatusCode int
  40. // ECS error code ("UnsupportedOperation", ...)
  41. Code string
  42. // The error type
  43. Type string
  44. // The human-oriented error message
  45. Message string
  46. RequestId string `xml:"RequestID"`
  47. }
  48. func (err *Error) Error() string {
  49. if err.Code == "" {
  50. return err.Message
  51. }
  52. return fmt.Sprintf("%s (%s)", err.Message, err.Code)
  53. }
  54. type xmlErrors struct {
  55. RequestId string `xml:"RequestId"`
  56. Errors []Error `xml:"Error"`
  57. }
  58. func (e *ECS) query(params map[string]string, resp interface{}) error {
  59. params["Version"] = "2014-11-13"
  60. data := strings.NewReader(multimap(params).Encode())
  61. hreq, err := http.NewRequest("POST", e.Region.ECSEndpoint+"/", data)
  62. if err != nil {
  63. return err
  64. }
  65. hreq.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
  66. token := e.Auth.Token()
  67. if token != "" {
  68. hreq.Header.Set("X-Amz-Security-Token", token)
  69. }
  70. signer := aws.NewV4Signer(e.Auth, "ecs", e.Region)
  71. signer.Sign(hreq)
  72. if debug {
  73. log.Printf("%v -> {\n", hreq)
  74. }
  75. r, err := http.DefaultClient.Do(hreq)
  76. if err != nil {
  77. log.Printf("Error calling Amazon %v", err)
  78. return err
  79. }
  80. defer r.Body.Close()
  81. if debug {
  82. dump, _ := httputil.DumpResponse(r, true)
  83. log.Printf("response:\n")
  84. log.Printf("%v\n}\n", string(dump))
  85. }
  86. if r.StatusCode != 200 {
  87. return buildError(r)
  88. }
  89. err = xml.NewDecoder(r.Body).Decode(resp)
  90. return err
  91. }
  92. func buildError(r *http.Response) error {
  93. var (
  94. err Error
  95. errors xmlErrors
  96. )
  97. xml.NewDecoder(r.Body).Decode(&errors)
  98. if len(errors.Errors) > 0 {
  99. err = errors.Errors[0]
  100. }
  101. err.RequestId = errors.RequestId
  102. err.StatusCode = r.StatusCode
  103. if err.Message == "" {
  104. err.Message = r.Status
  105. }
  106. return &err
  107. }
  108. func multimap(p map[string]string) url.Values {
  109. q := make(url.Values, len(p))
  110. for k, v := range p {
  111. q[k] = []string{v}
  112. }
  113. return q
  114. }
  115. func makeParams(action string) map[string]string {
  116. params := make(map[string]string)
  117. params["Action"] = action
  118. return params
  119. }
  120. func addParamsList(params map[string]string, label string, ids []string) {
  121. for i, id := range ids {
  122. params[label+"."+strconv.Itoa(i+1)] = id
  123. }
  124. }
  125. // ----------------------------------------------------------------------------
  126. // ECS types and related functions.
  127. // SimpleResp is the beic response from most actions.
  128. type SimpleResp struct {
  129. XMLName xml.Name
  130. RequestId string `xml:"ResponseMetadata>RequestId"`
  131. }
  132. // Cluster encapsulates the cluster datatype
  133. //
  134. // See
  135. type Cluster struct {
  136. ClusterArn string `xml:"clusterArn"`
  137. ClusterName string `xml:"clusterName"`
  138. Status string `xml:"status"`
  139. }
  140. // CreateClusterReq encapsulates the createcluster req params
  141. type CreateClusterReq struct {
  142. ClusterName string
  143. }
  144. // CreateClusterResp encapsulates the createcluster response
  145. type CreateClusterResp struct {
  146. Cluster Cluster `xml:"CreateClusterResult>cluster"`
  147. RequestId string `xml:"ResponseMetadata>RequestId"`
  148. }
  149. // CreateCluster creates a new Amazon ECS cluster. By default, your account
  150. // will receive a default cluster when you launch your first container instance
  151. func (e *ECS) CreateCluster(req *CreateClusterReq) (resp *CreateClusterResp, err error) {
  152. if req == nil {
  153. return nil, fmt.Errorf("The req params cannot be nil")
  154. }
  155. params := makeParams("CreateCluster")
  156. params["clusterName"] = req.ClusterName
  157. resp = new(CreateClusterResp)
  158. if err := e.query(params, resp); err != nil {
  159. return nil, err
  160. }
  161. return resp, nil
  162. }
  163. // Resource describes the resources available for a container instance.
  164. type Resource struct {
  165. DoubleValue float64 `xml:"doubleValue"`
  166. IntegerValue int32 `xml:"integerValue"`
  167. LongValue int64 `xml:"longValue"`
  168. Name string `xml:"name"`
  169. StringSetValue []string `xml:"stringSetValue>member"`
  170. Type string `xml:"type"`
  171. }
  172. // ContainerInstance represents n Amazon EC2 instance that is running
  173. // the Amazon ECS agent and has been registered with a cluster
  174. type ContainerInstance struct {
  175. AgentConnected bool `xml:"agentConnected"`
  176. ContainerInstanceArn string `xml:"containerInstanceArn"`
  177. Ec2InstanceId string `xml:"ec2InstanceId"`
  178. RegisteredResources []Resource `xml:"registeredResources>member"`
  179. RemainingResources []Resource `xml:"remainingResources>member"`
  180. Status string `xml:"status"`
  181. }
  182. // DeregisterContainerInstanceReq encapsulates DeregisterContainerInstance request params
  183. type DeregisterContainerInstanceReq struct {
  184. Cluster string
  185. // arn:aws:ecs:region:aws_account_id:container-instance/container_instance_UUID.
  186. ContainerInstance string
  187. Force bool
  188. }
  189. // DeregisterContainerInstanceResp encapsulates DeregisterContainerInstance response
  190. type DeregisterContainerInstanceResp struct {
  191. ContainerInstance ContainerInstance `xml:"DeregisterContainerInstanceResult>containerInstance"`
  192. RequestId string `xml:"ResponseMetadata>RequestId"`
  193. }
  194. // DeregisterContainerInstance deregisters an Amazon ECS container instance from the specified cluster
  195. func (e *ECS) DeregisterContainerInstance(req *DeregisterContainerInstanceReq) (
  196. resp *DeregisterContainerInstanceResp, err error) {
  197. if req == nil {
  198. return nil, fmt.Errorf("The req params cannot be nil")
  199. }
  200. params := makeParams("DeregisterContainerInstance")
  201. params["containerInstance"] = req.ContainerInstance
  202. params["force"] = strconv.FormatBool(req.Force)
  203. if req.Cluster != "" {
  204. params["cluster"] = req.Cluster
  205. }
  206. resp = new(DeregisterContainerInstanceResp)
  207. if err := e.query(params, resp); err != nil {
  208. return nil, err
  209. }
  210. return resp, nil
  211. }
  212. // PortMapping encapsulates the PortMapping data type
  213. type PortMapping struct {
  214. ContainerPort int32 `xml:containerPort`
  215. HostPort int32 `xml:hostPort`
  216. }
  217. // KeyValuePair encapsulates the KeyValuePair data type
  218. type KeyValuePair struct {
  219. Name string `xml:"name"`
  220. Value string `xml:"value"`
  221. }
  222. // MountPoint encapsulates the MountPoint data type
  223. type MountPoint struct {
  224. ContainerPath string `xml:"containerPath"`
  225. ReadOnly bool `xml:"readOnly"`
  226. SourceVolume string `xml:"sourceVolume"`
  227. }
  228. // VolumeFrom encapsulates the VolumeFrom data type
  229. type VolumeFrom struct {
  230. ReadOnly bool `xml:"readOnly"`
  231. SourceContainer string `xml:"sourceContainer"`
  232. }
  233. // HostVolumeProperties encapsulates the HostVolumeProperties data type
  234. type HostVolumeProperties struct {
  235. SourcePath string `xml:"sourcePath"`
  236. }
  237. // Volume encapsulates the Volume data type
  238. type Volume struct {
  239. Host HostVolumeProperties `xml:"host"`
  240. Name string `xml:"name"`
  241. }
  242. // ContainerDefinition encapsulates the container definition type
  243. // Container definitions are used in task definitions to describe
  244. // the different containers that are launched as part of a task
  245. type ContainerDefinition struct {
  246. Command []string `xml:"command>member"`
  247. Cpu int32 `xml:"cpu"`
  248. EntryPoint []string `xml:"entryPoint>member"`
  249. Environment []KeyValuePair `xml:"environment>member"`
  250. Essential bool `xml:"essential"`
  251. Image string `xml:"image"`
  252. Links []string `xml:"links>member"`
  253. Memory int32 `xml:"memory"`
  254. MountPoints []MountPoint `xml:"mountPoints>member"`
  255. Name string `xml:"name"`
  256. PortMappings []PortMapping `xml:"portMappings>member"`
  257. VolumesFrom []VolumeFrom `xml:"volumesFrom>member"`
  258. }
  259. // TaskDefinition encapsulates the task definition type
  260. type TaskDefinition struct {
  261. ContainerDefinitions []ContainerDefinition `xml:"containerDefinitions>member"`
  262. Family string `xml:"family"`
  263. Revision int32 `xml:"revision"`
  264. TaskDefinitionArn string `xml:"taskDefinitionArn"`
  265. Status string `xml:"status"`
  266. Volumes []Volume `xml:"volumes>member"`
  267. }
  268. // DeregisterTaskDefinitionReq encapsulates DeregisterTaskDefinition req params
  269. type DeregisterTaskDefinitionReq struct {
  270. TaskDefinition string
  271. }
  272. // DeregisterTaskDefinitionResp encapsuates the DeregisterTaskDefinition response
  273. type DeregisterTaskDefinitionResp struct {
  274. TaskDefinition TaskDefinition `xml:"DeregisterTaskDefinitionResult>taskDefinition"`
  275. RequestId string `xml:"ResponseMetadata>RequestId"`
  276. }
  277. // DeregisterTaskDefinition deregisters the specified task definition
  278. func (e *ECS) DeregisterTaskDefinition(req *DeregisterTaskDefinitionReq) (
  279. *DeregisterTaskDefinitionResp, error) {
  280. if req == nil {
  281. return nil, fmt.Errorf("The req params cannot be nil")
  282. }
  283. params := makeParams("DeregisterTaskDefinition")
  284. params["taskDefinition"] = req.TaskDefinition
  285. resp := new(DeregisterTaskDefinitionResp)
  286. if err := e.query(params, resp); err != nil {
  287. return nil, err
  288. }
  289. return resp, nil
  290. }
  291. // Failure encapsulates the failure type
  292. type Failure struct {
  293. Arn string `xml:"arn"`
  294. Reason string `xml:"reason"`
  295. }
  296. // DescribeClustersReq encapsulates DescribeClusters req params
  297. type DescribeClustersReq struct {
  298. Clusters []string
  299. }
  300. // DescribeClustersResp encapsuates the DescribeClusters response
  301. type DescribeClustersResp struct {
  302. Clusters []Cluster `xml:"DescribeClustersResult>clusters>member"`
  303. Failures []Failure `xml:"DescribeClustersResult>failures>member"`
  304. RequestId string `xml:"ResponseMetadata>RequestId"`
  305. }
  306. // DescribeClusters describes one or more of your clusters
  307. func (e *ECS) DescribeClusters(req *DescribeClustersReq) (*DescribeClustersResp, error) {
  308. if req == nil {
  309. return nil, fmt.Errorf("The req params cannot be nil")
  310. }
  311. params := makeParams("DescribeClusters")
  312. if len(req.Clusters) > 0 {
  313. addParamsList(params, "clusters.member", req.Clusters)
  314. }
  315. resp := new(DescribeClustersResp)
  316. if err := e.query(params, resp); err != nil {
  317. return nil, err
  318. }
  319. return resp, nil
  320. }
  321. // DescribeContainerInstancesReq ecapsulates DescribeContainerInstances req params
  322. type DescribeContainerInstancesReq struct {
  323. Cluster string
  324. ContainerInstances []string
  325. }
  326. // DescribeContainerInstancesResp ecapsulates DescribeContainerInstances response
  327. type DescribeContainerInstancesResp struct {
  328. ContainerInstances []ContainerInstance `xml:"DescribeContainerInstancesResult>containerInstances>member"`
  329. Failures []Failure `xml:"DescribeContainerInstancesResult>failures>member"`
  330. RequestId string `xml:"ResponseMetadata>RequestId"`
  331. }
  332. // DescribeContainerInstances describes Amazon EC2 Container Service container instances
  333. // Returns metadata about registered and remaining resources on each container instance requested
  334. func (e *ECS) DescribeContainerInstances(req *DescribeContainerInstancesReq) (
  335. *DescribeContainerInstancesResp, error) {
  336. if req == nil {
  337. return nil, fmt.Errorf("The req params cannot be nil")
  338. }
  339. params := makeParams("DescribeContainerInstances")
  340. if req.Cluster != "" {
  341. params["cluster"] = req.Cluster
  342. }
  343. if len(req.ContainerInstances) > 0 {
  344. addParamsList(params, "containerInstances.member", req.ContainerInstances)
  345. }
  346. resp := new(DescribeContainerInstancesResp)
  347. if err := e.query(params, resp); err != nil {
  348. return nil, err
  349. }
  350. return resp, nil
  351. }
  352. // DescribeTaskDefinitionReq encapsulates DescribeTaskDefinition req params
  353. type DescribeTaskDefinitionReq struct {
  354. TaskDefinition string
  355. }
  356. // DescribeTaskDefinitionResp encapsuates the DescribeTaskDefinition response
  357. type DescribeTaskDefinitionResp struct {
  358. TaskDefinition TaskDefinition `xml:"DescribeTaskDefinitionResult>taskDefinition"`
  359. RequestId string `xml:"ResponseMetadata>RequestId"`
  360. }
  361. // DescribeTaskDefinition describes a task definition
  362. func (e *ECS) DescribeTaskDefinition(req *DescribeTaskDefinitionReq) (
  363. *DescribeTaskDefinitionResp, error) {
  364. if req == nil {
  365. return nil, fmt.Errorf("The req params cannot be nil")
  366. }
  367. params := makeParams("DescribeTaskDefinition")
  368. params["taskDefinition"] = req.TaskDefinition
  369. resp := new(DescribeTaskDefinitionResp)
  370. if err := e.query(params, resp); err != nil {
  371. return nil, err
  372. }
  373. return resp, nil
  374. }
  375. // NetworkBinding encapsulates the network binding data type
  376. type NetworkBinding struct {
  377. BindIp string `xml:"bindIp"`
  378. ContainerPort int32 `xml:"containerPort"`
  379. HostPort int32 `xml:"hostPort"`
  380. }
  381. // Container encapsulates the container data type
  382. type Container struct {
  383. ContainerArn string `xml:"containerArn"`
  384. ExitCode int32 `xml:"exitCode"`
  385. LastStatus string `xml:"lastStatus"`
  386. Name string `xml:"name"`
  387. NetworkBindings []NetworkBinding `xml:"networkBindings>member"`
  388. Reason string `xml:"reason"`
  389. TaskArn string `xml:"taskArn"`
  390. }
  391. // ContainerOverride encapsulates the container override data type
  392. type ContainerOverride struct {
  393. Command []string `xml:"command>member"`
  394. Environment []KeyValuePair `xml:"environment>member"`
  395. Name string `xml:"name"`
  396. }
  397. // TaskOverride encapsulates the task override data type
  398. type TaskOverride struct {
  399. ContainerOverrides []ContainerOverride `xml:"containerOverrides>member"`
  400. }
  401. // Task encapsulates the task data type
  402. type Task struct {
  403. ClusterArn string `xml:"clusterArn"`
  404. ContainerInstanceArn string `xml:"containerInstanceArn"`
  405. Containers []Container `xml:"containers>member"`
  406. DesiredStatus string `xml:"desiredStatus"`
  407. LastStatus string `xml:"lastStatus"`
  408. Overrides TaskOverride `xml:"overrides"`
  409. TaskArn string `xml:"taskArn"`
  410. TaskDefinitionArn string `xml:"taskDefinitionArn"`
  411. }
  412. // DescribeTasksReq encapsulates DescribeTasks req params
  413. type DescribeTasksReq struct {
  414. Cluster string
  415. Tasks []string
  416. }
  417. // DescribeTasksResp encapsuates the DescribeTasks response
  418. type DescribeTasksResp struct {
  419. Tasks []Task `xml:"DescribeTasksResult>tasks>member"`
  420. Failures []Failure `xml:"DescribeTasksResult>failures>member"`
  421. RequestId string `xml:"ResponseMetadata>RequestId"`
  422. }
  423. // DescribeTasks describes a task definition
  424. func (e *ECS) DescribeTasks(req *DescribeTasksReq) (*DescribeTasksResp, error) {
  425. if req == nil {
  426. return nil, fmt.Errorf("The req params cannot be nil")
  427. }
  428. params := makeParams("DescribeTasks")
  429. if len(req.Tasks) > 0 {
  430. addParamsList(params, "tasks.member", req.Tasks)
  431. }
  432. if req.Cluster != "" {
  433. params["cluster"] = req.Cluster
  434. }
  435. resp := new(DescribeTasksResp)
  436. if err := e.query(params, resp); err != nil {
  437. return nil, err
  438. }
  439. return resp, nil
  440. }
  441. // DiscoverPollEndpointReq encapsulates DiscoverPollEndpoint req params
  442. type DiscoverPollEndpointReq struct {
  443. ContainerInstance string
  444. }
  445. // DiscoverPollEndpointResp encapsuates the DiscoverPollEndpoint response
  446. type DiscoverPollEndpointResp struct {
  447. Endpoint string `xml:"DiscoverPollEndpointResult>endpoint"`
  448. RequestId string `xml:"ResponseMetadata>RequestId"`
  449. }
  450. // DiscoverPollEndpoint returns an endpoint for the Amazon EC2 Container Service agent
  451. // to poll for updates
  452. func (e *ECS) DiscoverPollEndpoint(req *DiscoverPollEndpointReq) (
  453. *DiscoverPollEndpointResp, error) {
  454. if req == nil {
  455. return nil, fmt.Errorf("The req params cannot be nil")
  456. }
  457. params := makeParams("DiscoverPollEndpoint")
  458. if req.ContainerInstance != "" {
  459. params["containerInstance"] = req.ContainerInstance
  460. }
  461. resp := new(DiscoverPollEndpointResp)
  462. if err := e.query(params, resp); err != nil {
  463. return nil, err
  464. }
  465. return resp, nil
  466. }
  467. // ListClustersReq encapsulates ListClusters req params
  468. type ListClustersReq struct {
  469. MaxResults int32
  470. NextToken string
  471. }
  472. // ListClustersResp encapsuates the ListClusters response
  473. type ListClustersResp struct {
  474. ClusterArns []string `xml:"ListClustersResult>clusterArns>member"`
  475. NextToken string `xml:"ListClustersResult>nextToken"`
  476. RequestId string `xml:"ResponseMetadata>RequestId"`
  477. }
  478. // ListClusters returns a list of existing clusters
  479. func (e *ECS) ListClusters(req *ListClustersReq) (
  480. *ListClustersResp, error) {
  481. if req == nil {
  482. return nil, fmt.Errorf("The req params cannot be nil")
  483. }
  484. params := makeParams("ListClusters")
  485. if req.MaxResults > 0 {
  486. params["maxResults"] = strconv.Itoa(int(req.MaxResults))
  487. }
  488. if req.NextToken != "" {
  489. params["nextToken"] = req.NextToken
  490. }
  491. resp := new(ListClustersResp)
  492. if err := e.query(params, resp); err != nil {
  493. return nil, err
  494. }
  495. return resp, nil
  496. }
  497. // ListContainerInstancesReq encapsulates ListContainerInstances req params
  498. type ListContainerInstancesReq struct {
  499. Cluster string
  500. MaxResults int32
  501. NextToken string
  502. }
  503. // ListContainerInstancesResp encapsuates the ListContainerInstances response
  504. type ListContainerInstancesResp struct {
  505. ContainerInstanceArns []string `xml:"ListContainerInstancesResult>containerInstanceArns>member"`
  506. NextToken string `xml:"ListContainerInstancesResult>nextToken"`
  507. RequestId string `xml:"ResponseMetadata>RequestId"`
  508. }
  509. // ListContainerInstances returns a list of container instances in a specified cluster.
  510. func (e *ECS) ListContainerInstances(req *ListContainerInstancesReq) (
  511. *ListContainerInstancesResp, error) {
  512. if req == nil {
  513. return nil, fmt.Errorf("The req params cannot be nil")
  514. }
  515. params := makeParams("ListContainerInstances")
  516. if req.MaxResults > 0 {
  517. params["maxResults"] = strconv.Itoa(int(req.MaxResults))
  518. }
  519. if req.Cluster != "" {
  520. params["cluster"] = req.Cluster
  521. }
  522. if req.NextToken != "" {
  523. params["nextToken"] = req.NextToken
  524. }
  525. resp := new(ListContainerInstancesResp)
  526. if err := e.query(params, resp); err != nil {
  527. return nil, err
  528. }
  529. return resp, nil
  530. }
  531. // ListTaskDefinitionsReq encapsulates ListTaskDefinitions req params
  532. type ListTaskDefinitionsReq struct {
  533. FamilyPrefix string
  534. MaxResults int32
  535. NextToken string
  536. }
  537. // ListTaskDefinitionsResp encapsuates the ListTaskDefinitions response
  538. type ListTaskDefinitionsResp struct {
  539. TaskDefinitionArns []string `xml:"ListTaskDefinitionsResult>taskDefinitionArns>member"`
  540. NextToken string `xml:"ListTaskDefinitionsResult>nextToken"`
  541. RequestId string `xml:"ResponseMetadata>RequestId"`
  542. }
  543. // ListTaskDefinitions Returns a list of task definitions that are registered to your account.
  544. func (e *ECS) ListTaskDefinitions(req *ListTaskDefinitionsReq) (
  545. *ListTaskDefinitionsResp, error) {
  546. if req == nil {
  547. return nil, fmt.Errorf("The req params cannot be nil")
  548. }
  549. params := makeParams("ListTaskDefinitions")
  550. if req.MaxResults > 0 {
  551. params["maxResults"] = strconv.Itoa(int(req.MaxResults))
  552. }
  553. if req.FamilyPrefix != "" {
  554. params["familyPrefix"] = req.FamilyPrefix
  555. }
  556. if req.NextToken != "" {
  557. params["nextToken"] = req.NextToken
  558. }
  559. resp := new(ListTaskDefinitionsResp)
  560. if err := e.query(params, resp); err != nil {
  561. return nil, err
  562. }
  563. return resp, nil
  564. }
  565. // ListTasksReq encapsulates ListTasks req params
  566. type ListTasksReq struct {
  567. Cluster string
  568. ContainerInstance string
  569. Family string
  570. MaxResults int32
  571. NextToken string
  572. }
  573. // ListTasksResp encapsuates the ListTasks response
  574. type ListTasksResp struct {
  575. TaskArns []string `xml:"ListTasksResult>taskArns>member"`
  576. NextToken string `xml:"ListTasksResult>nextToken"`
  577. RequestId string `xml:"ResponseMetadata>RequestId"`
  578. }
  579. // ListTasks Returns a list of tasks for a specified cluster.
  580. // You can filter the results by family name or by a particular container instance
  581. // with the family and containerInstance parameters.
  582. func (e *ECS) ListTasks(req *ListTasksReq) (
  583. *ListTasksResp, error) {
  584. if req == nil {
  585. return nil, fmt.Errorf("The req params cannot be nil")
  586. }
  587. params := makeParams("ListTasks")
  588. if req.MaxResults > 0 {
  589. params["maxResults"] = strconv.Itoa(int(req.MaxResults))
  590. }
  591. if req.Cluster != "" {
  592. params["cluster"] = req.Cluster
  593. }
  594. if req.ContainerInstance != "" {
  595. params["containerInstance"] = req.ContainerInstance
  596. }
  597. if req.Family != "" {
  598. params["family"] = req.Family
  599. }
  600. if req.NextToken != "" {
  601. params["nextToken"] = req.NextToken
  602. }
  603. resp := new(ListTasksResp)
  604. if err := e.query(params, resp); err != nil {
  605. return nil, err
  606. }
  607. return resp, nil
  608. }
  609. // RegisterContainerInstanceReq encapsulates RegisterContainerInstance req params
  610. type RegisterContainerInstanceReq struct {
  611. Cluster string
  612. InstanceIdentityDocument string
  613. InstanceIdentityDocumentSignature string
  614. TotalResources []Resource
  615. }
  616. // DeregisterContainerInstanceResp encapsulates RegisterContainerInstance response
  617. type RegisterContainerInstanceResp struct {
  618. ContainerInstance ContainerInstance `xml:"RegisterContainerInstanceResult>containerInstance"`
  619. RequestId string `xml:"ResponseMetadata>RequestId"`
  620. }
  621. // RegisterContainerInstance registers an Amazon EC2 instance into the specified cluster.
  622. // This instance will become available to place containers on.
  623. func (e *ECS) RegisterContainerInstance(req *RegisterContainerInstanceReq) (
  624. resp *RegisterContainerInstanceResp, err error) {
  625. if req == nil {
  626. return nil, fmt.Errorf("The req params cannot be nil")
  627. }
  628. params := makeParams("RegisterContainerInstance")
  629. if req.InstanceIdentityDocument != "" {
  630. params["instanceIdentityDocument"] = req.InstanceIdentityDocument
  631. }
  632. if req.InstanceIdentityDocumentSignature != "" {
  633. params["instanceIdentityDocumentSignature"] = req.InstanceIdentityDocumentSignature
  634. }
  635. if req.Cluster != "" {
  636. params["cluster"] = req.Cluster
  637. }
  638. // Marshal Resources
  639. for i, r := range req.TotalResources {
  640. key := fmt.Sprintf("totalResources.member.%d", i+1)
  641. params[fmt.Sprintf("%s.doubleValue", key)] = strconv.FormatFloat(r.DoubleValue, 'f', 1, 64)
  642. params[fmt.Sprintf("%s.integerValue", key)] = strconv.Itoa(int(r.IntegerValue))
  643. params[fmt.Sprintf("%s.longValue", key)] = strconv.Itoa(int(r.LongValue))
  644. params[fmt.Sprintf("%s.name", key)] = r.Name
  645. params[fmt.Sprintf("%s.type", key)] = r.Type
  646. for k, sv := range r.StringSetValue {
  647. params[fmt.Sprintf("%s.stringSetValue.member.%d", key, k+1)] = sv
  648. }
  649. }
  650. resp = new(RegisterContainerInstanceResp)
  651. if err := e.query(params, resp); err != nil {
  652. return nil, err
  653. }
  654. return resp, nil
  655. }
  656. // RegisterTaskDefinitionReq encapsulates RegisterTaskDefinition req params
  657. type RegisterTaskDefinitionReq struct {
  658. Family string
  659. ContainerDefinitions []ContainerDefinition
  660. Volumes []Volume
  661. }
  662. // RegisterTaskDefinitionResp encapsulates RegisterTaskDefinition response
  663. type RegisterTaskDefinitionResp struct {
  664. TaskDefinition TaskDefinition `xml:"RegisterTaskDefinitionResult>taskDefinition"`
  665. RequestId string `xml:"ResponseMetadata>RequestId"`
  666. }
  667. // RegisterTaskDefinition registers a new task definition from the supplied family and containerDefinitions.
  668. func (e *ECS) RegisterTaskDefinition(req *RegisterTaskDefinitionReq) (
  669. resp *RegisterTaskDefinitionResp, err error) {
  670. if req == nil {
  671. return nil, fmt.Errorf("The req params cannot be nil")
  672. }
  673. params := makeParams("RegisterTaskDefinition")
  674. if req.Family != "" {
  675. params["family"] = req.Family
  676. }
  677. // Marshal Container Definitions
  678. for i, c := range req.ContainerDefinitions {
  679. key := fmt.Sprintf("containerDefinitions.member.%d", i+1)
  680. params[fmt.Sprintf("%s.cpu", key)] = strconv.Itoa(int(c.Cpu))
  681. params[fmt.Sprintf("%s.essential", key)] = strconv.FormatBool(c.Essential)
  682. params[fmt.Sprintf("%s.image", key)] = c.Image
  683. params[fmt.Sprintf("%s.memory", key)] = strconv.Itoa(int(c.Memory))
  684. params[fmt.Sprintf("%s.name", key)] = c.Name
  685. for k, cmd := range c.Command {
  686. params[fmt.Sprintf("%s.command.member.%d", key, k+1)] = cmd
  687. }
  688. for k, ep := range c.EntryPoint {
  689. params[fmt.Sprintf("%s.entryPoint.member.%d", key, k+1)] = ep
  690. }
  691. for k, env := range c.Environment {
  692. params[fmt.Sprintf("%s.environment.member.%d.name", key, k+1)] = env.Name
  693. params[fmt.Sprintf("%s.environment.member.%d.value", key, k+1)] = env.Value
  694. }
  695. for k, l := range c.Links {
  696. params[fmt.Sprintf("%s.links.member.%d", key, k+1)] = l
  697. }
  698. for k, p := range c.PortMappings {
  699. params[fmt.Sprintf("%s.portMappings.member.%d.containerPort", key, k+1)] = strconv.Itoa(int(p.ContainerPort))
  700. params[fmt.Sprintf("%s.portMappings.member.%d.hostPort", key, k+1)] = strconv.Itoa(int(p.HostPort))
  701. }
  702. for k, m := range c.MountPoints {
  703. params[fmt.Sprintf("%s.mountPoints.member.%d.containerPath", key, k+1)] = m.ContainerPath
  704. params[fmt.Sprintf("%s.mountPoints.member.%d.readOnly", key, k+1)] = strconv.FormatBool(m.ReadOnly)
  705. params[fmt.Sprintf("%s.mountPoints.member.%d.sourceVolume", key, k+1)] = m.SourceVolume
  706. }
  707. for k, v := range c.VolumesFrom {
  708. params[fmt.Sprintf("%s.volumesFrom.member.%d.readOnly", key, k+1)] = strconv.FormatBool(v.ReadOnly)
  709. params[fmt.Sprintf("%s.volumesFrom.member.%d.sourceContainer", key, k+1)] = v.SourceContainer
  710. }
  711. }
  712. for k, v := range req.Volumes {
  713. params[fmt.Sprintf("volumes.member.%d.name", k+1)] = v.Name
  714. params[fmt.Sprintf("volumes.member.%d.host.sourcePath", k+1)] = v.Host.SourcePath
  715. }
  716. resp = new(RegisterTaskDefinitionResp)
  717. if err := e.query(params, resp); err != nil {
  718. return nil, err
  719. }
  720. return resp, nil
  721. }
  722. // RunTaskReq encapsulates RunTask req params
  723. type RunTaskReq struct {
  724. Cluster string
  725. Count int32
  726. Overrides TaskOverride
  727. TaskDefinition string
  728. }
  729. // RunTaskResp encapsuates the RunTask response
  730. type RunTaskResp struct {
  731. Tasks []Task `xml:"RunTaskResult>tasks>member"`
  732. Failures []Failure `xml:"RunTaskResult>failures>member"`
  733. RequestId string `xml:"ResponseMetadata>RequestId"`
  734. }
  735. // RunTask Start a task using random placement and the default Amazon ECS scheduler.
  736. // If you want to use your own scheduler or place a task on a specific container instance,
  737. // use StartTask instead.
  738. func (e *ECS) RunTask(req *RunTaskReq) (*RunTaskResp, error) {
  739. if req == nil {
  740. return nil, fmt.Errorf("The req params cannot be nil")
  741. }
  742. params := makeParams("RunTask")
  743. if req.Count > 0 {
  744. params["count"] = strconv.Itoa(int(req.Count))
  745. }
  746. if req.Cluster != "" {
  747. params["cluster"] = req.Cluster
  748. }
  749. if req.TaskDefinition != "" {
  750. params["taskDefinition"] = req.TaskDefinition
  751. }
  752. for i, co := range req.Overrides.ContainerOverrides {
  753. key := fmt.Sprintf("overrides.containerOverrides.member.%d", i+1)
  754. params[fmt.Sprintf("%s.name", key)] = co.Name
  755. for k, cmd := range co.Command {
  756. params[fmt.Sprintf("%s.command.member.%d", key, k+1)] = cmd
  757. }
  758. for k, env := range co.Environment {
  759. params[fmt.Sprintf("%s.environment.member.%d.name", key, k+1)] = env.Name
  760. params[fmt.Sprintf("%s.environment.member.%d.value", key, k+1)] = env.Value
  761. }
  762. }
  763. resp := new(RunTaskResp)
  764. if err := e.query(params, resp); err != nil {
  765. return nil, err
  766. }
  767. return resp, nil
  768. }
  769. // StartTaskReq encapsulates StartTask req params
  770. type StartTaskReq struct {
  771. Cluster string
  772. ContainerInstances []string
  773. Overrides TaskOverride
  774. TaskDefinition string
  775. }
  776. // StartTaskResp encapsuates the StartTask response
  777. type StartTaskResp struct {
  778. Tasks []Task `xml:"StartTaskResult>tasks>member"`
  779. Failures []Failure `xml:"StartTaskResult>failures>member"`
  780. RequestId string `xml:"ResponseMetadata>RequestId"`
  781. }
  782. // StartTask Starts a new task from the specified task definition on the specified
  783. // container instance or instances. If you want to use the default Amazon ECS scheduler
  784. // to place your task, use RunTask instead.
  785. func (e *ECS) StartTask(req *StartTaskReq) (*StartTaskResp, error) {
  786. if req == nil {
  787. return nil, fmt.Errorf("The req params cannot be nil")
  788. }
  789. params := makeParams("StartTask")
  790. if req.Cluster != "" {
  791. params["cluster"] = req.Cluster
  792. }
  793. if req.TaskDefinition != "" {
  794. params["taskDefinition"] = req.TaskDefinition
  795. }
  796. for i, ci := range req.ContainerInstances {
  797. params[fmt.Sprintf("containerInstances.member.%d", i+1)] = ci
  798. }
  799. for i, co := range req.Overrides.ContainerOverrides {
  800. key := fmt.Sprintf("overrides.containerOverrides.member.%d", i+1)
  801. params[fmt.Sprintf("%s.name", key)] = co.Name
  802. for k, cmd := range co.Command {
  803. params[fmt.Sprintf("%s.command.member.%d", key, k+1)] = cmd
  804. }
  805. }
  806. resp := new(StartTaskResp)
  807. if err := e.query(params, resp); err != nil {
  808. return nil, err
  809. }
  810. return resp, nil
  811. }
  812. // StopTaskReq encapsulates StopTask req params
  813. type StopTaskReq struct {
  814. Cluster string
  815. Task string
  816. }
  817. // StopTaskResp encapsuates the StopTask response
  818. type StopTaskResp struct {
  819. Task Task `xml:"StopTaskResult>task"`
  820. RequestId string `xml:"ResponseMetadata>RequestId"`
  821. }
  822. // StopTask stops a running task
  823. func (e *ECS) StopTask(req *StopTaskReq) (*StopTaskResp, error) {
  824. if req == nil {
  825. return nil, fmt.Errorf("The req params cannot be nil")
  826. }
  827. params := makeParams("StopTask")
  828. if req.Cluster != "" {
  829. params["cluster"] = req.Cluster
  830. }
  831. if req.Task != "" {
  832. params["task"] = req.Task
  833. }
  834. resp := new(StopTaskResp)
  835. if err := e.query(params, resp); err != nil {
  836. return nil, err
  837. }
  838. return resp, nil
  839. }
  840. // SubmitContainerStateChangeReq encapsulates SubmitContainerStateChange req params
  841. type SubmitContainerStateChangeReq struct {
  842. Cluster string
  843. ContainerName string
  844. ExitCode int32
  845. NetworkBindings []NetworkBinding
  846. Reason string
  847. Status string
  848. Task string
  849. }
  850. // SubmitContainerStateChangeResp encapsuates the SubmitContainerStateChange response
  851. type SubmitContainerStateChangeResp struct {
  852. Acknowledgment string `xml:"SubmitContainerStateChangeResult>acknowledgment"`
  853. RequestId string `xml:"ResponseMetadata>RequestId"`
  854. }
  855. // SubmitContainerStateChange is used to acknowledge that a container changed states.
  856. // Note: This action is only used by the Amazon EC2 Container Service agent,
  857. // and it is not intended for use outside of the agent.
  858. func (e *ECS) SubmitContainerStateChange(req *SubmitContainerStateChangeReq) (
  859. *SubmitContainerStateChangeResp, error) {
  860. if req == nil {
  861. return nil, fmt.Errorf("The req params cannot be nil")
  862. }
  863. params := makeParams("SubmitContainerStateChange")
  864. if req.Cluster != "" {
  865. params["cluster"] = req.Cluster
  866. }
  867. if req.ContainerName != "" {
  868. params["containerName"] = req.ContainerName
  869. }
  870. if req.Reason != "" {
  871. params["reason"] = req.Reason
  872. }
  873. if req.Status != "" {
  874. params["status"] = req.Status
  875. }
  876. if req.Task != "" {
  877. params["task"] = req.Task
  878. }
  879. for i, nb := range req.NetworkBindings {
  880. key := fmt.Sprintf("networkBindings.member.%d", i+1)
  881. params[fmt.Sprintf("%s.bindIp", key)] = nb.BindIp
  882. params[fmt.Sprintf("%s.containerPort", key)] = strconv.Itoa(int(nb.ContainerPort))
  883. params[fmt.Sprintf("%s.hostPort", key)] = strconv.Itoa(int(nb.HostPort))
  884. }
  885. params["exitCode"] = strconv.Itoa(int(req.ExitCode))
  886. resp := new(SubmitContainerStateChangeResp)
  887. if err := e.query(params, resp); err != nil {
  888. return nil, err
  889. }
  890. return resp, nil
  891. }
  892. // SubmitTaskStateChangeReq encapsulates SubmitTaskStateChange req params
  893. type SubmitTaskStateChangeReq struct {
  894. Cluster string
  895. Reason string
  896. Status string
  897. Task string
  898. }
  899. // SubmitTaskStateChangeResp encapsuates the SubmitTaskStateChange response
  900. type SubmitTaskStateChangeResp struct {
  901. Acknowledgment string `xml:"SubmitTaskStateChangeResult>acknowledgment"`
  902. RequestId string `xml:"ResponseMetadata>RequestId"`
  903. }
  904. // SubmitTaskStateChange is used to acknowledge that a task changed states.
  905. // Note: This action is only used by the Amazon EC2 Container Service agent,
  906. // and it is not intended for use outside of the agent.
  907. func (e *ECS) SubmitTaskStateChange(req *SubmitTaskStateChangeReq) (
  908. *SubmitTaskStateChangeResp, error) {
  909. if req == nil {
  910. return nil, fmt.Errorf("The req params cannot be nil")
  911. }
  912. params := makeParams("SubmitTaskStateChange")
  913. if req.Cluster != "" {
  914. params["cluster"] = req.Cluster
  915. }
  916. if req.Reason != "" {
  917. params["reason"] = req.Reason
  918. }
  919. if req.Status != "" {
  920. params["status"] = req.Status
  921. }
  922. if req.Task != "" {
  923. params["task"] = req.Task
  924. }
  925. resp := new(SubmitTaskStateChangeResp)
  926. if err := e.query(params, resp); err != nil {
  927. return nil, err
  928. }
  929. return resp, nil
  930. }