From b5a9fd67a069081a7c66f52b0d7870b4f9748661 Mon Sep 17 00:00:00 2001 From: Ye Chen <127243817+yec-akamai@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:17:49 -0500 Subject: [PATCH] Release v0.7.0 (#62) * release v0.7.0 * add release v0.7.0 --- package.json | 2 +- releases/v0.7.0/component.css | 3 + releases/v0.7.0/component.js | 138 ++++++ releases/v0.7.0/linode-addons.yml | 718 ++++++++++++++++++++++++++++++ releases/v0.7.0/linode.svg | 22 + 5 files changed, 882 insertions(+), 1 deletion(-) create mode 100644 releases/v0.7.0/component.css create mode 100644 releases/v0.7.0/component.js create mode 100644 releases/v0.7.0/linode-addons.yml create mode 100644 releases/v0.7.0/linode.svg diff --git a/package.json b/package.json index ea17b7e..337de64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui-driver-linode", - "version": "0.6.0", + "version": "0.7.0", "description": "Rancher UI driver for the Linode docker-machine driver", "repository": { "type": "git", diff --git a/releases/v0.7.0/component.css b/releases/v0.7.0/component.css new file mode 100644 index 0000000..da41fd1 --- /dev/null +++ b/releases/v0.7.0/component.css @@ -0,0 +1,3 @@ +.machine-driver.linode { + background-image: url('linode.svg'); +} diff --git a/releases/v0.7.0/component.js b/releases/v0.7.0/component.js new file mode 100644 index 0000000..098acdc --- /dev/null +++ b/releases/v0.7.0/component.js @@ -0,0 +1,138 @@ +"use strict"; + +define("nodes/components/driver-linode/component", ["exports", "shared/mixins/node-driver"], function (exports, _nodeDriver) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + const LAYOUT = "PHNlY3Rpb24gY2xhc3M9Imhvcml6b250YWwtZm9ybSI+CiAge3sjYWNjb3JkaW9uLWxpc3Qgc2hvd0V4cGFuZEFsbD1mYWxzZSBhcyB8IGFsIGV4cGFuZEZuIHx9fQogICB7eyNpZiAoZXEgc3RlcCAxKX19CiAgICAgIHt7I2FjY29yZGlvbi1saXN0LWl0ZW0KICAgICAgICAgdGl0bGU9KHQgIm1vZGFsQWRkQ2xvdWRLZXkubGlub2RlLnRva2VuLmxhYmVsIikKICAgICAgICAgZGV0YWlsPSh0ICJtb2RhbEFkZENsb3VkS2V5Lmxpbm9kZS50b2tlbi5oZWxwIiBodG1sU2FmZT10cnVlKQogICAgICAgICBleHBhbmRBbGw9ZXhwYW5kQWxsCiAgICAgICAgIGV4cGFuZD0oYWN0aW9uIGV4cGFuZEZuKQogICAgICAgICBleHBhbmRPbkluaXQ9dHJ1ZQogICAgICB9fQogICAgICAgIHt7Zm9ybS1hdXRoLWNsb3VkLWNyZWRlbnRpYWwKICAgICAgICAgIGRyaXZlck5hbWU9ZHJpdmVyTmFtZQogICAgICAgICAgcGFyc2VBbmRDb2xsZWN0RXJyb3JzPShhY3Rpb24gImVycm9ySGFuZGxlciIpCiAgICAgICAgICBwcmltYXJ5UmVzb3VyY2U9cHJpbWFyeVJlc291cmNlCiAgICAgICAgICBjbG91ZENyZWRlbnRpYWxzPWNsb3VkQ3JlZGVudGlhbHMKICAgICAgICAgIGZpbmlzaEFuZFNlbGVjdENsb3VkQ3JlZGVudGlhbD0oYWN0aW9uICJmaW5pc2hBbmRTZWxlY3RDbG91ZENyZWRlbnRpYWwiKQogICAgICAgICAgcHJvZ3Jlc3NTdGVwPShhY3Rpb24gImF1dGhMaW5vZGUiKQogICAgICAgICAgY2FuY2VsPShhY3Rpb24gImNhbmNlbCIpCiAgICAgICAgICBjcmVhdGVMYWJlbD0ibW9kYWxBZGRDbG91ZEtleS5saW5vZGUuYXV0aEFjY291bnRCdXR0b24iCiAgICAgICAgfX0KICAgICAge3svYWNjb3JkaW9uLWxpc3QtaXRlbX19CiAgICB7e3RvcC1lcnJvcnMgZXJyb3JzPWVycm9yc319CiAge3tlbHNlfX0KICB7eyNhY2NvcmRpb24tbGlzdCBzaG93RXhwYW5kQWxsPWZhbHNlIGFzIHwgYWwgZXhwYW5kRm4gfH19CiAgICB7eyEtLSBUaGlzIGxpbmUgc2hvd3MgdGhlIGRyaXZlciB0aXRsZSB3aGljaCB5b3UgZG9uJ3QgaGF2ZSB0byBjaGFuZ2UgaXQgLS19fQogICAgPGRpdiBjbGFzcz0ib3Zlci1ociI+PHNwYW4+e3tkcml2ZXJPcHRpb25zVGl0bGV9fTwvc3Bhbj48L2Rpdj4KICAgICAge3sjYWNjb3JkaW9uLWxpc3QtaXRlbQogICAgICAgIHRpdGxlPSJJbnN0YW5jZSBPcHRpb25zIgogICAgICAgIGRldGFpbD0iQ29uZmlndXJlIHRoZSBvcHRpb25zIGZvciB0aGUgTGlub2RlIEluc3RhbmNlcyB0aGF0IHdpbGwgYmUgY3JlYXRlZCBieSB0aGlzIHRlbXBsYXRlLiIKICAgICAgICBleHBhbmRBbGw9ZXhwYW5kQWxsCiAgICAgICAgZXhwYW5kPShhY3Rpb24gZXhwYW5kRm4pCiAgICAgICAgZXhwYW5kT25Jbml0PXRydWUKICAgICAgfX0KICAgICAge3shLS0gU3RhcnQgb2YgTGlub2RlIE9wdGlvbnMgLS19fQogICAgICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wgc3Bhbi02Ij4KICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJhY2MtbGFiZWwiPlJlZ2lvbjwvbGFiZWw+CiAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9ImZvcm0tY29udHJvbCIgb25jaGFuZ2U9e3thY3Rpb24gKG11dCBtb2RlbC5saW5vZGVDb25maWcucmVnaW9uKSB2YWx1ZT0idGFyZ2V0LnZhbHVlIiB9fT4KICAgICAgICAgICAgICB7eyNlYWNoIHJlZ2lvbkNob2ljZXMgYXMgfGNob2ljZXx9fQogICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT17e2Nob2ljZS5pZH19IHNlbGVjdGVkPXt7ZXEgbW9kZWwubGlub2RlQ29uZmlnLnJlZ2lvbiBjaG9pY2UuaWR9fT57e2Nob2ljZS5sYWJlbH19PC9vcHRpb24+CiAgICAgICAgICAgICAge3svZWFjaH19CiAgICAgICAgICAgIDwvc2VsZWN0PgogICAgICAgICAgPC9kaXY+CgogICAgICAgICAgPGRpdiBjbGFzcz0iY29sIHNwYW4tNiI+CiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iYWNjLWxhYmVsIj5JbnN0YW5jZSBUeXBlPC9sYWJlbD4KICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz0iZm9ybS1jb250cm9sIiBvbmNoYW5nZT17e2FjdGlvbiAobXV0IG1vZGVsLmxpbm9kZUNvbmZpZy5pbnN0YW5jZVR5cGUpIHZhbHVlPSJ0YXJnZXQudmFsdWUiIH19PgogICAgICAgICAgICAgIHt7I2VhY2ggc2l6ZUNob2ljZXMgYXMgfGNob2ljZXx9fQogICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT17e2Nob2ljZS5pZH19IHNlbGVjdGVkPXt7ZXEgbW9kZWwubGlub2RlQ29uZmlnLmluc3RhbmNlVHlwZSBjaG9pY2UuaWR9fT57e2Nob2ljZS5sYWJlbH19IC0ge3tjaG9pY2UudmNwdXN9fSB2Q1BVcywge3tjaG9pY2UubWVtb3J5fX1HQiBNZW1vcnksIHt7Y2hvaWNlLmRpc2t9fUdCIERpc2sgc3BhY2U8L29wdGlvbj4KICAgICAgICAgICAgICB7ey9lYWNofX0KICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJyb3ciPgogICAgICAgICAgPGRpdiBjbGFzcz0iY29sIHNwYW4tNiI+CiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iYWNjLWxhYmVsIj5JbWFnZTwvbGFiZWw+CiAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9ImZvcm0tY29udHJvbCIgb25jaGFuZ2U9e3thY3Rpb24gKG11dCBtb2RlbC5saW5vZGVDb25maWcuaW1hZ2UpIHZhbHVlPSJ0YXJnZXQudmFsdWUiIH19PgogICAgICAgICAgICAgIHt7I2VhY2ggaW1hZ2VDaG9pY2VzIGFzIHxjaG9pY2V8fX0KICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9e3tjaG9pY2UuaWR9fSBzZWxlY3RlZD17e2VxIG1vZGVsLmxpbm9kZUNvbmZpZy5pbWFnZSBjaG9pY2UuaWR9fT57e2Nob2ljZS5sYWJlbH19PC9vcHRpb24+CiAgICAgICAgICAgICAge3svZWFjaH19CiAgICAgICAgICAgIDwvc2VsZWN0PgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICB7eyN1bmxlc3MgcHJvZmlsZS5yZXN0cmljdGVkIH19CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbCBzcGFuLTYiPgogICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iYWNjLWxhYmVsIj5UYWdzPC9sYWJlbD4KICAgICAgICAgICAgICB7eyBpbnB1dCBjbGFzc05hbWVzPSJmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJFeGFtcGxlczogdGFnQSwgdGFnQiwgdGFnQyIgdmFsdWU9bW9kZWwubGlub2RlQ29uZmlnLnRhZ3MgfX0KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICB7ey91bmxlc3N9fQogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wgc3Bhbi02Ij4KICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJhY2MtbGFiZWwiPlByaXZhdGUgSVA8L2xhYmVsPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjaGVja2JveCI+CiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJhY2MtbGFiZWwiPnt7aW5wdXQgdHlwZT0iY2hlY2tib3giIGNoZWNrZWQ9bW9kZWwubGlub2RlQ29uZmlnLmNyZWF0ZVByaXZhdGVJcH19IEFkZCBhIFByaXZhdGUgSVA8L2xhYmVsPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICB7ey9hY2NvcmRpb24tbGlzdC1pdGVtfX0KICAgICAge3shLS0gRW5kIG9mIExpbm9kZSBPcHRpb25zIC0tfX0KICAgICAge3sjYWNjb3JkaW9uLWxpc3QtaXRlbQogICAgICAgIHRpdGxlPSJBdXRoZW50aWNhdGlvbiIKICAgICAgICBkZXRhaWw9IkNvbmZpZ3VyZSBMaW5vZGUgdXNlciBTU0ggS2V5cyBhbmQgYSBwYXNzd29yZCBmb3IgdGhlICdyb290JyB1c2VyIGFjY291bnQiCiAgICAgICAgZXhwYW5kQWxsPWV4cGFuZEFsbAogICAgICAgIGV4cGFuZD0oYWN0aW9uIGV4cGFuZEZuKQogICAgICAgIGV4cGFuZE9uSW5pdD1mYWxzZQogICAgICB9fQogICAgICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wgc3Bhbi0xMiI+CiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iYWNjLWxhYmVsIj5QYXNzd29yZCBmb3IgdGhlICJyb290IiB1c2VyPC9sYWJlbD4KICAgICAgICAgICAge3sgaW5wdXQKICAgICAgICAgICAgICB0eXBlPSJwYXNzd29yZCIKICAgICAgICAgICAgICBjbGFzc05hbWVzPSJmb3JtLWNvbnRyb2wiCiAgICAgICAgICAgICAgdmFsdWU9bW9kZWwubGlub2RlQ29uZmlnLnJvb3RQYXNzCiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9ImFDb21wbGV4UEBzc3dvcmQiCiAgICAgICAgICAgIH19CiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbCBzcGFuLTEyIj4KICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJhY2MtbGFiZWwiPkxpbm9kZSBVc2VybmFtZXM8L2xhYmVsPgogICAgICAgICAgICB7eyBpbnB1dCBjbGFzc05hbWVzPSJmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSJ5b3VydXNlcm5hbWUiIHZhbHVlPW1vZGVsLmxpbm9kZUNvbmZpZy5hdXRob3JpemVkVXNlcnMgfX0KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICB7ey9hY2NvcmRpb24tbGlzdC1pdGVtfX0KICAgICAge3sjYWNjb3JkaW9uLWxpc3QtaXRlbQogICAgICAgIHRpdGxlPSJTdGFja1NjcmlwdHMiCiAgICAgICAgZGV0YWlsPSJDb25maWd1cmUgYSBTdGFja1NjcmlwdCB0byBydW4gb24gZmlyc3QgYm9vdCIKICAgICAgICBleHBhbmRBbGw9ZXhwYW5kQWxsCiAgICAgICAgZXhwYW5kPShhY3Rpb24gZXhwYW5kRm4pCiAgICAgICAgZXhwYW5kT25Jbml0PWZhbHNlCiAgICAgIH19CiAgICAgICAgPGRpdiBjbGFzcz0icm93Ij4KICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbCBzcGFuLTEyIj4KICAgICAgICAgICAgPGxhYmVsIGNsYXNzPSJhY2MtbGFiZWwiPlN0YWNrU2NyaXB0ICg8YSBocmVmPSJodHRwczovL2Nsb3VkLmxpbm9kZS5jb20vc3RhY2tzY3JpcHRzIiB0YXJnZXQ9Il9ibGFuayIgcmVsPSJub2ZvbGxvdyBub3JlZmVycmVyIG5vb3BlbmVyIj5tYW5hZ2UgeW91ciBTdGFja1NjcmlwdHM8L2E+KTwvbGFiZWw+CiAgICAgICAgICAgIHt7IGlucHV0CiAgICAgICAgICAgIGNsYXNzTmFtZXM9ImZvcm0tY29udHJvbCIKICAgICAgICAgICAgcGxhY2Vob2xkZXI9IkV4YW1wbGVzOiAndXNlcm5hbWUvU3RhY2tzY3JpcHQgTGFiZWwnIG9yICcxMjM0NSciCiAgICAgICAgICAgIHZhbHVlPW1vZGVsLmxpbm9kZUNvbmZpZy5zdGFja3NjcmlwdAogICAgICAgICAgICB9fQogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wgc3Bhbi0xMiI+CiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iYWNjLWxhYmVsIj5TdGFja1NjcmlwdCBWYXJpYWJsZXM8L2xhYmVsPgogICAgICAgICAgICB7eyB0ZXh0YXJlYSBjbGFzc05hbWVzPSJmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSd7ICJleGFtcGxlIjogInZhbHVlIiwgImpzb24iOiB0cnVlIH0nIHZhbHVlPW1vZGVsLmxpbm9kZUNvbmZpZy5zdGFja3NjcmlwdERhdGEgfX0KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICB7ey9hY2NvcmRpb24tbGlzdC1pdGVtfX0KICAgICAge3shLS0gRW5kIG9mIExpbm9kZSBPcHRpb25zIC0tfX0KCiAgICB7eyEtLSBUaGlzIGZvbGxvd2luZyBjb250YWlucyB0aGUgTmFtZSwgTGFiZWxzIGFuZCBFbmdpbmUgT3B0aW9ucyBmaWVsZHMgLS19fQogICAgPGRpdiBjbGFzcz0ib3Zlci1ociI+PHNwYW4+e3t0ZW1wbGF0ZU9wdGlvbnNUaXRsZX19PC9zcGFuPjwvZGl2PgoKICAgIHt7Zm9ybS1uYW1lLWRlc2NyaXB0aW9uCiAgICAgIG1vZGVsPW1vZGVsCiAgICAgIG5hbWVSZXF1aXJlZD10cnVlCiAgICB9fQoKICAgIHt7Zm9ybS11c2VyLWxhYmVscwogICAgICBpbml0aWFsTGFiZWxzPWxhYmVsUmVzb3VyY2UubGFiZWxzCiAgICAgIHNldExhYmVscz0oYWN0aW9uICdzZXRMYWJlbHMnKQogICAgICBleHBhbmRBbGw9ZXhwYW5kQWxsCiAgICAgIGV4cGFuZD0oYWN0aW9uIGV4cGFuZEZuKQogICAgfX0KCiAgICB7e2Zvcm0tZW5naW5lLW9wdHMKICAgICAgbWFjaGluZT1tb2RlbAogICAgICBzaG93RW5naW5lVXJsPXNob3dFbmdpbmVVcmwKICAgIH19CiAge3svYWNjb3JkaW9uLWxpc3R9fQoKCiAge3shLS0gVGhpcyBjb21wb25lbnQgc2hvd3MgZXJyb3JzIHByb2R1Y2VkIGJ5IHZhbGlkYXRlKCkgaW4gdGhlIGNvbXBvbmVudCAtLX19CiAge3t0b3AtZXJyb3JzIGVycm9ycz1lcnJvcnN9fQoKICB7eyEtLSBUaGlzIGNvbXBvbmVudCBzaG93cyB0aGUgQ3JlYXRlIGFuZCBDYW5jZWwgYnV0dG9ucyAtLX19CiAge3tzYXZlLWNhbmNlbCBzYXZlPShhY3Rpb24gInNhdmUiKSBlZGl0aW5nPWVkaXRpbmcgY2FuY2VsPShhY3Rpb24gImNhbmNlbCIpfX0KICB7ey9pZn19CiAge3svYWNjb3JkaW9uLWxpc3R9fQo8L3NlY3Rpb24+Cg=="; + const computed = Ember.computed; + const get = Ember.get; + const set = Ember.set; + const alias = Ember.computed.alias; + const service = Ember.inject.service; + const observer = Ember.observer; + const hash = Ember.RSVP.hash; + const defaultRadix = 10; + const defaultBase = 1024; + exports.default = Ember.Component.extend(_nodeDriver.default, { + driverName: 'linode', + step: 1, + config: alias('model.linodeConfig'), + app: service(), + intl: service(), + linode: service(), + init() { + const decodedLayout = window.atob(LAYOUT); + const template = Ember.HTMLBars.compile(decodedLayout, { + moduleName: 'nodes/components/driver-linode/template' + }); + set(this, 'layout', template); + this._super(...arguments); + }, + bootstrap: function () { + let config = get(this, 'globalStore').createRecord({ + type: 'linodeConfig', + instanceType: 'g6-standard-4', + region: 'us-iad', + image: 'linode/ubuntu22.04', + uaPrefix: 'Rancher', + tags: '', + authorizedUsers: '', + createPrivateIp: true, + stackscript: '', + stackscriptData: '', + rootPass: null + }); + set(this, 'model.linodeConfig', config); + }, + validate() { + this._super(); + var errors = get(this, 'errors') || []; + if (!get(this, 'model.name')) { + errors.push('Name is required'); + } + if (!this.get('model.linodeConfig.instanceType')) { + errors.push('Specifying a linode Instance Type is required'); + } + if (!this.get('model.linodeConfig.image')) { + errors.push('Specifying a linode Image is required'); + } + if (!this.get('model.linodeConfig.region')) { + errors.push('Specifying a linode Region is required'); + } + if (!this.validateCloudCredentials()) { + errors.push(this.intl.t('nodeDriver.cloudCredentialError')); + } + if (get(errors, 'length')) { + set(this, 'errors', errors); + return false; + } else { + set(this, 'errors', null); + return true; + } + }, + actions: { + finishAndSelectCloudCredential(cred) { + if (cred) { + set(this, 'model.cloudCredentialId', get(cred, 'id')); + this.send('authLinode'); + } + }, + authLinode(cb) { + const auth = { + type: 'cloud', + token: get(this, 'model.cloudCredentialId') + }; + hash({ + regions: this.linode.request(auth, 'regions'), + images: this.linode.request(auth, 'images'), + sizes: this.linode.request(auth, 'linode/types') + }).then(responses => { + this.setProperties({ + errors: [], + step: 2, + restricted: responses.regions.restricted, + regionChoices: responses.regions.data.map(region => { + region.label = region.id.slice(0, 4).toUpperCase() + region.id.slice(4) + " (" + region.country.toUpperCase() + ")"; + return region; + }).sort((a, b) => String.prototype.localeCompare(a, b)), + imageChoices: responses.images.data.filter(image => /^linode.(ubuntu22.04|ubuntu20.04|ubuntu18.04|ubuntu16.04|debian10|debian9)/.test(image.id) && !image.id.includes('kube')).sort((a, b) => a.id > b.id), + sizeChoices: responses.sizes.data.map(size => { + size.disk /= 1024; + size.memory /= 1024; + return size; + }) + }); + }).catch(err => { + let errors = get(this, 'errors') || []; + if (err && err.body && err.body.errors && err.body.errors[0]) { + errors.push(`Error received from Linode: ${err.body.errors[0].reason}`); + } else { + errors.push(`Error received from Linode`); + } + this.setProperties({ + errors + }); + cb(); + }); + } + } + }); +});; +"use strict"; + +define("ui/components/driver-linode/component", ["exports", "nodes/components/driver-linode/component"], function (exports, _component) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + Object.defineProperty(exports, "default", { + enumerable: true, + get: function () { + return _component.default; + } + }); +}); \ No newline at end of file diff --git a/releases/v0.7.0/linode-addons.yml b/releases/v0.7.0/linode-addons.yml new file mode 100644 index 0000000..c55b8a8 --- /dev/null +++ b/releases/v0.7.0/linode-addons.yml @@ -0,0 +1,718 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ccm-linode + namespace: kube-system +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: system:ccm-linode +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + # TODO: make these permissions more fine-grained + name: cluster-admin +subjects: + - kind: ServiceAccount + name: ccm-linode + namespace: kube-system +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: ccm-linode + labels: + app: ccm-linode + namespace: kube-system +spec: + selector: + matchLabels: + app: ccm-linode + template: + metadata: + labels: + app: ccm-linode + spec: + serviceAccountName: ccm-linode + nodeSelector: + # The CCM will only run on a Node labelled as a master, you may want to change this + node-role.kubernetes.io/controlplane: "true" + tolerations: + # The CCM can run on Nodes tainted as masters + - key: "node-role.kubernetes.io/controlplane" + effect: "NoSchedule" + # The CCM is a "critical addon" + - key: "CriticalAddonsOnly" + operator: "Exists" + # This taint is set on all Nodes when an external CCM is used + - key: node.cloudprovider.kubernetes.io/uninitialized + value: "true" + effect: NoSchedule + - key: node.kubernetes.io/not-ready + operator: Exists + effect: NoSchedule + - key: node.kubernetes.io/unreachable + operator: Exists + effect: NoSchedule + hostNetwork: true + containers: + - image: linode/linode-cloud-controller-manager:latest + imagePullPolicy: Always + name: ccm-linode + args: + - --cloud-provider=linode + - --v=3 + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + env: + - name: LINODE_API_TOKEN + valueFrom: + secretKeyRef: + name: linode + key: token + - name: LINODE_REGION + valueFrom: + secretKeyRef: + name: linode + key: region + volumes: + - name: k8s + hostPath: + path: /etc/kubernetes +--- +allowVolumeExpansion: true +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: linode-block-storage + namespace: kube-system +provisioner: linodebs.csi.linode.com +--- +allowVolumeExpansion: true +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + annotations: + storageclass.kubernetes.io/is-default-class: "true" + name: linode-block-storage-retain + namespace: kube-system +provisioner: linodebs.csi.linode.com +reclaimPolicy: Retain +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: csi-controller-sa + namespace: kube-system +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: csi-node-sa + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: linode-csi-role + namespace: kube-system +rules: + - apiGroups: + - "" + resources: + - events + verbs: + - get + - list + - watch + - create + - update + - patch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-attacher-role +rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - update + - patch + - apiGroups: + - storage.k8s.io + resources: + - csinodes + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - volumeattachments + verbs: + - get + - list + - watch + - update + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-provisioner-role +rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - update + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - list + - watch + - create + - update + - patch + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - get + - list + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotcontents + verbs: + - get + - list + - apiGroups: + - storage.k8s.io + resources: + - csinodes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-resizer-role +rules: + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - patch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims/status + verbs: + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - list + - watch + - create + - update + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: linode-csi-binding + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: linode-csi-role +subjects: + - kind: ServiceAccount + name: csi-node-sa + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: csi-controller-attacher-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-attacher-role +subjects: + - kind: ServiceAccount + name: csi-controller-sa + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: csi-controller-provisioner-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-provisioner-role +subjects: + - kind: ServiceAccount + name: csi-controller-sa + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: csi-controller-resizer-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-resizer-role +subjects: + - kind: ServiceAccount + name: csi-controller-sa + namespace: kube-system +--- +apiVersion: v1 +data: + get-linode-id.sh: |- + #!/bin/bash -efu + id="$(kubectl get node/"${NODE_NAME}" -o jsonpath='{.spec.providerID}')" + if [[ ! -z "${id}" ]]; then + echo "${id}" + echo -n "${id:9}" > /linode-info/linode-id + exit 0 + fi + echo "Provider ID not found" + # Exit here so that we wait for the CCM to initialize the provider ID + exit 1 +kind: ConfigMap +metadata: + labels: + app: csi-linode + name: get-linode-id + namespace: kube-system +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + app: csi-linode-controller + name: csi-linode-controller + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: csi-linode-controller + serviceName: csi-linode + template: + metadata: + labels: + app: csi-linode-controller + role: csi-linode + spec: + containers: + - args: + - --default-fstype=ext4 + - --volume-name-prefix=pvc + - --volume-name-uuid-length=16 + - --csi-address=$(ADDRESS) + - --v=2 + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + image: k8s.gcr.io/sig-storage/csi-provisioner:v3.0.0 + imagePullPolicy: IfNotPresent + name: csi-provisioner + volumeMounts: + - mountPath: /var/lib/csi/sockets/pluginproxy/ + name: socket-dir + - args: + - --v=2 + - --csi-address=$(ADDRESS) + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + image: k8s.gcr.io/sig-storage/csi-attacher:v3.3.0 + imagePullPolicy: IfNotPresent + name: csi-attacher + volumeMounts: + - mountPath: /var/lib/csi/sockets/pluginproxy/ + name: socket-dir + - args: + - --v=2 + - --csi-address=$(ADDRESS) + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + image: k8s.gcr.io/sig-storage/csi-resizer:v1.3.0 + imagePullPolicy: IfNotPresent + name: csi-resizer + volumeMounts: + - mountPath: /var/lib/csi/sockets/pluginproxy/ + name: socket-dir + - args: + - --endpoint=$(CSI_ENDPOINT) + - --token=$(LINODE_TOKEN) + - --url=$(LINODE_API_URL) + - --node=$(NODE_NAME) + - --bs-prefix=$(LINODE_BS_PREFIX) + - --v=2 + env: + - name: CSI_ENDPOINT + value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock + - name: LINODE_API_URL + value: https://api.linode.com/v4 + - name: LINODE_BS_PREFIX + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: LINODE_TOKEN + valueFrom: + secretKeyRef: + key: token + name: linode + image: linode/linode-blockstorage-csi-driver:v0.5.0 + name: linode-csi-plugin + volumeMounts: + - mountPath: /linode-info + name: linode-info + - mountPath: /scripts + name: get-linode-id + - mountPath: /var/lib/csi/sockets/pluginproxy/ + name: socket-dir + initContainers: + - command: + - /scripts/get-linode-id.sh + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + image: bitnami/kubectl:1.16.3-debian-10-r36 + name: init + volumeMounts: + - mountPath: /linode-info + name: linode-info + - mountPath: /scripts + name: get-linode-id + serviceAccount: csi-controller-sa + tolerations: + - effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + volumes: + - emptyDir: {} + name: socket-dir + - emptyDir: {} + name: linode-info + - configMap: + defaultMode: 493 + name: get-linode-id + name: get-linode-id +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + app: csi-linode-node + name: csi-linode-node + namespace: kube-system +spec: + selector: + matchLabels: + app: csi-linode-node + template: + metadata: + labels: + app: csi-linode-node + role: csi-linode + spec: + containers: + - args: + - --v=2 + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + env: + - name: ADDRESS + value: /csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: /var/lib/kubelet/plugins/linodebs.csi.linode.com/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v1.3.0 + name: csi-node-driver-registrar + volumeMounts: + - mountPath: /csi + name: plugin-dir + - mountPath: /registration + name: registration-dir + - args: + - --endpoint=$(CSI_ENDPOINT) + - --token=$(LINODE_TOKEN) + - --url=$(LINODE_API_URL) + - --node=$(NODE_NAME) + - --v=2 + env: + - name: CSI_ENDPOINT + value: unix:///csi/csi.sock + - name: LINODE_API_URL + value: https://api.linode.com/v4 + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: LINODE_TOKEN + valueFrom: + secretKeyRef: + key: token + name: linode + image: linode/linode-blockstorage-csi-driver:v0.5.0 + imagePullPolicy: Always + name: csi-linode-plugin + securityContext: + allowPrivilegeEscalation: true + capabilities: + add: + - SYS_ADMIN + privileged: true + volumeMounts: + - mountPath: /linode-info + name: linode-info + - mountPath: /scripts + name: get-linode-id + - mountPath: /csi + name: plugin-dir + - mountPath: /var/lib/kubelet + mountPropagation: Bidirectional + name: pods-mount-dir + - mountPath: /dev + name: device-dir + hostNetwork: true + initContainers: + - command: + - /scripts/get-linode-id.sh + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + image: bitnami/kubectl:1.16.3-debian-10-r36 + name: init + volumeMounts: + - mountPath: /linode-info + name: linode-info + - mountPath: /scripts + name: get-linode-id + priorityClassName: system-node-critical + serviceAccount: csi-node-sa + tolerations: + - effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + volumes: + - emptyDir: {} + name: linode-info + - configMap: + defaultMode: 493 + name: get-linode-id + name: get-linode-id + - hostPath: + path: /var/lib/kubelet/plugins_registry/ + type: DirectoryOrCreate + name: registration-dir + - hostPath: + path: /var/lib/kubelet + type: Directory + name: kubelet-dir + - hostPath: + path: /var/lib/kubelet/plugins/linodebs.csi.linode.com + type: DirectoryOrCreate + name: plugin-dir + - hostPath: + path: /var/lib/kubelet + type: Directory + name: pods-mount-dir + - hostPath: + path: /dev + name: device-dir + - hostPath: + path: /etc/udev + type: Directory + name: udev-rules-etc + - hostPath: + path: /lib/udev + type: Directory + name: udev-rules-lib + - hostPath: + path: /run/udev + type: Directory + name: udev-socket + - hostPath: + path: /sys + type: Directory + name: sys +--- +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: linodebs.csi.linode.com +spec: + attachRequired: true + podInfoOnMount: true +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-dns + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-dns + namespace: kube-system +rules: + - apiGroups: [""] + resources: ["services","endpoints","pods"] + verbs: ["get","watch","list"] + - apiGroups: ["extensions","networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get","watch","list"] + - apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: external-dns-viewer + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-dns +subjects: + - kind: ServiceAccount + name: external-dns + namespace: kube-system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns + namespace: kube-system +spec: + strategy: + type: Recreate + selector: + matchLabels: + app: external-dns + template: + metadata: + labels: + app: external-dns + spec: + serviceAccountName: external-dns + containers: + - name: external-dns + image: registry.opensource.zalan.do/teapot/external-dns:latest + args: + - --provider=linode + # - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. + env: + - name: EXTERNAL_DNS_SOURCE + value: |- + service + ingress + - name: LINODE_TOKEN + valueFrom: + secretKeyRef: + name: linode + key: token +--- diff --git a/releases/v0.7.0/linode.svg b/releases/v0.7.0/linode.svg new file mode 100644 index 0000000..56989c0 --- /dev/null +++ b/releases/v0.7.0/linode.svg @@ -0,0 +1,22 @@ + + The Linode Logo consists of the 5 shaded green cubes arranged in the shape of the letter "L". + Linode Logo with linode.com domain name + + + + + + + + + + + + + + + + + + \ No newline at end of file