From 30d40d57ab8ba93a7e08bbf1e80a7c2f8f847c08 Mon Sep 17 00:00:00 2001 From: Dov Alperin Date: Tue, 19 Sep 2023 15:16:06 -0400 Subject: [PATCH 1/4] Migrate to flyctl/api as the source of truth --- go.mod | 12 +- go.sum | 36 +++-- internal/provider/machine_resource.go | 72 +++++---- pkg/apiv1/machines.go | 225 +++++++++++++------------- 4 files changed, 184 insertions(+), 161 deletions(-) diff --git a/go.mod b/go.mod index 071fe99..0e97307 100644 --- a/go.mod +++ b/go.mod @@ -10,11 +10,13 @@ require ( github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.3.0 github.com/imroc/req/v3 v3.37.1 + github.com/superfly/flyctl/api v0.0.0-20230919155046-5ec9cbf08d69 github.com/vektah/gqlparser/v2 v2.5.3 ) require ( github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/PuerkitoBio/rehttp v1.2.0 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect @@ -54,21 +56,23 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.1.0 // indirect github.com/onsi/ginkgo/v2 v2.11.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-19 v0.3.2 // indirect github.com/quic-go/qtls-go1-20 v0.2.2 // indirect github.com/quic-go/quic-go v0.36.0 // indirect github.com/refraction-networking/utls v1.3.2 // indirect + github.com/superfly/graphql v0.2.4 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zclconf/go-cty v1.13.2 // indirect - golang.org/x/crypto v0.10.0 // indirect + golang.org/x/crypto v0.12.0 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/mod v0.11.0 // indirect - golang.org/x/net v0.11.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.10.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect golang.org/x/tools v0.10.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect diff --git a/go.sum b/go.sum index d69f436..f222439 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4D github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/PuerkitoBio/rehttp v1.2.0 h1:V8MGVcDwR+u/xwLlMrw5YZONDm3JISEKqwJTiIuJA+s= +github.com/PuerkitoBio/rehttp v1.2.0/go.mod h1:LUwKPoDbDIA2RL5wYZCNsQ90cx4OJ4AWBmq6KzWZL1s= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= @@ -15,6 +17,10 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJE github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48= +github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= @@ -23,6 +29,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -111,6 +118,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -135,6 +143,8 @@ github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= @@ -153,8 +163,13 @@ github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ys github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/superfly/flyctl/api v0.0.0-20230919155046-5ec9cbf08d69 h1:lB3wFzZ/+rSDB6609wZRAW2SY51WdcnFWd1Vd5v//IU= +github.com/superfly/flyctl/api v0.0.0-20230919155046-5ec9cbf08d69/go.mod h1:rSR4fmkaMYHEw7vHSYfZeZd9pJYhk7VADmXvvt1iEPQ= +github.com/superfly/graphql v0.2.4 h1:Av8hSk4x8WvKJ6MTnEwrLknSVSGPc7DWpgT3z/kt3PU= +github.com/superfly/graphql v0.2.4/go.mod h1:CVfDl31srm8HnJ9udwLu6hFNUW/P6GUM2dKcG1YQ8jc= github.com/vektah/gqlparser/v2 v2.5.3 h1:goUwv4+blhtwR3GwefadPVI4ubYc/WZSypljWMQa6IE= github.com/vektah/gqlparser/v2 v2.5.3/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -171,8 +186,8 @@ github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -183,8 +198,9 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -194,6 +210,7 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -201,15 +218,16 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= diff --git a/internal/provider/machine_resource.go b/internal/provider/machine_resource.go index f324666..0c9b9f6 100644 --- a/internal/provider/machine_resource.go +++ b/internal/provider/machine_resource.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "github.com/superfly/flyctl/api" "strings" "github.com/fly-apps/terraform-provider-fly/pkg/apiv1" @@ -213,30 +214,31 @@ func (r *flyMachineResource) Schema(_ context.Context, _ resource.SchemaRequest, } } -func TfServicesToServices(input []TfService) []apiv1.Service { - services := make([]apiv1.Service, 0) +func TfServicesToServices(input []TfService) []api.MachineService { + services := make([]api.MachineService, 0) for _, s := range input { - var ports []apiv1.Port + var ports []api.MachinePort for _, j := range s.Ports { var handlers []string for _, k := range j.Handlers { handlers = append(handlers, k.ValueString()) } - ports = append(ports, apiv1.Port{ - Port: j.Port.ValueInt64(), + p := int(j.Port.ValueInt64()) + ports = append(ports, api.MachinePort{ + Port: &p, Handlers: handlers, }) } - services = append(services, apiv1.Service{ + services = append(services, api.MachineService{ Ports: ports, Protocol: s.Protocol.ValueString(), - InternalPort: s.InternalPort.ValueInt64(), + InternalPort: int(s.InternalPort.ValueInt64()), }) } return services } -func ServicesToTfServices(input []apiv1.Service) []TfService { +func ServicesToTfServices(input []api.MachineService) []TfService { tfservices := make([]TfService, 0) for _, s := range input { var tfports []TfPort @@ -246,14 +248,14 @@ func ServicesToTfServices(input []apiv1.Service) []TfService { handlers = append(handlers, types.StringValue(k)) } tfports = append(tfports, TfPort{ - Port: types.Int64Value(j.Port), + Port: types.Int64Value(int64(*j.Port)), Handlers: handlers, }) } tfservices = append(tfservices, TfService{ Ports: tfports, Protocol: types.StringValue(s.Protocol), - InternalPort: types.Int64Value(s.InternalPort), + InternalPort: types.Int64Value(int64(s.InternalPort)), }) } return tfservices @@ -269,13 +271,13 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ } services := TfServicesToServices(data.Services) - createReq := apiv1.MachineCreateOrUpdateRequest{ + createReq := api.Machine{ Name: data.Name.ValueString(), Region: data.Region.ValueString(), - Config: apiv1.MachineConfig{ + Config: &api.MachineConfig{ Image: data.Image.ValueString(), Services: services, - Init: apiv1.InitConfig{ + Init: api.MachineInit{ Cmd: data.Cmd, Entrypoint: data.Entrypoint, Exec: data.Exec, @@ -284,13 +286,13 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ } if !data.Cpus.IsUnknown() { - createReq.Config.Guest.Cpus = int(data.Cpus.ValueInt64()) + createReq.Config.Guest.CPUs = int(data.Cpus.ValueInt64()) } if !data.CpuType.IsUnknown() { - createReq.Config.Guest.CpuType = data.CpuType.ValueString() + createReq.Config.Guest.CPUKind = data.CpuType.ValueString() } if !data.MemoryMb.IsUnknown() { - createReq.Config.Guest.MemoryMb = int(data.MemoryMb.ValueInt64()) + createReq.Config.Guest.MemoryMB = int(data.MemoryMb.ValueInt64()) } if !data.Env.IsUnknown() { @@ -299,9 +301,9 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ createReq.Config.Env = env } if len(data.Mounts) > 0 { - var mounts []apiv1.MachineMount + var mounts []api.MachineMount for _, m := range data.Mounts { - mounts = append(mounts, apiv1.MachineMount{ + mounts = append(mounts, api.MachineMount{ Encrypted: m.Encrypted.ValueBool(), Path: m.Path.ValueString(), SizeGb: int(m.SizeGb.ValueInt64()), @@ -313,7 +315,7 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) - var newMachine apiv1.MachineResponse + var newMachine api.Machine err := machineAPI.CreateMachine(createReq, data.App.ValueString(), &newMachine) if err != nil { resp.Diagnostics.AddError("Failed to create machine", err.Error()) @@ -339,8 +341,8 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ App: data.App, PrivateIP: types.StringValue(newMachine.PrivateIP), Image: types.StringValue(newMachine.Config.Image), - Cpus: types.Int64Value(int64(newMachine.Config.Guest.Cpus)), - MemoryMb: types.Int64Value(int64(newMachine.Config.Guest.MemoryMb)), + Cpus: types.Int64Value(int64(newMachine.Config.Guest.CPUs)), + MemoryMb: types.Int64Value(int64(newMachine.Config.Guest.MemoryMB)), CpuType: types.StringValue(newMachine.Config.Guest.CPUKind), Cmd: newMachine.Config.Init.Cmd, Entrypoint: newMachine.Config.Init.Entrypoint, @@ -383,7 +385,7 @@ func (r *flyMachineResource) Read(ctx context.Context, req resource.ReadRequest, machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) - var machine apiv1.MachineResponse + var machine api.Machine _, err := machineAPI.ReadMachine(data.App.ValueString(), data.Id.ValueString(), &machine) if err != nil { @@ -408,8 +410,8 @@ func (r *flyMachineResource) Read(ctx context.Context, req resource.ReadRequest, App: data.App, PrivateIP: types.StringValue(machine.PrivateIP), Image: types.StringValue(machine.Config.Image), - Cpus: types.Int64Value(int64(machine.Config.Guest.Cpus)), - MemoryMb: types.Int64Value(int64(machine.Config.Guest.MemoryMb)), + Cpus: types.Int64Value(int64(machine.Config.Guest.CPUs)), + MemoryMb: types.Int64Value(int64(machine.Config.Guest.MemoryMB)), CpuType: types.StringValue(machine.Config.Guest.CPUKind), Cmd: machine.Config.Init.Cmd, Entrypoint: machine.Config.Init.Entrypoint, @@ -466,13 +468,13 @@ func (r *flyMachineResource) Update(ctx context.Context, req resource.UpdateRequ services := TfServicesToServices(plan.Services) - updateReq := apiv1.MachineCreateOrUpdateRequest{ + updateReq := api.Machine{ Name: plan.Name.ValueString(), Region: state.Region.ValueString(), - Config: apiv1.MachineConfig{ + Config: &api.MachineConfig{ Image: plan.Image.ValueString(), Services: services, - Init: apiv1.InitConfig{ + Init: api.MachineInit{ Cmd: plan.Cmd, Entrypoint: plan.Entrypoint, Exec: plan.Exec, @@ -481,13 +483,13 @@ func (r *flyMachineResource) Update(ctx context.Context, req resource.UpdateRequ } if !plan.Cpus.IsUnknown() { - updateReq.Config.Guest.Cpus = int(plan.Cpus.ValueInt64()) + updateReq.Config.Guest.CPUs = int(plan.Cpus.ValueInt64()) } if !plan.CpuType.IsUnknown() { - updateReq.Config.Guest.CpuType = plan.CpuType.ValueString() + updateReq.Config.Guest.CPUKind = plan.CpuType.ValueString() } if !plan.MemoryMb.IsUnknown() { - updateReq.Config.Guest.MemoryMb = int(plan.MemoryMb.ValueInt64()) + updateReq.Config.Guest.MemoryMB = int(plan.MemoryMb.ValueInt64()) } if plan.Env.IsNull() { env := map[string]string{} @@ -501,9 +503,9 @@ func (r *flyMachineResource) Update(ctx context.Context, req resource.UpdateRequ } if len(plan.Mounts) > 0 { - var mounts []apiv1.MachineMount + var mounts []api.MachineMount for _, m := range plan.Mounts { - mounts = append(mounts, apiv1.MachineMount{ + mounts = append(mounts, api.MachineMount{ Encrypted: m.Encrypted.ValueBool(), Path: m.Path.ValueString(), SizeGb: int(m.SizeGb.ValueInt64()), @@ -515,7 +517,7 @@ func (r *flyMachineResource) Update(ctx context.Context, req resource.UpdateRequ machineApi := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) - var updatedMachine apiv1.MachineResponse + var updatedMachine api.Machine err := machineApi.UpdateMachine(updateReq, state.App.ValueString(), state.Id.ValueString(), &updatedMachine) if err != nil { @@ -536,8 +538,8 @@ func (r *flyMachineResource) Update(ctx context.Context, req resource.UpdateRequ App: state.App, PrivateIP: types.StringValue(updatedMachine.PrivateIP), Image: types.StringValue(updatedMachine.Config.Image), - Cpus: types.Int64Value(int64(updatedMachine.Config.Guest.Cpus)), - MemoryMb: types.Int64Value(int64(updatedMachine.Config.Guest.MemoryMb)), + Cpus: types.Int64Value(int64(updatedMachine.Config.Guest.CPUs)), + MemoryMb: types.Int64Value(int64(updatedMachine.Config.Guest.MemoryMB)), CpuType: types.StringValue(updatedMachine.Config.Guest.CPUKind), Cmd: updatedMachine.Config.Init.Cmd, Entrypoint: updatedMachine.Config.Init.Entrypoint, diff --git a/pkg/apiv1/machines.go b/pkg/apiv1/machines.go index 9470c14..e1ca2cb 100644 --- a/pkg/apiv1/machines.go +++ b/pkg/apiv1/machines.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/Khan/genqlient/graphql" hreq "github.com/imroc/req/v3" + "github.com/superfly/flyctl/api" "net/http" "time" ) @@ -17,98 +18,98 @@ type MachineAPI struct { endpoint string } -type MachineMount struct { - Encrypted bool `json:"encrypted,omitempty"` - Path string `json:"path"` - SizeGb int `json:"size_gb,omitempty"` - Volume string `json:"volume"` -} - -type Port struct { - Port int64 `json:"port"` - Handlers []string `json:"handlers"` -} - -type Service struct { - Ports []Port `json:"ports"` - Protocol string `json:"protocol"` - InternalPort int64 `json:"internal_port"` -} - -type InitConfig struct { - Cmd []string `json:"cmd,omitempty"` - Entrypoint []string `json:"entrypoint,omitempty"` - Exec []string `json:"exec,omitempty"` -} - -type MachineConfig struct { - Image string `json:"image"` - Env map[string]string `json:"env"` - Init InitConfig `json:"init,omitempty"` - Mounts []MachineMount `json:"mounts,omitempty"` - Services []Service `json:"services"` - Guest GuestConfig `json:"guest,omitempty"` -} - -type GuestConfig struct { - Cpus int `json:"cpus,omitempty"` - MemoryMb int `json:"memory_mb,omitempty"` - CpuType string `json:"cpu_kind,omitempty"` -} - -type MachineCreateOrUpdateRequest struct { - Name string `json:"name"` - Region string `json:"region"` - Config MachineConfig `json:"config"` -} - -type MachineResponse struct { - ID string `json:"id"` - Name string `json:"name"` - State string `json:"state"` - Region string `json:"region"` - InstanceID string `json:"instance_id"` - PrivateIP string `json:"private_ip"` - Config struct { - Env map[string]string `json:"env"` - Init struct { - Exec []string `json:"exec"` - Entrypoint []string `json:"entrypoint"` - Cmd []string `json:"cmd"` - //Tty bool `json:"tty"` - } `json:"init"` - Image string `json:"image"` - Metadata interface{} `json:"metadata"` - Restart struct { - Policy string `json:"policy"` - } `json:"restart"` - Services []Service `json:"services"` - Mounts []MachineMount `json:"mounts"` - Guest struct { - CPUKind string `json:"cpu_kind"` - Cpus int `json:"cpus"` - MemoryMb int `json:"memory_mb"` - } `json:"guest"` - } `json:"config"` - ImageRef struct { - Registry string `json:"registry"` - Repository string `json:"repository"` - Tag string `json:"tag"` - Digest string `json:"digest"` - Labels struct { - } `json:"labels"` - } `json:"image_ref"` - CreatedAt time.Time `json:"created_at"` -} - -type MachineLease struct { - Status string `json:"status"` - Data struct { - Nonce string `json:"nonce"` - ExpiresAt int64 `json:"expires_at"` - Owner string `json:"owner"` - } -} +//type MachineMount struct { +// Encrypted bool `json:"encrypted,omitempty"` +// Path string `json:"path"` +// SizeGb int `json:"size_gb,omitempty"` +// Volume string `json:"volume"` +//} +// +//type Port struct { +// Port int64 `json:"port"` +// Handlers []string `json:"handlers"` +//} +// +//type Service struct { +// Ports []Port `json:"ports"` +// Protocol string `json:"protocol"` +// InternalPort int64 `json:"internal_port"` +//} +// +//type InitConfig struct { +// Cmd []string `json:"cmd,omitempty"` +// Entrypoint []string `json:"entrypoint,omitempty"` +// Exec []string `json:"exec,omitempty"` +//} +// +//type MachineConfig struct { +// Image string `json:"image"` +// Env map[string]string `json:"env"` +// Init InitConfig `json:"init,omitempty"` +// Mounts []MachineMount `json:"mounts,omitempty"` +// Services []Service `json:"services"` +// Guest GuestConfig `json:"guest,omitempty"` +//} +// +//type GuestConfig struct { +// Cpus int `json:"cpus,omitempty"` +// MemoryMb int `json:"memory_mb,omitempty"` +// CpuType string `json:"cpu_kind,omitempty"` +//} +// +//type MachineCreateOrUpdateRequest struct { +// Name string `json:"name"` +// Region string `json:"region"` +// Config MachineConfig `json:"config"` +//} +// +//type MachineResponse struct { +// ID string `json:"id"` +// Name string `json:"name"` +// State string `json:"state"` +// Region string `json:"region"` +// InstanceID string `json:"instance_id"` +// PrivateIP string `json:"private_ip"` +// Config struct { +// Env map[string]string `json:"env"` +// Init struct { +// Exec []string `json:"exec"` +// Entrypoint []string `json:"entrypoint"` +// Cmd []string `json:"cmd"` +// //Tty bool `json:"tty"` +// } `json:"init"` +// Image string `json:"image"` +// Metadata interface{} `json:"metadata"` +// Restart struct { +// Policy string `json:"policy"` +// } `json:"restart"` +// Services []Service `json:"services"` +// Mounts []MachineMount `json:"mounts"` +// Guest struct { +// CPUKind string `json:"cpu_kind"` +// Cpus int `json:"cpus"` +// MemoryMb int `json:"memory_mb"` +// } `json:"guest"` +// } `json:"config"` +// ImageRef struct { +// Registry string `json:"registry"` +// Repository string `json:"repository"` +// Tag string `json:"tag"` +// Digest string `json:"digest"` +// Labels struct { +// } `json:"labels"` +// } `json:"image_ref"` +// CreatedAt time.Time `json:"created_at"` +//} +// +//type MachineLease struct { +// Status string `json:"status"` +// Data struct { +// Nonce string `json:"nonce"` +// ExpiresAt int64 `json:"expires_at"` +// Owner string `json:"owner"` +// } +//} func NewMachineAPI(httpClient *hreq.Client, endpoint string) *MachineAPI { return &MachineAPI{ @@ -117,8 +118,8 @@ func NewMachineAPI(httpClient *hreq.Client, endpoint string) *MachineAPI { } } -func (a *MachineAPI) LockMachine(app string, id string, timeout int) (*MachineLease, error) { - var res MachineLease +func (a *MachineAPI) LockMachine(app string, id string, timeout int) (*api.MachineLease, error) { + var res api.MachineLease _, err := a.httpClient.R().SetResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s/lease/?ttl=%d", a.endpoint, app, id, timeout)) if err != nil { return nil, err @@ -126,7 +127,7 @@ func (a *MachineAPI) LockMachine(app string, id string, timeout int) (*MachineLe return &res, nil } -func (a *MachineAPI) ReleaseMachine(lease MachineLease, app string, id string) error { +func (a *MachineAPI) ReleaseMachine(lease api.MachineLease, app string, id string) error { _, err := a.httpClient.R().SetHeader(NonceHeader, lease.Data.Nonce).Delete(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s/lease", a.endpoint, app, id)) if err != nil { return err @@ -140,15 +141,15 @@ func (a *MachineAPI) WaitForMachine(app string, id string, instanceID string) er } // CreateMachine takes a MachineCreateOrUpdateRequest and creates the requested machine in the given app and then writes the response into the `res` param -func (a *MachineAPI) CreateMachine(req MachineCreateOrUpdateRequest, app string, res *MachineResponse) error { - if req.Config.Guest.CpuType == "" { - req.Config.Guest.CpuType = "shared" +func (a *MachineAPI) CreateMachine(req api.Machine, app string, res *api.Machine) error { + if req.Config.Guest.CPUKind == "" { + req.Config.Guest.CPUKind = "shared" } - if req.Config.Guest.Cpus == 0 { - req.Config.Guest.Cpus = 1 + if req.Config.Guest.CPUs == 0 { + req.Config.Guest.CPUs = 1 } - if req.Config.Guest.MemoryMb == 0 { - req.Config.Guest.MemoryMb = 256 + if req.Config.Guest.MemoryMB == 0 { + req.Config.Guest.MemoryMB = 256 } createResponse, err := a.httpClient.R().SetBody(req).SetResult(res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines", a.endpoint, app)) @@ -162,17 +163,15 @@ func (a *MachineAPI) CreateMachine(req MachineCreateOrUpdateRequest, app string, return nil } -func (a *MachineAPI) UpdateMachine(req MachineCreateOrUpdateRequest, app string, id string, res *MachineResponse) error { - if req.Config.Guest.CpuType == "" { - req.Config.Guest.CpuType = "shared" +func (a *MachineAPI) UpdateMachine(req api.Machine, app string, id string, res *api.Machine) error { + if req.Config.Guest.CPUKind == "" { + req.Config.Guest.CPUKind = "shared" } - if req.Config.Guest.Cpus == 0 { - //You can't have a machine with no cpus - req.Config.Guest.Cpus = 1 + if req.Config.Guest.CPUs == 0 { + req.Config.Guest.CPUs = 1 } - if req.Config.Guest.MemoryMb == 0 { - //You can't have a machine with no memory - req.Config.Guest.MemoryMb = 256 + if req.Config.Guest.MemoryMB == 0 { + req.Config.Guest.MemoryMB = 256 } lease, err := a.LockMachine(app, id, 30) if err != nil { @@ -192,14 +191,14 @@ func (a *MachineAPI) UpdateMachine(req MachineCreateOrUpdateRequest, app string, return nil } -func (a *MachineAPI) ReadMachine(app string, id string, res *MachineResponse) (*hreq.Response, error) { +func (a *MachineAPI) ReadMachine(app string, id string, res *api.Machine) (*hreq.Response, error) { return a.httpClient.R().SetResult(res).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) } func (a *MachineAPI) DeleteMachine(app string, id string, maxRetries int) error { deleted := false for i := 0; i < maxRetries; i++ { - var machine MachineResponse + var machine api.Machine readResponse, err := a.httpClient.R().SetResult(&machine).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) if err != nil { return err From 00902befc76b6feb6a486ba19a797928c494008e Mon Sep 17 00:00:00 2001 From: Dov Alperin Date: Tue, 19 Sep 2023 16:32:14 -0400 Subject: [PATCH 2/4] Make volumes use flaps --- internal/provider/volume_data_source.go | 35 ++++++++--------- internal/provider/volume_resource.go | 50 ++++++++++++------------- pkg/apiv1/machines.go | 32 ++++++++++++++++ 3 files changed, 72 insertions(+), 45 deletions(-) diff --git a/internal/provider/volume_data_source.go b/internal/provider/volume_data_source.go index 2193d69..1c7b6a7 100644 --- a/internal/provider/volume_data_source.go +++ b/internal/provider/volume_data_source.go @@ -2,10 +2,9 @@ package provider import ( "context" + "github.com/fly-apps/terraform-provider-fly/pkg/apiv1" "regexp" - basegql "github.com/Khan/genqlient/graphql" - "github.com/fly-apps/terraform-provider-fly/graphql" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -18,7 +17,7 @@ var _ datasource.DataSource = &volumeDataSourceType{} var _ datasource.DataSourceWithConfigure = &appDataSourceType{} type volumeDataSourceType struct { - client *basegql.Client + config ProviderConfig } func NewVolumeDataSource() datasource.DataSource { @@ -33,9 +32,7 @@ func (d *volumeDataSourceType) Configure(_ context.Context, req datasource.Confi if req.ProviderData == nil { return } - - config := req.ProviderData.(ProviderConfig) - d.client = config.gqclient + d.config = req.ProviderData.(ProviderConfig) } // Matches Schema @@ -87,27 +84,27 @@ func (d *volumeDataSourceType) Read(ctx context.Context, req datasource.ReadRequ diags := req.Config.Get(ctx, &data) resp.Diagnostics.Append(diags...) - // strip leading vol_ off name - internalId := data.Id.ValueString()[4:] + id := data.Id.ValueString() + // New flaps based volumes don't have this prefix I'm pretty sure + if id[:4] == "vol_" { + // strip leading vol_ off name + id = id[4:] + } app := data.Appid.ValueString() - query, err := graphql.VolumeQuery(ctx, *d.client, app, internalId) + machineAPI := apiv1.NewMachineAPI(d.config.httpClient, d.config.httpEndpoint) + query, err := machineAPI.GetVolume(ctx, id, app) if err != nil { resp.Diagnostics.AddError("Query failed", err.Error()) return } - // this query will currently still return success if it finds nothing, so check it: - if query.App.Volume.Id == "" { - resp.Diagnostics.AddError("Query failed", "Could not find matching volume") - } - data = volumeDataSourceOutput{ - Id: types.StringValue(query.App.Volume.Id), - Name: types.StringValue(query.App.Volume.Name), - Size: types.Int64Value(int64(query.App.Volume.SizeGb)), - Appid: data.Appid, - Region: types.StringValue(query.App.Volume.Region), + Id: types.StringValue(query.ID), + Name: types.StringValue(query.Name), + Size: types.Int64Value(int64(query.SizeGb)), + Appid: types.StringValue(data.Appid.ValueString()), + Region: types.StringValue(query.Region), } if resp.Diagnostics.HasError() { diff --git a/internal/provider/volume_resource.go b/internal/provider/volume_resource.go index 0fd3e8f..cef807d 100644 --- a/internal/provider/volume_resource.go +++ b/internal/provider/volume_resource.go @@ -3,11 +3,10 @@ package provider import ( "context" "fmt" + "github.com/fly-apps/terraform-provider-fly/pkg/apiv1" "regexp" "strings" - basegql "github.com/Khan/genqlient/graphql" - "github.com/fly-apps/terraform-provider-fly/graphql" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -22,7 +21,7 @@ var _ resource.ResourceWithConfigure = &flyVolumeResource{} var _ resource.ResourceWithImportState = &flyVolumeResource{} type flyVolumeResource struct { - client *basegql.Client + config ProviderConfig } func NewVolumeResource() resource.Resource { @@ -37,9 +36,7 @@ func (r *flyVolumeResource) Configure(_ context.Context, req resource.ConfigureR if req.ProviderData == nil { return } - - config := req.ProviderData.(ProviderConfig) - r.client = config.gqclient + r.config = req.ProviderData.(ProviderConfig) } type flyVolumeResourceData struct { @@ -91,18 +88,19 @@ func (r *flyVolumeResource) Create(ctx context.Context, req resource.CreateReque diags := req.Plan.Get(ctx, &data) resp.Diagnostics.Append(diags...) - q, err := graphql.CreateVolume(ctx, *r.client, data.Appid.ValueString(), data.Name.ValueString(), data.Region.ValueString(), int(data.Size.ValueInt64())) + machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) + q, err := machineAPI.CreateVolume(ctx, data.Appid.ValueString(), data.Name.ValueString(), data.Region.ValueString(), int(data.Size.ValueInt64())) if err != nil { resp.Diagnostics.AddError("Failed to create volume", err.Error()) return } data = flyVolumeResourceData{ - Id: types.StringValue(q.CreateVolume.Volume.Id), - Name: types.StringValue(q.CreateVolume.Volume.Name), - Size: types.Int64Value(int64(q.CreateVolume.Volume.SizeGb)), + Id: types.StringValue(q.ID), + Name: types.StringValue(q.Name), + Size: types.Int64Value(int64(q.SizeGb)), Appid: types.StringValue(data.Appid.ValueString()), - Region: types.StringValue(q.CreateVolume.Volume.Region), + Region: types.StringValue(q.Region), } tflog.Info(ctx, fmt.Sprintf("%+v", data)) @@ -120,28 +118,27 @@ func (r *flyVolumeResource) Read(ctx context.Context, req resource.ReadRequest, diags := req.State.Get(ctx, &data) resp.Diagnostics.Append(diags...) - // strip leading vol_ off name - internalId := data.Id.ValueString()[4:] + id := data.Id.ValueString() + // New flaps based volumes don't have this prefix I'm pretty sure + if id[:4] == "vol_" { + // strip leading vol_ off name + id = id[4:] + } app := data.Appid.ValueString() - query, err := graphql.VolumeQuery(ctx, *r.client, app, internalId) + machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) + query, err := machineAPI.GetVolume(ctx, id, app) if err != nil { - resp.Diagnostics.AddError("Read: query failed", err.Error()) + resp.Diagnostics.AddError("Query failed", err.Error()) return } - // this query will currently still return success if it finds nothing, so check it: - if query.App.Volume.Id == "" { - resp.Diagnostics.AddError("Query failed", "Could not find matching volume") - } - data = flyVolumeResourceData{ - Id: types.StringValue(query.App.Volume.Id), - Name: types.StringValue(query.App.Volume.Name), - Size: types.Int64Value(int64(query.App.Volume.SizeGb)), + Id: types.StringValue(query.ID), + Name: types.StringValue(query.Name), + Size: types.Int64Value(int64(query.SizeGb)), Appid: types.StringValue(data.Appid.ValueString()), - Region: types.StringValue(query.App.Volume.Region), - // Internalid: types.StringValue(query.App.Volume.InternalId), + Region: types.StringValue(query.Region), } diags = resp.State.Set(ctx, &data) @@ -163,7 +160,8 @@ func (r *flyVolumeResource) Delete(ctx context.Context, req resource.DeleteReque resp.Diagnostics.Append(diags...) if !data.Id.IsUnknown() && !data.Id.IsNull() && data.Id.ValueString() != "" { - _, err := graphql.DeleteVolume(ctx, *r.client, data.Id.ValueString()) + machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) + err := machineAPI.DeleteVolume(ctx, data.Appid.ValueString(), data.Id.ValueString()) if err != nil { resp.Diagnostics.AddError("Delete volume failed", err.Error()) return diff --git a/pkg/apiv1/machines.go b/pkg/apiv1/machines.go index e1ca2cb..2d9cf68 100644 --- a/pkg/apiv1/machines.go +++ b/pkg/apiv1/machines.go @@ -1,6 +1,7 @@ package apiv1 import ( + "context" "errors" "fmt" "github.com/Khan/genqlient/graphql" @@ -228,3 +229,34 @@ func (a *MachineAPI) DeleteMachine(app string, id string, maxRetries int) error } return nil } + +func (a *MachineAPI) CreateVolume(ctx context.Context, name, app, region string, size int) (*api.Volume, error) { + var res api.Volume + _, err := a.httpClient.R().SetContext(ctx).SetBody(api.CreateVolumeRequest{ + Name: name, + Region: region, + SizeGb: &size, + }).SetResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/volumes", a.endpoint, app)) + if err != nil { + return nil, err + } + return &res, nil +} + +func (a *MachineAPI) GetVolume(ctx context.Context, id, app string) (*api.Volume, error) { + var res api.Volume + _, err := a.httpClient.R().SetContext(ctx).SetResult(&res).Get(fmt.Sprintf("http://%s/v1/apps/%s/volumes/%s", a.endpoint, app, id)) + if err != nil { + return nil, err + } + + return &res, nil +} + +func (a *MachineAPI) DeleteVolume(ctx context.Context, id, app string) error { + _, err := a.httpClient.R().SetContext(ctx).Delete(fmt.Sprintf("http://%s/v1/apps/%s/volumes/%s", a.endpoint, app, id)) + if err != nil { + return err + } + return nil +} From e07d13fb99fd371b6c05c138d74ea4a9fb153b91 Mon Sep 17 00:00:00 2001 From: Dov Alperin Date: Tue, 19 Sep 2023 18:19:42 -0400 Subject: [PATCH 3/4] Futz with pointers --- pkg/apiv1/machines.go | 121 +++++------------------------------------- 1 file changed, 14 insertions(+), 107 deletions(-) diff --git a/pkg/apiv1/machines.go b/pkg/apiv1/machines.go index 2d9cf68..c81e51f 100644 --- a/pkg/apiv1/machines.go +++ b/pkg/apiv1/machines.go @@ -19,99 +19,6 @@ type MachineAPI struct { endpoint string } -//type MachineMount struct { -// Encrypted bool `json:"encrypted,omitempty"` -// Path string `json:"path"` -// SizeGb int `json:"size_gb,omitempty"` -// Volume string `json:"volume"` -//} -// -//type Port struct { -// Port int64 `json:"port"` -// Handlers []string `json:"handlers"` -//} -// -//type Service struct { -// Ports []Port `json:"ports"` -// Protocol string `json:"protocol"` -// InternalPort int64 `json:"internal_port"` -//} -// -//type InitConfig struct { -// Cmd []string `json:"cmd,omitempty"` -// Entrypoint []string `json:"entrypoint,omitempty"` -// Exec []string `json:"exec,omitempty"` -//} -// -//type MachineConfig struct { -// Image string `json:"image"` -// Env map[string]string `json:"env"` -// Init InitConfig `json:"init,omitempty"` -// Mounts []MachineMount `json:"mounts,omitempty"` -// Services []Service `json:"services"` -// Guest GuestConfig `json:"guest,omitempty"` -//} -// -//type GuestConfig struct { -// Cpus int `json:"cpus,omitempty"` -// MemoryMb int `json:"memory_mb,omitempty"` -// CpuType string `json:"cpu_kind,omitempty"` -//} -// -//type MachineCreateOrUpdateRequest struct { -// Name string `json:"name"` -// Region string `json:"region"` -// Config MachineConfig `json:"config"` -//} -// -//type MachineResponse struct { -// ID string `json:"id"` -// Name string `json:"name"` -// State string `json:"state"` -// Region string `json:"region"` -// InstanceID string `json:"instance_id"` -// PrivateIP string `json:"private_ip"` -// Config struct { -// Env map[string]string `json:"env"` -// Init struct { -// Exec []string `json:"exec"` -// Entrypoint []string `json:"entrypoint"` -// Cmd []string `json:"cmd"` -// //Tty bool `json:"tty"` -// } `json:"init"` -// Image string `json:"image"` -// Metadata interface{} `json:"metadata"` -// Restart struct { -// Policy string `json:"policy"` -// } `json:"restart"` -// Services []Service `json:"services"` -// Mounts []MachineMount `json:"mounts"` -// Guest struct { -// CPUKind string `json:"cpu_kind"` -// Cpus int `json:"cpus"` -// MemoryMb int `json:"memory_mb"` -// } `json:"guest"` -// } `json:"config"` -// ImageRef struct { -// Registry string `json:"registry"` -// Repository string `json:"repository"` -// Tag string `json:"tag"` -// Digest string `json:"digest"` -// Labels struct { -// } `json:"labels"` -// } `json:"image_ref"` -// CreatedAt time.Time `json:"created_at"` -//} -// -//type MachineLease struct { -// Status string `json:"status"` -// Data struct { -// Nonce string `json:"nonce"` -// ExpiresAt int64 `json:"expires_at"` -// Owner string `json:"owner"` -// } -//} - func NewMachineAPI(httpClient *hreq.Client, endpoint string) *MachineAPI { return &MachineAPI{ httpClient: httpClient, @@ -120,12 +27,12 @@ func NewMachineAPI(httpClient *hreq.Client, endpoint string) *MachineAPI { } func (a *MachineAPI) LockMachine(app string, id string, timeout int) (*api.MachineLease, error) { - var res api.MachineLease - _, err := a.httpClient.R().SetResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s/lease/?ttl=%d", a.endpoint, app, id, timeout)) + var res *api.MachineLease + _, err := a.httpClient.R().SetSuccessResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s/lease/?ttl=%d", a.endpoint, app, id, timeout)) if err != nil { return nil, err } - return &res, nil + return res, nil } func (a *MachineAPI) ReleaseMachine(lease api.MachineLease, app string, id string) error { @@ -152,7 +59,7 @@ func (a *MachineAPI) CreateMachine(req api.Machine, app string, res *api.Machine if req.Config.Guest.MemoryMB == 0 { req.Config.Guest.MemoryMB = 256 } - createResponse, err := a.httpClient.R().SetBody(req).SetResult(res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines", a.endpoint, app)) + createResponse, err := a.httpClient.R().SetBody(req).SetSuccessResult(res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines", a.endpoint, app)) if err != nil { return err @@ -178,7 +85,7 @@ func (a *MachineAPI) UpdateMachine(req api.Machine, app string, id string, res * if err != nil { return err } - reqRes, err := a.httpClient.R().SetBody(req).SetResult(res).SetHeader(NonceHeader, lease.Data.Nonce).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) + reqRes, err := a.httpClient.R().SetBody(req).SetSuccessResult(res).SetHeader(NonceHeader, lease.Data.Nonce).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) if err != nil { return err } @@ -193,14 +100,14 @@ func (a *MachineAPI) UpdateMachine(req api.Machine, app string, id string, res * } func (a *MachineAPI) ReadMachine(app string, id string, res *api.Machine) (*hreq.Response, error) { - return a.httpClient.R().SetResult(res).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) + return a.httpClient.R().SetSuccessResult(res).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) } func (a *MachineAPI) DeleteMachine(app string, id string, maxRetries int) error { deleted := false for i := 0; i < maxRetries; i++ { - var machine api.Machine - readResponse, err := a.httpClient.R().SetResult(&machine).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) + var machine *api.Machine + readResponse, err := a.httpClient.R().SetSuccessResult(&machine).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) if err != nil { return err } @@ -231,26 +138,26 @@ func (a *MachineAPI) DeleteMachine(app string, id string, maxRetries int) error } func (a *MachineAPI) CreateVolume(ctx context.Context, name, app, region string, size int) (*api.Volume, error) { - var res api.Volume + var res *api.Volume _, err := a.httpClient.R().SetContext(ctx).SetBody(api.CreateVolumeRequest{ Name: name, Region: region, SizeGb: &size, - }).SetResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/volumes", a.endpoint, app)) + }).SetSuccessResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/volumes", a.endpoint, app)) if err != nil { return nil, err } - return &res, nil + return res, nil } func (a *MachineAPI) GetVolume(ctx context.Context, id, app string) (*api.Volume, error) { - var res api.Volume - _, err := a.httpClient.R().SetContext(ctx).SetResult(&res).Get(fmt.Sprintf("http://%s/v1/apps/%s/volumes/%s", a.endpoint, app, id)) + var res *api.Volume + _, err := a.httpClient.R().SetContext(ctx).SetSuccessResult(&res).Get(fmt.Sprintf("http://%s/v1/apps/%s/volumes/%s", a.endpoint, app, id)) if err != nil { return nil, err } - return &res, nil + return res, nil } func (a *MachineAPI) DeleteVolume(ctx context.Context, id, app string) error { From 1b7c880e570f8ee790fb395976dd7679fe3b303f Mon Sep 17 00:00:00 2001 From: Dov Alperin Date: Tue, 19 Sep 2023 18:52:57 -0400 Subject: [PATCH 4/4] WIP --- go.mod | 5 +- go.sum | 10 ++-- internal/provider/machine_resource.go | 55 +++++++++--------- pkg/apiv1/machines.go | 81 +++++++++++++++------------ 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/go.mod b/go.mod index 0e97307..84611db 100644 --- a/go.mod +++ b/go.mod @@ -58,9 +58,8 @@ require ( github.com/onsi/ginkgo/v2 v2.11.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.3.2 // indirect - github.com/quic-go/qtls-go1-20 v0.2.2 // indirect - github.com/quic-go/quic-go v0.36.0 // indirect + github.com/quic-go/qtls-go1-20 v0.3.3 // indirect + github.com/quic-go/quic-go v0.38.1 // indirect github.com/refraction-networking/utls v1.3.2 // indirect github.com/superfly/graphql v0.2.4 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect diff --git a/go.sum b/go.sum index f222439..903f2d5 100644 --- a/go.sum +++ b/go.sum @@ -149,12 +149,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= -github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= -github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/quic-go/quic-go v0.36.0 h1:JIrO7p7Ug6hssFcARjWDiqS2RAKJHCiwPxBAA989rbI= -github.com/quic-go/quic-go v0.36.0/go.mod h1:zPetvwDlILVxt15n3hr3Gf/I3mDf7LpLKPhR4Ez0AZQ= +github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM= +github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= +github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8= github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= diff --git a/internal/provider/machine_resource.go b/internal/provider/machine_resource.go index 0c9b9f6..16c944c 100644 --- a/internal/provider/machine_resource.go +++ b/internal/provider/machine_resource.go @@ -315,8 +315,7 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) - var newMachine api.Machine - err := machineAPI.CreateMachine(createReq, data.App.ValueString(), &newMachine) + newMachine, err := machineAPI.CreateMachine(createReq, data.App.ValueString()) if err != nil { resp.Diagnostics.AddError("Failed to create machine", err.Error()) return @@ -325,33 +324,43 @@ func (r *flyMachineResource) Create(ctx context.Context, req resource.CreateRequ tflog.Info(ctx, fmt.Sprintf("%+v", newMachine)) // env := utils.KVToTfMap(newMachine.Config.Env, types.StringType) - env, diags := types.MapValueFrom(ctx, types.StringType, newMachine.Config.Env) + env, diags := types.MapValueFrom(ctx, types.StringType, map[string]string{}) + if newMachine.Config != nil { + env, diags = types.MapValueFrom(ctx, types.StringType, newMachine.Config.Env) + } resp.Diagnostics.Append(diags...) - tfservices := ServicesToTfServices(newMachine.Config.Services) + tfservices := ServicesToTfServices([]api.MachineService{}) + if newMachine.Config != nil { + tfservices = ServicesToTfServices(newMachine.Config.Services) + } if data.Services == nil && len(tfservices) == 0 { tfservices = nil } data = flyMachineResourceData{ - Name: types.StringValue(newMachine.Name), - Region: types.StringValue(newMachine.Region), - Id: types.StringValue(newMachine.ID), - App: data.App, - PrivateIP: types.StringValue(newMachine.PrivateIP), - Image: types.StringValue(newMachine.Config.Image), - Cpus: types.Int64Value(int64(newMachine.Config.Guest.CPUs)), - MemoryMb: types.Int64Value(int64(newMachine.Config.Guest.MemoryMB)), - CpuType: types.StringValue(newMachine.Config.Guest.CPUKind), - Cmd: newMachine.Config.Init.Cmd, - Entrypoint: newMachine.Config.Init.Entrypoint, - Exec: newMachine.Config.Init.Exec, - Env: env, - Services: tfservices, + Name: types.StringValue(newMachine.Name), + Region: types.StringValue(newMachine.Region), + Id: types.StringValue(newMachine.ID), + App: data.App, + PrivateIP: types.StringValue(newMachine.PrivateIP), + Env: env, + Services: tfservices, } - if len(newMachine.Config.Mounts) > 0 { + if newMachine.Config != nil { + data.Image = types.StringValue(newMachine.Config.Image) + data.Cpus = types.Int64Value(int64(newMachine.Config.Guest.CPUs)) + data.MemoryMb = types.Int64Value(int64(newMachine.Config.Guest.MemoryMB)) + data.CpuType = types.StringValue(newMachine.Config.Guest.CPUKind) + data.Cmd = newMachine.Config.Init.Cmd + data.Entrypoint = newMachine.Config.Init.Entrypoint + data.Exec = newMachine.Config.Init.Exec + + } + + if newMachine.Config != nil && len(newMachine.Config.Mounts) > 0 { var tfmounts []TfMachineMount for _, m := range newMachine.Config.Mounts { tfmounts = append(tfmounts, TfMachineMount{ @@ -385,9 +394,7 @@ func (r *flyMachineResource) Read(ctx context.Context, req resource.ReadRequest, machineAPI := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) - var machine api.Machine - - _, err := machineAPI.ReadMachine(data.App.ValueString(), data.Id.ValueString(), &machine) + machine, err := machineAPI.ReadMachine(data.App.ValueString(), data.Id.ValueString()) if err != nil { resp.Diagnostics.AddError("Failed to create machine", err.Error()) return @@ -517,9 +524,7 @@ func (r *flyMachineResource) Update(ctx context.Context, req resource.UpdateRequ machineApi := apiv1.NewMachineAPI(r.config.httpClient, r.config.httpEndpoint) - var updatedMachine api.Machine - - err := machineApi.UpdateMachine(updateReq, state.App.ValueString(), state.Id.ValueString(), &updatedMachine) + updatedMachine, err := machineApi.UpdateMachine(updateReq, state.App.ValueString(), state.Id.ValueString()) if err != nil { resp.Diagnostics.AddError("Failed to update machine", err.Error()) return diff --git a/pkg/apiv1/machines.go b/pkg/apiv1/machines.go index c81e51f..c13d8ac 100644 --- a/pkg/apiv1/machines.go +++ b/pkg/apiv1/machines.go @@ -27,12 +27,12 @@ func NewMachineAPI(httpClient *hreq.Client, endpoint string) *MachineAPI { } func (a *MachineAPI) LockMachine(app string, id string, timeout int) (*api.MachineLease, error) { - var res *api.MachineLease + var res api.MachineLease _, err := a.httpClient.R().SetSuccessResult(&res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s/lease/?ttl=%d", a.endpoint, app, id, timeout)) if err != nil { return nil, err } - return res, nil + return &res, nil } func (a *MachineAPI) ReleaseMachine(lease api.MachineLease, app string, id string) error { @@ -49,58 +49,69 @@ func (a *MachineAPI) WaitForMachine(app string, id string, instanceID string) er } // CreateMachine takes a MachineCreateOrUpdateRequest and creates the requested machine in the given app and then writes the response into the `res` param -func (a *MachineAPI) CreateMachine(req api.Machine, app string, res *api.Machine) error { - if req.Config.Guest.CPUKind == "" { - req.Config.Guest.CPUKind = "shared" - } - if req.Config.Guest.CPUs == 0 { - req.Config.Guest.CPUs = 1 - } - if req.Config.Guest.MemoryMB == 0 { - req.Config.Guest.MemoryMB = 256 +func (a *MachineAPI) CreateMachine(req api.Machine, app string) (*api.Machine, error) { + var res api.Machine + if req.Config != nil && req.Config.Guest != nil { + if req.Config.Guest.CPUKind == "" { + req.Config.Guest.CPUKind = "shared" + } + if req.Config.Guest.CPUs == 0 { + req.Config.Guest.CPUs = 1 + } + if req.Config.Guest.MemoryMB == 0 { + req.Config.Guest.MemoryMB = 256 + } } createResponse, err := a.httpClient.R().SetBody(req).SetSuccessResult(res).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines", a.endpoint, app)) if err != nil { - return err + return nil, err } if createResponse.StatusCode != http.StatusCreated && createResponse.StatusCode != http.StatusOK { - return errors.New(fmt.Sprintf("Create request failed: %s, %+v", createResponse.Status, createResponse)) + return nil, errors.New(fmt.Sprintf("Create request failed: %s, %+v", createResponse.Status, createResponse)) } - return nil + return &res, nil } -func (a *MachineAPI) UpdateMachine(req api.Machine, app string, id string, res *api.Machine) error { - if req.Config.Guest.CPUKind == "" { - req.Config.Guest.CPUKind = "shared" - } - if req.Config.Guest.CPUs == 0 { - req.Config.Guest.CPUs = 1 - } - if req.Config.Guest.MemoryMB == 0 { - req.Config.Guest.MemoryMB = 256 +func (a *MachineAPI) UpdateMachine(req api.Machine, app string, id string) (*api.Machine, error) { + var res api.Machine + if req.Config != nil && req.Config.Guest != nil { + if req.Config.Guest.CPUKind == "" { + req.Config.Guest.CPUKind = "shared" + } + if req.Config.Guest.CPUs == 0 { + req.Config.Guest.CPUs = 1 + } + if req.Config.Guest.MemoryMB == 0 { + req.Config.Guest.MemoryMB = 256 + } } lease, err := a.LockMachine(app, id, 30) if err != nil { - return err + return nil, err } - reqRes, err := a.httpClient.R().SetBody(req).SetSuccessResult(res).SetHeader(NonceHeader, lease.Data.Nonce).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) + reqRes, err := a.httpClient.R().SetBody(req).SetSuccessResult(&res).SetHeader(NonceHeader, lease.Data.Nonce).Post(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) if err != nil { - return err + return nil, err } err = a.ReleaseMachine(*lease, app, id) if err != nil { - return err + return nil, err } if reqRes.StatusCode != http.StatusCreated && reqRes.StatusCode != http.StatusOK { - return errors.New(fmt.Sprintf("Update request failed: %s, %+v", reqRes.Status, reqRes)) + return nil, errors.New(fmt.Sprintf("Update request failed: %s, %+v", reqRes.Status, reqRes)) } - return nil + return &res, nil } -func (a *MachineAPI) ReadMachine(app string, id string, res *api.Machine) (*hreq.Response, error) { - return a.httpClient.R().SetSuccessResult(res).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) +func (a *MachineAPI) ReadMachine(app string, id string) (*api.Machine, error) { + var res api.Machine + _, err := a.httpClient.R().SetSuccessResult(&res).Get(fmt.Sprintf("http://%s/v1/apps/%s/machines/%s", a.endpoint, app, id)) + if err != nil { + return nil, err + } + return &res, nil } func (a *MachineAPI) DeleteMachine(app string, id string, maxRetries int) error { @@ -138,7 +149,7 @@ func (a *MachineAPI) DeleteMachine(app string, id string, maxRetries int) error } func (a *MachineAPI) CreateVolume(ctx context.Context, name, app, region string, size int) (*api.Volume, error) { - var res *api.Volume + var res api.Volume _, err := a.httpClient.R().SetContext(ctx).SetBody(api.CreateVolumeRequest{ Name: name, Region: region, @@ -147,17 +158,17 @@ func (a *MachineAPI) CreateVolume(ctx context.Context, name, app, region string, if err != nil { return nil, err } - return res, nil + return &res, nil } func (a *MachineAPI) GetVolume(ctx context.Context, id, app string) (*api.Volume, error) { - var res *api.Volume + var res api.Volume _, err := a.httpClient.R().SetContext(ctx).SetSuccessResult(&res).Get(fmt.Sprintf("http://%s/v1/apps/%s/volumes/%s", a.endpoint, app, id)) if err != nil { return nil, err } - return res, nil + return &res, nil } func (a *MachineAPI) DeleteVolume(ctx context.Context, id, app string) error {