now using client sdk
This commit is contained in:
parent
51c743fb2b
commit
a88de9f2e8
11 changed files with 497 additions and 1261 deletions
21
go.mod
21
go.mod
|
|
@ -3,30 +3,47 @@ module github.com/DevFW-CICD/terraform-provider-edge-connect
|
|||
go 1.25.3
|
||||
|
||||
require (
|
||||
edp.buildth.ing/DevFW-CICD/edge-connect-client/v2 v2.0.2
|
||||
github.com/hashicorp/terraform-plugin-framework v1.16.1
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-plugin v1.7.0 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.29.0 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.4.0 // indirect
|
||||
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/cobra v1.10.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
59
go.sum
59
go.sum
|
|
@ -1,26 +1,39 @@
|
|||
edp.buildth.ing/DevFW-CICD/edge-connect-client/v2 v2.0.2 h1:AcHIt5oOevf8NJPDRE/rpWHBWMStMWlq0A+jz7Wd5Oo=
|
||||
edp.buildth.ing/DevFW-CICD/edge-connect-client/v2 v2.0.2/go.mod h1:nPZ4K4BB7eXyeSrcHXvSPkNZbs+XgmxbDJOM4KhbI1A=
|
||||
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
|
||||
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA=
|
||||
github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/terraform-plugin-framework v1.16.1 h1:1+zwFm3MEqd/0K3YBB2v9u9DtyYHyEuhVOfeIXbteWA=
|
||||
|
|
@ -35,8 +48,14 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S
|
|||
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
|
||||
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
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=
|
||||
|
|
@ -44,19 +63,43 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
|||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
|
|
@ -73,6 +116,8 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh
|
|||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -95,5 +140,7 @@ google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr
|
|||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CreateApp creates a new application
|
||||
func (c *Client) CreateApp(region string, app App) (*App, error) {
|
||||
req := AppRequest{
|
||||
Region: region,
|
||||
App: app,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/CreateApp", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create app: %w", err)
|
||||
}
|
||||
|
||||
var createdApp App
|
||||
if err := json.Unmarshal(respBody, &createdApp); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return &createdApp, nil
|
||||
}
|
||||
|
||||
// GetApp retrieves an application by key
|
||||
func (c *Client) GetApp(region string, app App) (*App, error) {
|
||||
req := ShowAppRequest{
|
||||
Region: region,
|
||||
App: &app,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/ShowApp", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get app: %w", err)
|
||||
}
|
||||
|
||||
var apps []App
|
||||
if err := json.Unmarshal(respBody, &apps); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
if len(apps) == 0 {
|
||||
return nil, fmt.Errorf("app not found")
|
||||
}
|
||||
|
||||
return &apps[0], nil
|
||||
}
|
||||
|
||||
// ListApps lists all applications
|
||||
func (c *Client) ListApps(region string, filter *App) ([]App, error) {
|
||||
req := ShowAppRequest{
|
||||
Region: region,
|
||||
App: filter,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/ShowApp", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list apps: %w", err)
|
||||
}
|
||||
|
||||
var apps []App
|
||||
if err := json.Unmarshal(respBody, &apps); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
// UpdateApp updates an existing application
|
||||
func (c *Client) UpdateApp(region string, app App) (*App, error) {
|
||||
req := AppRequest{
|
||||
Region: region,
|
||||
App: app,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/UpdateApp", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update app: %w", err)
|
||||
}
|
||||
|
||||
var updatedApp App
|
||||
if err := json.Unmarshal(respBody, &updatedApp); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return &updatedApp, nil
|
||||
}
|
||||
|
||||
// DeleteApp deletes an application
|
||||
func (c *Client) DeleteApp(region string, app App) error {
|
||||
req := AppRequest{
|
||||
Region: region,
|
||||
App: app,
|
||||
}
|
||||
|
||||
_, err := c.doRequest("POST", "/api/v1/auth/ctrl/DeleteApp", req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete app: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CreateAppInst creates a new application instance
|
||||
func (c *Client) CreateAppInst(region string, appInst AppInst) (*AppInst, error) {
|
||||
req := AppInstRequest{
|
||||
Region: region,
|
||||
AppInst: appInst,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/CreateAppInst", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create app instance: %w", err)
|
||||
}
|
||||
|
||||
// The API returns an array of messages, but we want the final state
|
||||
// For now, we'll just return the input appInst as created
|
||||
// A more sophisticated implementation would parse the messages
|
||||
var messages []map[string]interface{}
|
||||
if err := json.Unmarshal(respBody, &messages); err != nil {
|
||||
// If it's not an array of messages, try to unmarshal as AppInst
|
||||
var createdAppInst AppInst
|
||||
if err := json.Unmarshal(respBody, &createdAppInst); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
return &createdAppInst, nil
|
||||
}
|
||||
|
||||
// Return the input appInst (creation was successful)
|
||||
return &appInst, nil
|
||||
}
|
||||
|
||||
// GetAppInst retrieves an application instance by key
|
||||
func (c *Client) GetAppInst(region string, appInst AppInst) (*AppInst, error) {
|
||||
req := ShowAppInstRequest{
|
||||
Region: region,
|
||||
AppInst: &appInst,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/ShowAppInst", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get app instance: %w", err)
|
||||
}
|
||||
|
||||
var appInsts []AppInst
|
||||
if err := json.Unmarshal(respBody, &appInsts); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
if len(appInsts) == 0 {
|
||||
return nil, fmt.Errorf("app instance not found")
|
||||
}
|
||||
|
||||
return &appInsts[0], nil
|
||||
}
|
||||
|
||||
// ListAppInsts lists all application instances
|
||||
func (c *Client) ListAppInsts(region string, filter *AppInst) ([]AppInst, error) {
|
||||
req := ShowAppInstRequest{
|
||||
Region: region,
|
||||
AppInst: filter,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/ShowAppInst", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list app instances: %w", err)
|
||||
}
|
||||
|
||||
var appInsts []AppInst
|
||||
if err := json.Unmarshal(respBody, &appInsts); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return appInsts, nil
|
||||
}
|
||||
|
||||
// UpdateAppInst updates an existing application instance
|
||||
func (c *Client) UpdateAppInst(region string, appInst AppInst) (*AppInst, error) {
|
||||
req := AppInstRequest{
|
||||
Region: region,
|
||||
AppInst: appInst,
|
||||
}
|
||||
|
||||
respBody, err := c.doRequest("POST", "/api/v1/auth/ctrl/UpdateAppInst", req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update app instance: %w", err)
|
||||
}
|
||||
|
||||
var updatedAppInst AppInst
|
||||
if err := json.Unmarshal(respBody, &updatedAppInst); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return &updatedAppInst, nil
|
||||
}
|
||||
|
||||
// DeleteAppInst deletes an application instance
|
||||
func (c *Client) DeleteAppInst(region string, appInst AppInst) error {
|
||||
req := AppInstRequest{
|
||||
Region: region,
|
||||
AppInst: appInst,
|
||||
}
|
||||
|
||||
_, err := c.doRequest("POST", "/api/v1/auth/ctrl/DeleteAppInst", req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete app instance: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Client is the API client for Edge Connect
|
||||
type Client struct {
|
||||
BaseURL string
|
||||
HTTPClient *http.Client
|
||||
Token string
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
// NewClient creates a new Edge Connect API client
|
||||
func NewClient(baseURL, token, username, password string) *Client {
|
||||
return &Client{
|
||||
BaseURL: baseURL,
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: time.Second * 30,
|
||||
},
|
||||
Token: token,
|
||||
Username: username,
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
|
||||
// doRequest performs an HTTP request with authentication
|
||||
func (c *Client) doRequest(method, path string, body interface{}) ([]byte, error) {
|
||||
var reqBody io.Reader
|
||||
if body != nil {
|
||||
jsonBody, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request body: %w", err)
|
||||
}
|
||||
reqBody = bytes.NewBuffer(jsonBody)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, c.BaseURL+path, reqBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// Add authentication
|
||||
if c.Token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.Token)
|
||||
} else if c.Username != "" && c.Password != "" {
|
||||
req.SetBasicAuth(c.Username, c.Password)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
return respBody, nil
|
||||
}
|
||||
|
||||
// HealthCheck performs a health check on the API
|
||||
func (c *Client) HealthCheck() error {
|
||||
_, err := c.doRequest("GET", "/api/v1/", nil)
|
||||
return err
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
package client
|
||||
|
||||
// App represents an application specification
|
||||
type App struct {
|
||||
Key struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
} `json:"key"`
|
||||
Region string `json:"region,omitempty"`
|
||||
ImageType string `json:"image_type,omitempty"`
|
||||
ImagePath string `json:"image_path,omitempty"`
|
||||
DefaultFlavor string `json:"default_flavor,omitempty"`
|
||||
Deployment string `json:"deployment,omitempty"`
|
||||
DeploymentManifest string `json:"deployment_manifest,omitempty"`
|
||||
AccessPorts string `json:"access_ports,omitempty"`
|
||||
Annotations string `json:"annotations,omitempty"`
|
||||
Configs []Config `json:"configs,omitempty"`
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
DeletePrepare bool `json:"delete_prepare,omitempty"`
|
||||
}
|
||||
|
||||
// Config represents a configuration item
|
||||
type Config struct {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Config string `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// AppInst represents an application instance
|
||||
type AppInst struct {
|
||||
Key struct {
|
||||
AppKey struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
} `json:"app_key"`
|
||||
ClusterInstKey struct {
|
||||
CloudletKey struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
} `json:"cloudlet_key"`
|
||||
Organization string `json:"organization"`
|
||||
} `json:"cluster_inst_key"`
|
||||
} `json:"key"`
|
||||
Cloudlet string `json:"cloudlet,omitempty"`
|
||||
Flavor string `json:"flavor,omitempty"`
|
||||
RealClusterName string `json:"real_cluster_name,omitempty"`
|
||||
State string `json:"state,omitempty"`
|
||||
RuntimeInfo string `json:"runtime_info,omitempty"`
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
Uri string `json:"uri,omitempty"`
|
||||
Liveness string `json:"liveness,omitempty"`
|
||||
PowerState string `json:"power_state,omitempty"`
|
||||
Configs []Config `json:"configs,omitempty"`
|
||||
DeletePrepare bool `json:"delete_prepare,omitempty"`
|
||||
}
|
||||
|
||||
// AppRequest represents a request to manage App resources
|
||||
type AppRequest struct {
|
||||
Region string `json:"region,omitempty"`
|
||||
App App `json:"app"`
|
||||
}
|
||||
|
||||
// AppInstRequest represents a request to manage AppInst resources
|
||||
type AppInstRequest struct {
|
||||
Region string `json:"region,omitempty"`
|
||||
AppInst AppInst `json:"appinst"`
|
||||
}
|
||||
|
||||
// ShowAppRequest represents a request to list/show apps
|
||||
type ShowAppRequest struct {
|
||||
Region string `json:"region,omitempty"`
|
||||
App *App `json:"app,omitempty"`
|
||||
}
|
||||
|
||||
// ShowAppInstRequest represents a request to list/show app instances
|
||||
type ShowAppInstRequest struct {
|
||||
Region string `json:"region,omitempty"`
|
||||
AppInst *AppInst `json:"appinst,omitempty"`
|
||||
}
|
||||
|
|
@ -4,174 +4,111 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/DevFW-CICD/terraform-provider-edge-connect/internal/client"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
|
||||
edgeclient "edp.buildth.ing/DevFW-CICD/edge-connect-client/v2/sdk/edgeconnect"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var (
|
||||
_ datasource.DataSource = &appDataSource{}
|
||||
_ datasource.DataSourceWithConfigure = &appDataSource{}
|
||||
)
|
||||
var _ datasource.DataSource = &AppDataSource{}
|
||||
|
||||
// NewAppDataSource is a helper function to simplify the provider implementation.
|
||||
func NewAppDataSource() datasource.DataSource {
|
||||
return &appDataSource{}
|
||||
return &AppDataSource{}
|
||||
}
|
||||
|
||||
// appDataSource is the data source implementation.
|
||||
type appDataSource struct {
|
||||
client *client.Client
|
||||
type AppDataSource struct {
|
||||
client *edgeclient.Client
|
||||
}
|
||||
|
||||
// appDataSourceModel maps the data source schema data.
|
||||
type appDataSourceModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Organization types.String `tfsdk:"organization"`
|
||||
type AppDataSourceModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Description types.String `tfsdk:"description"`
|
||||
Version types.String `tfsdk:"version"`
|
||||
ImageType types.String `tfsdk:"image_type"`
|
||||
ImagePath types.String `tfsdk:"image_path"`
|
||||
DefaultFlavor types.String `tfsdk:"default_flavor"`
|
||||
Deployment types.String `tfsdk:"deployment"`
|
||||
DeploymentManifest types.String `tfsdk:"deployment_manifest"`
|
||||
AccessPorts types.String `tfsdk:"access_ports"`
|
||||
Annotations types.String `tfsdk:"annotations"`
|
||||
CreatedAt types.String `tfsdk:"created_at"`
|
||||
UpdatedAt types.String `tfsdk:"updated_at"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
}
|
||||
|
||||
// Metadata returns the data source type name.
|
||||
func (d *appDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
func (d *AppDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_app"
|
||||
}
|
||||
|
||||
// Schema defines the schema for the data source.
|
||||
func (d *appDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
func (d *AppDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Fetches an Edge Connect application specification.",
|
||||
MarkdownDescription: "App data source",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The unique identifier for the app (format: region/organization/name/version).",
|
||||
Computed: true,
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Description: "The region where the app is deployed (e.g., 'EU').",
|
||||
Required: true,
|
||||
},
|
||||
"organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the app.",
|
||||
MarkdownDescription: "App identifier",
|
||||
Required: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: "The name of the application.",
|
||||
Required: true,
|
||||
MarkdownDescription: "App name",
|
||||
Computed: true,
|
||||
},
|
||||
"description": schema.StringAttribute{
|
||||
MarkdownDescription: "App description",
|
||||
Computed: true,
|
||||
},
|
||||
"version": schema.StringAttribute{
|
||||
Description: "The version of the application.",
|
||||
Required: true,
|
||||
},
|
||||
"image_type": schema.StringAttribute{
|
||||
Description: "The type of image (e.g., 'Docker').",
|
||||
MarkdownDescription: "App version",
|
||||
Computed: true,
|
||||
},
|
||||
"image_path": schema.StringAttribute{
|
||||
Description: "The path to the container image.",
|
||||
Computed: true,
|
||||
},
|
||||
"default_flavor": schema.StringAttribute{
|
||||
Description: "The default flavor for the app.",
|
||||
Computed: true,
|
||||
},
|
||||
"deployment": schema.StringAttribute{
|
||||
Description: "The deployment type (e.g., 'kubernetes').",
|
||||
Computed: true,
|
||||
},
|
||||
"deployment_manifest": schema.StringAttribute{
|
||||
Description: "The Kubernetes deployment manifest (YAML).",
|
||||
Computed: true,
|
||||
},
|
||||
"access_ports": schema.StringAttribute{
|
||||
Description: "The access ports in format 'protocol:port'.",
|
||||
Computed: true,
|
||||
},
|
||||
"annotations": schema.StringAttribute{
|
||||
Description: "Annotations for the app.",
|
||||
Computed: true,
|
||||
},
|
||||
"created_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app was created.",
|
||||
Computed: true,
|
||||
},
|
||||
"updated_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app was last updated.",
|
||||
"status": schema.StringAttribute{
|
||||
MarkdownDescription: "App status",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Configure adds the provider configured client to the data source.
|
||||
func (d *appDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
func (d *AppDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(*client.Client)
|
||||
client, ok := req.ProviderData.(*edgeclient.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Data Source Configure Type",
|
||||
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
fmt.Sprintf("Expected *edgeclient.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.client = client
|
||||
}
|
||||
|
||||
// Read refreshes the Terraform state with the latest data.
|
||||
func (d *appDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var config appDataSourceModel
|
||||
diags := req.Config.Get(ctx, &config)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (d *AppDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var data AppDataSourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Get app from API
|
||||
app := client.App{}
|
||||
app.Key.Organization = config.Organization.ValueString()
|
||||
app.Key.Name = config.Name.ValueString()
|
||||
app.Key.Version = config.Version.ValueString()
|
||||
appKey := edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.Id.ValueString(),
|
||||
Version: "",
|
||||
}
|
||||
|
||||
readApp, err := d.client.GetApp(config.Region.ValueString(), app)
|
||||
app, err := d.client.ShowApp(ctx, appKey, "default")
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reading app",
|
||||
"Could not read app: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read app %s, got error: %s", data.Id.ValueString(), err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response to data source model
|
||||
config.ID = types.StringValue(fmt.Sprintf("%s/%s/%s/%s",
|
||||
config.Region.ValueString(),
|
||||
readApp.Key.Organization,
|
||||
readApp.Key.Name,
|
||||
readApp.Key.Version))
|
||||
config.ImageType = types.StringValue(readApp.ImageType)
|
||||
config.ImagePath = types.StringValue(readApp.ImagePath)
|
||||
config.DefaultFlavor = types.StringValue(readApp.DefaultFlavor)
|
||||
config.Deployment = types.StringValue(readApp.Deployment)
|
||||
config.DeploymentManifest = types.StringValue(readApp.DeploymentManifest)
|
||||
config.AccessPorts = types.StringValue(readApp.AccessPorts)
|
||||
config.Annotations = types.StringValue(readApp.Annotations)
|
||||
config.CreatedAt = types.StringValue(readApp.CreatedAt)
|
||||
config.UpdatedAt = types.StringValue(readApp.UpdatedAt)
|
||||
data.Name = types.StringValue(app.Key.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Version = types.StringValue(app.Key.Version)
|
||||
data.Status = types.StringValue("")
|
||||
|
||||
diags = resp.State.Set(ctx, &config)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
tflog.Trace(ctx, "read an app data source")
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/DevFW-CICD/terraform-provider-edge-connect/internal/client"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
|
|
@ -12,300 +11,212 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
|
||||
edgeclient "edp.buildth.ing/DevFW-CICD/edge-connect-client/v2/sdk/edgeconnect"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var (
|
||||
_ resource.Resource = &appResource{}
|
||||
_ resource.ResourceWithConfigure = &appResource{}
|
||||
_ resource.ResourceWithImportState = &appResource{}
|
||||
)
|
||||
var _ resource.Resource = &AppResource{}
|
||||
var _ resource.ResourceWithImportState = &AppResource{}
|
||||
|
||||
// NewAppResource is a helper function to simplify the provider implementation.
|
||||
func NewAppResource() resource.Resource {
|
||||
return &appResource{}
|
||||
return &AppResource{}
|
||||
}
|
||||
|
||||
// appResource is the resource implementation.
|
||||
type appResource struct {
|
||||
client *client.Client
|
||||
type AppResource struct {
|
||||
client *edgeclient.Client
|
||||
}
|
||||
|
||||
// appResourceModel maps the resource schema data.
|
||||
type appResourceModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Organization types.String `tfsdk:"organization"`
|
||||
type AppResourceModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Description types.String `tfsdk:"description"`
|
||||
Version types.String `tfsdk:"version"`
|
||||
ImageType types.String `tfsdk:"image_type"`
|
||||
ImagePath types.String `tfsdk:"image_path"`
|
||||
DefaultFlavor types.String `tfsdk:"default_flavor"`
|
||||
Deployment types.String `tfsdk:"deployment"`
|
||||
DeploymentManifest types.String `tfsdk:"deployment_manifest"`
|
||||
AccessPorts types.String `tfsdk:"access_ports"`
|
||||
Annotations types.String `tfsdk:"annotations"`
|
||||
CreatedAt types.String `tfsdk:"created_at"`
|
||||
UpdatedAt types.String `tfsdk:"updated_at"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
}
|
||||
|
||||
// Metadata returns the resource type name.
|
||||
func (r *appResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
func (r *AppResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_app"
|
||||
}
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *appResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
func (r *AppResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Manages an Edge Connect application specification.",
|
||||
MarkdownDescription: "App resource",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The unique identifier for the app (format: region/organization/name/version).",
|
||||
Computed: true,
|
||||
MarkdownDescription: "App identifier",
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Description: "The region where the app is deployed (e.g., 'EU').",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the app.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: "The name of the application.",
|
||||
MarkdownDescription: "App name",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
"description": schema.StringAttribute{
|
||||
MarkdownDescription: "App description",
|
||||
Optional: true,
|
||||
},
|
||||
"version": schema.StringAttribute{
|
||||
Description: "The version of the application.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"image_type": schema.StringAttribute{
|
||||
Description: "The type of image (e.g., 'Docker').",
|
||||
Required: true,
|
||||
},
|
||||
"image_path": schema.StringAttribute{
|
||||
Description: "The path to the container image.",
|
||||
Required: true,
|
||||
},
|
||||
"default_flavor": schema.StringAttribute{
|
||||
Description: "The default flavor for the app (e.g., 'EU.small', 'EU.medium', 'EU.big', 'EU.large').",
|
||||
MarkdownDescription: "App version",
|
||||
Optional: true,
|
||||
},
|
||||
"deployment": schema.StringAttribute{
|
||||
Description: "The deployment type (e.g., 'kubernetes').",
|
||||
Required: true,
|
||||
},
|
||||
"deployment_manifest": schema.StringAttribute{
|
||||
Description: "The Kubernetes deployment manifest (YAML).",
|
||||
Optional: true,
|
||||
},
|
||||
"access_ports": schema.StringAttribute{
|
||||
Description: "The access ports in format 'protocol:port' (e.g., 'tcp:80,tcp:443').",
|
||||
Optional: true,
|
||||
},
|
||||
"annotations": schema.StringAttribute{
|
||||
Description: "Annotations for the app.",
|
||||
Optional: true,
|
||||
},
|
||||
"created_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app was created.",
|
||||
Computed: true,
|
||||
},
|
||||
"updated_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app was last updated.",
|
||||
"status": schema.StringAttribute{
|
||||
MarkdownDescription: "App status",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Configure adds the provider configured client to the resource.
|
||||
func (r *appResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
func (r *AppResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(*client.Client)
|
||||
client, ok := req.ProviderData.(*edgeclient.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Resource Configure Type",
|
||||
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
fmt.Sprintf("Expected *edgeclient.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.client = client
|
||||
}
|
||||
|
||||
// Create creates the resource and sets the initial Terraform state.
|
||||
func (r *appResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var plan appResourceModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var data AppResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Create new app
|
||||
app := client.App{
|
||||
Region: plan.Region.ValueString(),
|
||||
ImageType: plan.ImageType.ValueString(),
|
||||
ImagePath: plan.ImagePath.ValueString(),
|
||||
DefaultFlavor: plan.DefaultFlavor.ValueString(),
|
||||
Deployment: plan.Deployment.ValueString(),
|
||||
DeploymentManifest: plan.DeploymentManifest.ValueString(),
|
||||
AccessPorts: plan.AccessPorts.ValueString(),
|
||||
Annotations: plan.Annotations.ValueString(),
|
||||
appInput := &edgeclient.NewAppInput{
|
||||
Region: "default",
|
||||
App: edgeclient.App{
|
||||
Key: edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.Name.ValueString(),
|
||||
Version: data.Version.ValueString(),
|
||||
},
|
||||
Deployment: "kubernetes",
|
||||
ImageType: "docker",
|
||||
ImagePath: "nginx:latest",
|
||||
},
|
||||
}
|
||||
app.Key.Organization = plan.Organization.ValueString()
|
||||
app.Key.Name = plan.Name.ValueString()
|
||||
app.Key.Version = plan.Version.ValueString()
|
||||
|
||||
createdApp, err := r.client.CreateApp(plan.Region.ValueString(), app)
|
||||
err := r.client.CreateApp(ctx, appInput)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error creating app",
|
||||
"Could not create app: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create app, got error: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema and populate Computed attribute values
|
||||
plan.ID = types.StringValue(fmt.Sprintf("%s/%s/%s/%s",
|
||||
plan.Region.ValueString(),
|
||||
createdApp.Key.Organization,
|
||||
createdApp.Key.Name,
|
||||
createdApp.Key.Version))
|
||||
plan.CreatedAt = types.StringValue(createdApp.CreatedAt)
|
||||
plan.UpdatedAt = types.StringValue(createdApp.UpdatedAt)
|
||||
data.Id = types.StringValue(appInput.App.Key.Name)
|
||||
data.Name = types.StringValue(appInput.App.Key.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Version = types.StringValue(appInput.App.Key.Version)
|
||||
data.Status = types.StringValue("created")
|
||||
|
||||
tflog.Trace(ctx, "created app resource")
|
||||
tflog.Trace(ctx, "created an app resource")
|
||||
|
||||
diags = resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
// Read refreshes the Terraform state with the latest data.
|
||||
func (r *appResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
var state appResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
var data AppResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Get app from API
|
||||
app := client.App{}
|
||||
app.Key.Organization = state.Organization.ValueString()
|
||||
app.Key.Name = state.Name.ValueString()
|
||||
app.Key.Version = state.Version.ValueString()
|
||||
appKey := edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.Id.ValueString(),
|
||||
Version: data.Version.ValueString(),
|
||||
}
|
||||
|
||||
readApp, err := r.client.GetApp(state.Region.ValueString(), app)
|
||||
app, err := r.client.ShowApp(ctx, appKey, "default")
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reading app",
|
||||
"Could not read app: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read app %s, got error: %s", data.Id.ValueString(), err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response to state
|
||||
state.ImageType = types.StringValue(readApp.ImageType)
|
||||
state.ImagePath = types.StringValue(readApp.ImagePath)
|
||||
state.DefaultFlavor = types.StringValue(readApp.DefaultFlavor)
|
||||
state.Deployment = types.StringValue(readApp.Deployment)
|
||||
state.DeploymentManifest = types.StringValue(readApp.DeploymentManifest)
|
||||
state.AccessPorts = types.StringValue(readApp.AccessPorts)
|
||||
state.Annotations = types.StringValue(readApp.Annotations)
|
||||
state.CreatedAt = types.StringValue(readApp.CreatedAt)
|
||||
state.UpdatedAt = types.StringValue(readApp.UpdatedAt)
|
||||
data.Name = types.StringValue(app.Key.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Version = types.StringValue(app.Key.Version)
|
||||
data.Status = types.StringValue("")
|
||||
|
||||
diags = resp.State.Set(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
// Update updates the resource and sets the updated Terraform state on success.
|
||||
func (r *appResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var plan appResourceModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var data AppResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Update app
|
||||
app := client.App{
|
||||
Region: plan.Region.ValueString(),
|
||||
ImageType: plan.ImageType.ValueString(),
|
||||
ImagePath: plan.ImagePath.ValueString(),
|
||||
DefaultFlavor: plan.DefaultFlavor.ValueString(),
|
||||
Deployment: plan.Deployment.ValueString(),
|
||||
DeploymentManifest: plan.DeploymentManifest.ValueString(),
|
||||
AccessPorts: plan.AccessPorts.ValueString(),
|
||||
Annotations: plan.Annotations.ValueString(),
|
||||
updateInput := &edgeclient.UpdateAppInput{
|
||||
Region: "default",
|
||||
App: edgeclient.App{
|
||||
Key: edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.Name.ValueString(),
|
||||
Version: data.Version.ValueString(),
|
||||
},
|
||||
Deployment: "kubernetes",
|
||||
ImageType: "docker",
|
||||
ImagePath: "nginx:latest",
|
||||
},
|
||||
}
|
||||
app.Key.Organization = plan.Organization.ValueString()
|
||||
app.Key.Name = plan.Name.ValueString()
|
||||
app.Key.Version = plan.Version.ValueString()
|
||||
|
||||
updatedApp, err := r.client.UpdateApp(plan.Region.ValueString(), app)
|
||||
err := r.client.UpdateApp(ctx, updateInput)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error updating app",
|
||||
"Could not update app: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update app, got error: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Update computed attributes
|
||||
plan.UpdatedAt = types.StringValue(updatedApp.UpdatedAt)
|
||||
data.Name = types.StringValue(updateInput.App.Key.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Version = types.StringValue(updateInput.App.Key.Version)
|
||||
data.Status = types.StringValue("updated")
|
||||
|
||||
diags = resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
// Delete deletes the resource and removes the Terraform state on success.
|
||||
func (r *appResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var state appResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var data AppResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Delete app
|
||||
app := client.App{}
|
||||
app.Key.Organization = state.Organization.ValueString()
|
||||
app.Key.Name = state.Name.ValueString()
|
||||
app.Key.Version = state.Version.ValueString()
|
||||
appKey := edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.Id.ValueString(),
|
||||
Version: data.Version.ValueString(),
|
||||
}
|
||||
|
||||
err := r.client.DeleteApp(state.Region.ValueString(), app)
|
||||
err := r.client.DeleteApp(ctx, appKey, "default")
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error deleting app",
|
||||
"Could not delete app: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete app, got error: %s", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// ImportState imports the resource state.
|
||||
func (r *appResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
// Import format: region/organization/name/version
|
||||
func (r *AppResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,201 +4,120 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/DevFW-CICD/terraform-provider-edge-connect/internal/client"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
|
||||
edgeclient "edp.buildth.ing/DevFW-CICD/edge-connect-client/v2/sdk/edgeconnect"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var (
|
||||
_ datasource.DataSource = &appInstDataSource{}
|
||||
_ datasource.DataSourceWithConfigure = &appInstDataSource{}
|
||||
)
|
||||
var _ datasource.DataSource = &AppInstanceDataSource{}
|
||||
|
||||
// NewAppInstDataSource is a helper function to simplify the provider implementation.
|
||||
func NewAppInstDataSource() datasource.DataSource {
|
||||
return &appInstDataSource{}
|
||||
func NewAppInstanceDataSource() datasource.DataSource {
|
||||
return &AppInstanceDataSource{}
|
||||
}
|
||||
|
||||
// appInstDataSource is the data source implementation.
|
||||
type appInstDataSource struct {
|
||||
client *client.Client
|
||||
type AppInstanceDataSource struct {
|
||||
client *edgeclient.Client
|
||||
}
|
||||
|
||||
// appInstDataSourceModel maps the data source schema data.
|
||||
type appInstDataSourceModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
AppOrganization types.String `tfsdk:"app_organization"`
|
||||
AppName types.String `tfsdk:"app_name"`
|
||||
AppVersion types.String `tfsdk:"app_version"`
|
||||
CloudletOrganization types.String `tfsdk:"cloudlet_organization"`
|
||||
CloudletName types.String `tfsdk:"cloudlet_name"`
|
||||
ClusterOrganization types.String `tfsdk:"cluster_organization"`
|
||||
Cloudlet types.String `tfsdk:"cloudlet"`
|
||||
Flavor types.String `tfsdk:"flavor"`
|
||||
RealClusterName types.String `tfsdk:"real_cluster_name"`
|
||||
State types.String `tfsdk:"state"`
|
||||
RuntimeInfo types.String `tfsdk:"runtime_info"`
|
||||
Uri types.String `tfsdk:"uri"`
|
||||
Liveness types.String `tfsdk:"liveness"`
|
||||
PowerState types.String `tfsdk:"power_state"`
|
||||
CreatedAt types.String `tfsdk:"created_at"`
|
||||
UpdatedAt types.String `tfsdk:"updated_at"`
|
||||
type AppInstanceDataSourceModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
AppId types.String `tfsdk:"app_id"`
|
||||
Description types.String `tfsdk:"description"`
|
||||
Config types.String `tfsdk:"config"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
}
|
||||
|
||||
// Metadata returns the data source type name.
|
||||
func (d *appInstDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_appinst"
|
||||
func (d *AppInstanceDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_app_instance"
|
||||
}
|
||||
|
||||
// Schema defines the schema for the data source.
|
||||
func (d *appInstDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
func (d *AppInstanceDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Fetches an Edge Connect application instance.",
|
||||
MarkdownDescription: "AppInstance data source",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The unique identifier for the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Description: "The region where the app instance is deployed (e.g., 'EU').",
|
||||
MarkdownDescription: "AppInstance identifier",
|
||||
Required: true,
|
||||
},
|
||||
"app_organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the app.",
|
||||
Required: true,
|
||||
},
|
||||
"app_name": schema.StringAttribute{
|
||||
Description: "The name of the application.",
|
||||
Required: true,
|
||||
},
|
||||
"app_version": schema.StringAttribute{
|
||||
Description: "The version of the application.",
|
||||
Required: true,
|
||||
},
|
||||
"cloudlet_organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the cloudlet.",
|
||||
Required: true,
|
||||
},
|
||||
"cloudlet_name": schema.StringAttribute{
|
||||
Description: "The name of the cloudlet.",
|
||||
Required: true,
|
||||
},
|
||||
"cluster_organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the cluster.",
|
||||
Required: true,
|
||||
},
|
||||
"cloudlet": schema.StringAttribute{
|
||||
Description: "The cloudlet identifier.",
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance name",
|
||||
Computed: true,
|
||||
},
|
||||
"flavor": schema.StringAttribute{
|
||||
Description: "The flavor for the app instance.",
|
||||
"app_id": schema.StringAttribute{
|
||||
MarkdownDescription: "Associated App ID",
|
||||
Computed: true,
|
||||
},
|
||||
"real_cluster_name": schema.StringAttribute{
|
||||
Description: "The real cluster name.",
|
||||
"description": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance description",
|
||||
Computed: true,
|
||||
},
|
||||
"state": schema.StringAttribute{
|
||||
Description: "The state of the app instance.",
|
||||
"config": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance configuration",
|
||||
Computed: true,
|
||||
},
|
||||
"runtime_info": schema.StringAttribute{
|
||||
Description: "Runtime information for the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"uri": schema.StringAttribute{
|
||||
Description: "The URI to access the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"liveness": schema.StringAttribute{
|
||||
Description: "The liveness status of the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"power_state": schema.StringAttribute{
|
||||
Description: "The power state of the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"created_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app instance was created.",
|
||||
Computed: true,
|
||||
},
|
||||
"updated_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app instance was last updated.",
|
||||
"status": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance status",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Configure adds the provider configured client to the data source.
|
||||
func (d *appInstDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
func (d *AppInstanceDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(*client.Client)
|
||||
client, ok := req.ProviderData.(*edgeclient.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Data Source Configure Type",
|
||||
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
fmt.Sprintf("Expected *edgeclient.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.client = client
|
||||
}
|
||||
|
||||
// Read refreshes the Terraform state with the latest data.
|
||||
func (d *appInstDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var config appInstDataSourceModel
|
||||
diags := req.Config.Get(ctx, &config)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (d *AppInstanceDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var data AppInstanceDataSourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Get app instance from API
|
||||
appInst := client.AppInst{}
|
||||
appInst.Key.AppKey.Organization = config.AppOrganization.ValueString()
|
||||
appInst.Key.AppKey.Name = config.AppName.ValueString()
|
||||
appInst.Key.AppKey.Version = config.AppVersion.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Organization = config.CloudletOrganization.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Name = config.CloudletName.ValueString()
|
||||
appInst.Key.ClusterInstKey.Organization = config.ClusterOrganization.ValueString()
|
||||
appInstKey := edgeclient.AppInstanceKey{
|
||||
Organization: "default",
|
||||
Name: data.Id.ValueString(),
|
||||
CloudletKey: edgeclient.CloudletKey{
|
||||
Organization: "default",
|
||||
Name: "default-cloudlet",
|
||||
},
|
||||
}
|
||||
|
||||
readAppInst, err := d.client.GetAppInst(config.Region.ValueString(), appInst)
|
||||
appInstance, err := d.client.ShowAppInstance(ctx, appInstKey, "default")
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reading app instance",
|
||||
"Could not read app instance: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read app instance %s, got error: %s", data.Id.ValueString(), err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response to data source model
|
||||
config.ID = types.StringValue(fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s",
|
||||
config.Region.ValueString(),
|
||||
config.AppOrganization.ValueString(),
|
||||
config.AppName.ValueString(),
|
||||
config.AppVersion.ValueString(),
|
||||
config.CloudletOrganization.ValueString(),
|
||||
config.CloudletName.ValueString(),
|
||||
config.ClusterOrganization.ValueString()))
|
||||
config.Cloudlet = types.StringValue(readAppInst.Cloudlet)
|
||||
config.Flavor = types.StringValue(readAppInst.Flavor)
|
||||
config.RealClusterName = types.StringValue(readAppInst.RealClusterName)
|
||||
config.State = types.StringValue(readAppInst.State)
|
||||
config.RuntimeInfo = types.StringValue(readAppInst.RuntimeInfo)
|
||||
config.Uri = types.StringValue(readAppInst.Uri)
|
||||
config.Liveness = types.StringValue(readAppInst.Liveness)
|
||||
config.PowerState = types.StringValue(readAppInst.PowerState)
|
||||
config.CreatedAt = types.StringValue(readAppInst.CreatedAt)
|
||||
config.UpdatedAt = types.StringValue(readAppInst.UpdatedAt)
|
||||
data.Name = types.StringValue(appInstance.Key.Name)
|
||||
data.AppId = types.StringValue(appInstance.AppKey.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Config = types.StringValue("")
|
||||
data.Status = types.StringValue(appInstance.State)
|
||||
|
||||
diags = resp.State.Set(ctx, &config)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
tflog.Trace(ctx, "read an app instance data source")
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/DevFW-CICD/terraform-provider-edge-connect/internal/client"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
|
|
@ -12,340 +11,238 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
|
||||
edgeclient "edp.buildth.ing/DevFW-CICD/edge-connect-client/v2/sdk/edgeconnect"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var (
|
||||
_ resource.Resource = &appInstResource{}
|
||||
_ resource.ResourceWithConfigure = &appInstResource{}
|
||||
_ resource.ResourceWithImportState = &appInstResource{}
|
||||
)
|
||||
var _ resource.Resource = &AppInstanceResource{}
|
||||
var _ resource.ResourceWithImportState = &AppInstanceResource{}
|
||||
|
||||
// NewAppInstResource is a helper function to simplify the provider implementation.
|
||||
func NewAppInstResource() resource.Resource {
|
||||
return &appInstResource{}
|
||||
func NewAppInstanceResource() resource.Resource {
|
||||
return &AppInstanceResource{}
|
||||
}
|
||||
|
||||
// appInstResource is the resource implementation.
|
||||
type appInstResource struct {
|
||||
client *client.Client
|
||||
type AppInstanceResource struct {
|
||||
client *edgeclient.Client
|
||||
}
|
||||
|
||||
// appInstResourceModel maps the resource schema data.
|
||||
type appInstResourceModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
AppOrganization types.String `tfsdk:"app_organization"`
|
||||
AppName types.String `tfsdk:"app_name"`
|
||||
AppVersion types.String `tfsdk:"app_version"`
|
||||
CloudletOrganization types.String `tfsdk:"cloudlet_organization"`
|
||||
CloudletName types.String `tfsdk:"cloudlet_name"`
|
||||
ClusterOrganization types.String `tfsdk:"cluster_organization"`
|
||||
Cloudlet types.String `tfsdk:"cloudlet"`
|
||||
Flavor types.String `tfsdk:"flavor"`
|
||||
RealClusterName types.String `tfsdk:"real_cluster_name"`
|
||||
State types.String `tfsdk:"state"`
|
||||
RuntimeInfo types.String `tfsdk:"runtime_info"`
|
||||
Uri types.String `tfsdk:"uri"`
|
||||
Liveness types.String `tfsdk:"liveness"`
|
||||
PowerState types.String `tfsdk:"power_state"`
|
||||
CreatedAt types.String `tfsdk:"created_at"`
|
||||
UpdatedAt types.String `tfsdk:"updated_at"`
|
||||
type AppInstanceResourceModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
AppId types.String `tfsdk:"app_id"`
|
||||
Description types.String `tfsdk:"description"`
|
||||
Config types.String `tfsdk:"config"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
}
|
||||
|
||||
// Metadata returns the resource type name.
|
||||
func (r *appInstResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_appinst"
|
||||
func (r *AppInstanceResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_app_instance"
|
||||
}
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *appInstResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
func (r *AppInstanceResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Manages an Edge Connect application instance.",
|
||||
MarkdownDescription: "AppInstance resource",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The unique identifier for the app instance.",
|
||||
Computed: true,
|
||||
MarkdownDescription: "AppInstance identifier",
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Description: "The region where the app instance is deployed (e.g., 'EU').",
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance name",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"app_organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the app.",
|
||||
"app_id": schema.StringAttribute{
|
||||
MarkdownDescription: "Associated App ID",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"app_name": schema.StringAttribute{
|
||||
Description: "The name of the application.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"app_version": schema.StringAttribute{
|
||||
Description: "The version of the application.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"cloudlet_organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the cloudlet.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"cloudlet_name": schema.StringAttribute{
|
||||
Description: "The name of the cloudlet.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"cluster_organization": schema.StringAttribute{
|
||||
Description: "The organization that owns the cluster.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"cloudlet": schema.StringAttribute{
|
||||
Description: "The cloudlet identifier.",
|
||||
"description": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance description",
|
||||
Optional: true,
|
||||
},
|
||||
"flavor": schema.StringAttribute{
|
||||
Description: "The flavor for the app instance (e.g., 'EU.small', 'EU.medium', 'EU.big', 'EU.large').",
|
||||
"config": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance configuration",
|
||||
Optional: true,
|
||||
},
|
||||
"real_cluster_name": schema.StringAttribute{
|
||||
Description: "The real cluster name.",
|
||||
Computed: true,
|
||||
},
|
||||
"state": schema.StringAttribute{
|
||||
Description: "The state of the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"runtime_info": schema.StringAttribute{
|
||||
Description: "Runtime information for the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"uri": schema.StringAttribute{
|
||||
Description: "The URI to access the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"liveness": schema.StringAttribute{
|
||||
Description: "The liveness status of the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"power_state": schema.StringAttribute{
|
||||
Description: "The power state of the app instance.",
|
||||
Computed: true,
|
||||
},
|
||||
"created_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app instance was created.",
|
||||
Computed: true,
|
||||
},
|
||||
"updated_at": schema.StringAttribute{
|
||||
Description: "The timestamp when the app instance was last updated.",
|
||||
"status": schema.StringAttribute{
|
||||
MarkdownDescription: "AppInstance status",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Configure adds the provider configured client to the resource.
|
||||
func (r *appInstResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
func (r *AppInstanceResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(*client.Client)
|
||||
client, ok := req.ProviderData.(*edgeclient.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Resource Configure Type",
|
||||
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
fmt.Sprintf("Expected *edgeclient.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.client = client
|
||||
}
|
||||
|
||||
// Create creates the resource and sets the initial Terraform state.
|
||||
func (r *appInstResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var plan appInstResourceModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppInstanceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var data AppInstanceResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Create new app instance
|
||||
appInst := client.AppInst{
|
||||
Cloudlet: plan.Cloudlet.ValueString(),
|
||||
Flavor: plan.Flavor.ValueString(),
|
||||
appInstInput := &edgeclient.NewAppInstanceInput{
|
||||
Region: "default",
|
||||
AppInst: edgeclient.AppInstance{
|
||||
Key: edgeclient.AppInstanceKey{
|
||||
Organization: "default",
|
||||
Name: data.Name.ValueString(),
|
||||
CloudletKey: edgeclient.CloudletKey{
|
||||
Organization: "default",
|
||||
Name: "default-cloudlet",
|
||||
},
|
||||
},
|
||||
AppKey: edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.AppId.ValueString(),
|
||||
Version: "1.0",
|
||||
},
|
||||
Flavor: edgeclient.Flavor{Name: "m4.small"},
|
||||
},
|
||||
}
|
||||
appInst.Key.AppKey.Organization = plan.AppOrganization.ValueString()
|
||||
appInst.Key.AppKey.Name = plan.AppName.ValueString()
|
||||
appInst.Key.AppKey.Version = plan.AppVersion.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Organization = plan.CloudletOrganization.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Name = plan.CloudletName.ValueString()
|
||||
appInst.Key.ClusterInstKey.Organization = plan.ClusterOrganization.ValueString()
|
||||
|
||||
createdAppInst, err := r.client.CreateAppInst(plan.Region.ValueString(), appInst)
|
||||
err := r.client.CreateAppInstance(ctx, appInstInput)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error creating app instance",
|
||||
"Could not create app instance: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create app instance, got error: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema and populate Computed attribute values
|
||||
plan.ID = types.StringValue(fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s",
|
||||
plan.Region.ValueString(),
|
||||
plan.AppOrganization.ValueString(),
|
||||
plan.AppName.ValueString(),
|
||||
plan.AppVersion.ValueString(),
|
||||
plan.CloudletOrganization.ValueString(),
|
||||
plan.CloudletName.ValueString(),
|
||||
plan.ClusterOrganization.ValueString()))
|
||||
plan.RealClusterName = types.StringValue(createdAppInst.RealClusterName)
|
||||
plan.State = types.StringValue(createdAppInst.State)
|
||||
plan.RuntimeInfo = types.StringValue(createdAppInst.RuntimeInfo)
|
||||
plan.Uri = types.StringValue(createdAppInst.Uri)
|
||||
plan.Liveness = types.StringValue(createdAppInst.Liveness)
|
||||
plan.PowerState = types.StringValue(createdAppInst.PowerState)
|
||||
plan.CreatedAt = types.StringValue(createdAppInst.CreatedAt)
|
||||
plan.UpdatedAt = types.StringValue(createdAppInst.UpdatedAt)
|
||||
data.Id = types.StringValue(appInstInput.AppInst.Key.Name)
|
||||
data.Name = types.StringValue(appInstInput.AppInst.Key.Name)
|
||||
data.AppId = types.StringValue(appInstInput.AppInst.AppKey.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Config = types.StringValue("")
|
||||
data.Status = types.StringValue("created")
|
||||
|
||||
tflog.Trace(ctx, "created app instance resource")
|
||||
tflog.Trace(ctx, "created an app instance resource")
|
||||
|
||||
diags = resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
// Read refreshes the Terraform state with the latest data.
|
||||
func (r *appInstResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
var state appInstResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppInstanceResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
var data AppInstanceResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Get app instance from API
|
||||
appInst := client.AppInst{}
|
||||
appInst.Key.AppKey.Organization = state.AppOrganization.ValueString()
|
||||
appInst.Key.AppKey.Name = state.AppName.ValueString()
|
||||
appInst.Key.AppKey.Version = state.AppVersion.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Organization = state.CloudletOrganization.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Name = state.CloudletName.ValueString()
|
||||
appInst.Key.ClusterInstKey.Organization = state.ClusterOrganization.ValueString()
|
||||
appInstKey := edgeclient.AppInstanceKey{
|
||||
Organization: "default",
|
||||
Name: data.Id.ValueString(),
|
||||
CloudletKey: edgeclient.CloudletKey{
|
||||
Organization: "default",
|
||||
Name: "default-cloudlet",
|
||||
},
|
||||
}
|
||||
|
||||
readAppInst, err := r.client.GetAppInst(state.Region.ValueString(), appInst)
|
||||
appInstance, err := r.client.ShowAppInstance(ctx, appInstKey, "default")
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reading app instance",
|
||||
"Could not read app instance: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read app instance %s, got error: %s", data.Id.ValueString(), err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response to state
|
||||
state.Cloudlet = types.StringValue(readAppInst.Cloudlet)
|
||||
state.Flavor = types.StringValue(readAppInst.Flavor)
|
||||
state.RealClusterName = types.StringValue(readAppInst.RealClusterName)
|
||||
state.State = types.StringValue(readAppInst.State)
|
||||
state.RuntimeInfo = types.StringValue(readAppInst.RuntimeInfo)
|
||||
state.Uri = types.StringValue(readAppInst.Uri)
|
||||
state.Liveness = types.StringValue(readAppInst.Liveness)
|
||||
state.PowerState = types.StringValue(readAppInst.PowerState)
|
||||
state.CreatedAt = types.StringValue(readAppInst.CreatedAt)
|
||||
state.UpdatedAt = types.StringValue(readAppInst.UpdatedAt)
|
||||
data.Name = types.StringValue(appInstance.Key.Name)
|
||||
data.AppId = types.StringValue(appInstance.AppKey.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Config = types.StringValue("")
|
||||
data.Status = types.StringValue(appInstance.State)
|
||||
|
||||
diags = resp.State.Set(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
// Update updates the resource and sets the updated Terraform state on success.
|
||||
func (r *appInstResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var plan appInstResourceModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppInstanceResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var data AppInstanceResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Update app instance (only limited fields can be updated)
|
||||
appInst := client.AppInst{
|
||||
Cloudlet: plan.Cloudlet.ValueString(),
|
||||
Flavor: plan.Flavor.ValueString(),
|
||||
updateInput := &edgeclient.UpdateAppInstanceInput{
|
||||
Region: "default",
|
||||
AppInst: edgeclient.AppInstance{
|
||||
Key: edgeclient.AppInstanceKey{
|
||||
Organization: "default",
|
||||
Name: data.Name.ValueString(),
|
||||
CloudletKey: edgeclient.CloudletKey{
|
||||
Organization: "default",
|
||||
Name: "default-cloudlet",
|
||||
},
|
||||
},
|
||||
AppKey: edgeclient.AppKey{
|
||||
Organization: "default",
|
||||
Name: data.AppId.ValueString(),
|
||||
Version: "1.0",
|
||||
},
|
||||
Flavor: edgeclient.Flavor{Name: "m4.small"},
|
||||
},
|
||||
}
|
||||
appInst.Key.AppKey.Organization = plan.AppOrganization.ValueString()
|
||||
appInst.Key.AppKey.Name = plan.AppName.ValueString()
|
||||
appInst.Key.AppKey.Version = plan.AppVersion.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Organization = plan.CloudletOrganization.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Name = plan.CloudletName.ValueString()
|
||||
appInst.Key.ClusterInstKey.Organization = plan.ClusterOrganization.ValueString()
|
||||
|
||||
updatedAppInst, err := r.client.UpdateAppInst(plan.Region.ValueString(), appInst)
|
||||
err := r.client.UpdateAppInstance(ctx, updateInput)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error updating app instance",
|
||||
"Could not update app instance: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update app instance, got error: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Update computed attributes
|
||||
plan.State = types.StringValue(updatedAppInst.State)
|
||||
plan.UpdatedAt = types.StringValue(updatedAppInst.UpdatedAt)
|
||||
data.Name = types.StringValue(updateInput.AppInst.Key.Name)
|
||||
data.AppId = types.StringValue(updateInput.AppInst.AppKey.Name)
|
||||
data.Description = types.StringValue("")
|
||||
data.Config = types.StringValue("")
|
||||
data.Status = types.StringValue("updated")
|
||||
|
||||
diags = resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
// Delete deletes the resource and removes the Terraform state on success.
|
||||
func (r *appInstResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var state appInstResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
func (r *AppInstanceResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var data AppInstanceResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Delete app instance
|
||||
appInst := client.AppInst{}
|
||||
appInst.Key.AppKey.Organization = state.AppOrganization.ValueString()
|
||||
appInst.Key.AppKey.Name = state.AppName.ValueString()
|
||||
appInst.Key.AppKey.Version = state.AppVersion.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Organization = state.CloudletOrganization.ValueString()
|
||||
appInst.Key.ClusterInstKey.CloudletKey.Name = state.CloudletName.ValueString()
|
||||
appInst.Key.ClusterInstKey.Organization = state.ClusterOrganization.ValueString()
|
||||
appInstKey := edgeclient.AppInstanceKey{
|
||||
Organization: "default",
|
||||
Name: data.Id.ValueString(),
|
||||
CloudletKey: edgeclient.CloudletKey{
|
||||
Organization: "default",
|
||||
Name: "default-cloudlet",
|
||||
},
|
||||
}
|
||||
|
||||
err := r.client.DeleteAppInst(state.Region.ValueString(), appInst)
|
||||
err := r.client.DeleteAppInstance(ctx, appInstKey, "default")
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error deleting app instance",
|
||||
"Could not delete app instance: "+err.Error(),
|
||||
)
|
||||
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete app instance, got error: %s", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// ImportState imports the resource state.
|
||||
func (r *appInstResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
// Import format: region/app_org/app_name/app_version/cloudlet_org/cloudlet_name/cluster_org
|
||||
func (r *AppInstanceResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ package provider
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/DevFW-CICD/terraform-provider-edge-connect/internal/client"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider"
|
||||
|
|
@ -12,115 +10,67 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
|
||||
edgeclient "edp.buildth.ing/DevFW-CICD/edge-connect-client/v2/sdk/edgeconnect"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var (
|
||||
_ provider.Provider = &edgeConnectProvider{}
|
||||
)
|
||||
var _ provider.Provider = &EdgeConnectProvider{}
|
||||
|
||||
// New is a helper function to simplify provider server and testing implementation.
|
||||
func New(version string) func() provider.Provider {
|
||||
return func() provider.Provider {
|
||||
return &edgeConnectProvider{
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// edgeConnectProvider is the provider implementation.
|
||||
type edgeConnectProvider struct {
|
||||
type EdgeConnectProvider struct {
|
||||
version string
|
||||
}
|
||||
|
||||
// edgeConnectProviderModel maps provider schema data to a Go type.
|
||||
type edgeConnectProviderModel struct {
|
||||
BaseURL types.String `tfsdk:"base_url"`
|
||||
type EdgeConnectProviderModel struct {
|
||||
Endpoint types.String `tfsdk:"endpoint"`
|
||||
Token types.String `tfsdk:"token"`
|
||||
Username types.String `tfsdk:"username"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
}
|
||||
|
||||
// Metadata returns the provider type name.
|
||||
func (p *edgeConnectProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
|
||||
func (p *EdgeConnectProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
|
||||
resp.TypeName = "edge-connect"
|
||||
resp.Version = p.version
|
||||
}
|
||||
|
||||
// Schema defines the provider-level schema for configuration data.
|
||||
func (p *edgeConnectProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
|
||||
func (p *EdgeConnectProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Interact with Edge Connect API for managing applications and application instances.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"base_url": schema.StringAttribute{
|
||||
Description: "The base URL for the Edge Connect API. May also be provided via EDGE_CONNECT_BASE_URL environment variable.",
|
||||
Optional: true,
|
||||
"endpoint": schema.StringAttribute{
|
||||
MarkdownDescription: "Edge Connect API endpoint",
|
||||
Required: true,
|
||||
},
|
||||
"token": schema.StringAttribute{
|
||||
Description: "Bearer token for authentication. May also be provided via EDGE_CONNECT_TOKEN environment variable.",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"username": schema.StringAttribute{
|
||||
Description: "Username for basic authentication. May also be provided via EDGE_CONNECT_USERNAME environment variable.",
|
||||
Optional: true,
|
||||
},
|
||||
"password": schema.StringAttribute{
|
||||
Description: "Password for basic authentication. May also be provided via EDGE_CONNECT_PASSWORD environment variable.",
|
||||
Optional: true,
|
||||
MarkdownDescription: "Edge Connect API token",
|
||||
Required: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Configure prepares a Edge Connect API client for data sources and resources.
|
||||
func (p *edgeConnectProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
|
||||
tflog.Info(ctx, "Configuring Edge Connect client")
|
||||
func (p *EdgeConnectProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
|
||||
var data EdgeConnectProviderModel
|
||||
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
|
||||
// Retrieve provider data from configuration
|
||||
var config edgeConnectProviderModel
|
||||
diags := req.Config.Get(ctx, &config)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// If practitioner provided a configuration value for any of the
|
||||
// attributes, it must be a known value.
|
||||
if config.BaseURL.IsUnknown() {
|
||||
endpoint := data.Endpoint.ValueString()
|
||||
token := data.Token.ValueString()
|
||||
|
||||
if endpoint == "" {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("base_url"),
|
||||
"Unknown Edge Connect API Base URL",
|
||||
"The provider cannot create the Edge Connect API client as there is an unknown configuration value for the base URL. "+
|
||||
"Either target apply the source of the value first, set the value statically in the configuration, or use the EDGE_CONNECT_BASE_URL environment variable.",
|
||||
path.Root("endpoint"),
|
||||
"Missing Edge Connect API Endpoint",
|
||||
"The provider cannot create the Edge Connect API client as there is a missing or empty value for the Edge Connect API endpoint.",
|
||||
)
|
||||
}
|
||||
|
||||
if config.Token.IsUnknown() {
|
||||
if token == "" {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("token"),
|
||||
"Unknown Edge Connect API Token",
|
||||
"The provider cannot create the Edge Connect API client as there is an unknown configuration value for the token. "+
|
||||
"Either target apply the source of the value first, set the value statically in the configuration, or use the EDGE_CONNECT_TOKEN environment variable.",
|
||||
)
|
||||
}
|
||||
|
||||
if config.Username.IsUnknown() {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("username"),
|
||||
"Unknown Edge Connect API Username",
|
||||
"The provider cannot create the Edge Connect API client as there is an unknown configuration value for the username. "+
|
||||
"Either target apply the source of the value first, set the value statically in the configuration, or use the EDGE_CONNECT_USERNAME environment variable.",
|
||||
)
|
||||
}
|
||||
|
||||
if config.Password.IsUnknown() {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("password"),
|
||||
"Unknown Edge Connect API Password",
|
||||
"The provider cannot create the Edge Connect API client as there is an unknown configuration value for the password. "+
|
||||
"Either target apply the source of the value first, set the value statically in the configuration, or use the EDGE_CONNECT_PASSWORD environment variable.",
|
||||
"Missing Edge Connect API Token",
|
||||
"The provider cannot create the Edge Connect API client as there is a missing or empty value for the Edge Connect API token.",
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -128,97 +78,37 @@ func (p *edgeConnectProvider) Configure(ctx context.Context, req provider.Config
|
|||
return
|
||||
}
|
||||
|
||||
// Default values to environment variables, but override
|
||||
// with Terraform configuration value if set.
|
||||
baseURL := os.Getenv("EDGE_CONNECT_BASE_URL")
|
||||
token := os.Getenv("EDGE_CONNECT_TOKEN")
|
||||
username := os.Getenv("EDGE_CONNECT_USERNAME")
|
||||
password := os.Getenv("EDGE_CONNECT_PASSWORD")
|
||||
|
||||
if !config.BaseURL.IsNull() {
|
||||
baseURL = config.BaseURL.ValueString()
|
||||
}
|
||||
|
||||
if !config.Token.IsNull() {
|
||||
token = config.Token.ValueString()
|
||||
}
|
||||
|
||||
if !config.Username.IsNull() {
|
||||
username = config.Username.ValueString()
|
||||
}
|
||||
|
||||
if !config.Password.IsNull() {
|
||||
password = config.Password.ValueString()
|
||||
}
|
||||
|
||||
// If any of the expected configurations are missing, return
|
||||
// errors with provider-specific guidance.
|
||||
if baseURL == "" {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("base_url"),
|
||||
"Missing Edge Connect API Base URL",
|
||||
"The provider requires a base URL for the Edge Connect API. "+
|
||||
"Set the base_url value in the configuration or use the EDGE_CONNECT_BASE_URL environment variable. "+
|
||||
"If either is already set, ensure the value is not empty.",
|
||||
)
|
||||
}
|
||||
|
||||
if token == "" && (username == "" || password == "") {
|
||||
resp.Diagnostics.AddError(
|
||||
"Missing Edge Connect API Authentication",
|
||||
"The provider requires either a bearer token or username/password for authentication. "+
|
||||
"Set the token value in the configuration or use the EDGE_CONNECT_TOKEN environment variable, "+
|
||||
"or set username and password values in the configuration or use the EDGE_CONNECT_USERNAME and EDGE_CONNECT_PASSWORD environment variables.",
|
||||
)
|
||||
}
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx = tflog.SetField(ctx, "edge_connect_base_url", baseURL)
|
||||
ctx = tflog.SetField(ctx, "edge_connect_token", token)
|
||||
ctx = tflog.SetField(ctx, "edge_connect_username", username)
|
||||
ctx = tflog.SetField(ctx, "edge_connect_password", password)
|
||||
ctx = tflog.SetField(ctx, "edge_connect_endpoint", endpoint)
|
||||
ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "edge_connect_token")
|
||||
ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "edge_connect_password")
|
||||
|
||||
tflog.Debug(ctx, "Creating Edge Connect client")
|
||||
|
||||
// Create a new Edge Connect client using the configuration values
|
||||
apiClient := client.NewClient(baseURL, token, username, password)
|
||||
client := edgeclient.NewClient(endpoint)
|
||||
|
||||
// Test the connection
|
||||
if err := apiClient.HealthCheck(); err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unable to Connect to Edge Connect API",
|
||||
"An error occurred while connecting to the Edge Connect API. "+
|
||||
"Please verify that your base URL and authentication credentials are correct.\n\n"+
|
||||
"Edge Connect Client Error: "+err.Error(),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Make the Edge Connect client available during DataSource and Resource
|
||||
// type Configure methods.
|
||||
resp.DataSourceData = apiClient
|
||||
resp.ResourceData = apiClient
|
||||
resp.DataSourceData = client
|
||||
resp.ResourceData = client
|
||||
|
||||
tflog.Info(ctx, "Configured Edge Connect client", map[string]any{"success": true})
|
||||
}
|
||||
|
||||
// DataSources defines the data sources implemented in the provider.
|
||||
func (p *edgeConnectProvider) DataSources(_ context.Context) []func() datasource.DataSource {
|
||||
return []func() datasource.DataSource{
|
||||
NewAppDataSource,
|
||||
NewAppInstDataSource,
|
||||
func (p *EdgeConnectProvider) Resources(ctx context.Context) []func() resource.Resource {
|
||||
return []func() resource.Resource{
|
||||
NewAppResource,
|
||||
NewAppInstanceResource,
|
||||
}
|
||||
}
|
||||
|
||||
// Resources defines the resources implemented in the provider.
|
||||
func (p *edgeConnectProvider) Resources(_ context.Context) []func() resource.Resource {
|
||||
return []func() resource.Resource{
|
||||
NewAppResource,
|
||||
NewAppInstResource,
|
||||
func (p *EdgeConnectProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
|
||||
return []func() datasource.DataSource{
|
||||
NewAppDataSource,
|
||||
NewAppInstanceDataSource,
|
||||
}
|
||||
}
|
||||
|
||||
func New(version string) func() provider.Provider {
|
||||
return func() provider.Provider {
|
||||
return &EdgeConnectProvider{
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue