Compare commits

..

42 Commits

Author SHA1 Message Date
yi-portainer
2e92706ead Merge branch 'release/2.5' 2021-05-24 08:50:46 +12:00
Chaim Lev-Ari
819faa3948 fix(k8s/proxy): proxy healthz request to k8s api (#5090) 2021-05-21 00:20:08 +02:00
wheresolivia
ef8794c2b9 Merge pull request #5079 from portainer/fix/EE-769/code-editor-prompt-on-change
fix(stacks): check for editor change before setting as dirty
2021-05-20 18:44:46 +12:00
Felix Han
5618794927 fix(k8s-config): check for config editor change before setting as dirty 2021-05-20 11:46:17 +12:00
Felix Han
47d462f085 fix(web-editor): check for editor change before setting as dirty. 2021-05-20 10:22:07 +12:00
Felix Han
e54d99fd3d fix(stacks): remove line breaks in web editors value 2021-05-19 12:09:11 +12:00
Chaim Lev-Ari
b3784792fe fix(stacks): show containers only for standalone (#5080) 2021-05-18 23:06:04 +02:00
Chaim Lev-Ari
87e7d8ada8 fix(stacks): check for editor change before setting as dirty 2021-05-18 14:08:23 +03:00
yi-portainer
d4fa9db432 Merge branch 'release/2.5' 2021-05-17 13:59:38 +12:00
yi-portainer
a28559777f Merge branch 'release/2.1' 2021-05-17 13:43:48 +12:00
yi-portainer
43702c2516 * update portainer version to 2.5.0 2021-05-13 18:30:34 +12:00
Chaim Lev-Ari
a21798f518 fix(docker/containers): show sysctl control (#5051) 2021-05-12 02:29:35 +02:00
dbuduev
3641158daf fix: docker-compose use custom config.json to access private images (#5058)
cherry-picking commit a6b289c9.

Co-authored-by: Dmitry Salakhov <to@dimasalakhov.com>
2021-05-11 23:05:00 +02:00
Chaim Lev-Ari
0ac6274712 fix(docker/services): create a service webhook (#5052) 2021-05-11 10:59:42 +12:00
Chaim Lev-Ari
886d6764be fix(docker): set image pulls as valid if failed fetching (#5055) 2021-05-11 09:24:29 +12:00
Chaim Lev-Ari
b7980f1b60 fix(k8s/ingress): remove only selected ingress (#5035)
* fix(k8s/ingress): remove only selected ingress

* fix(k8s/ingress): remove ingress from namespace
2021-05-07 09:49:56 +12:00
Hui
564bea7575 fix(ACI): ACI UAC breaks when redeploying container with same name asone already existing EE-645 (#5030)
* add existing continer instance checking logic

* modify response status code and err message

* return json instead of plain text for err msg

* Update api/http/proxy/factory/azure/containergroup.go

* Update api/http/proxy/factory/azure/containergroup.go

* Update api/http/proxy/factory/azure/containergroup.go

Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
2021-05-05 20:26:31 +12:00
Chaim Lev-Ari
dcc77e50e5 fix(docker/images): show image selector advanced mode (#5032) 2021-05-05 20:16:59 +12:00
Stéphane Busso
317ebe2bfc Revert "feat(edge) EE-596 Update the version of agent to 2.4.0 in agent deploy command on the adding edge screen (#5021)" (#5031)
This reverts commit 7e2ce3ffc2.
2021-05-05 16:24:20 +12:00
cong meng
7e2ce3ffc2 feat(edge) EE-596 Update the version of agent to 2.4.0 in agent deploy command on the adding edge screen (#5021)
Co-authored-by: Simon Meng <simon.meng@portainer.io>
2021-04-29 16:25:09 +12:00
yi-portainer
f6531627d4 Squashed commit of the following:
commit 535215833d
Author: yi-portainer <yi.chen@portainer.io>
Date:   Thu Feb 4 18:04:18 2021 +1300

    * version change to 2.1.1

commit c4a1243af9
Author: Dmitry Salakhov <to@dimasalakhov.com>
Date:   Thu Feb 4 03:00:25 2021 +0000

    fix: docker-compose use custom config.json to access private images (#4820)

commit 305d0d2da0
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Wed Feb 3 06:38:56 2021 +0100

    fix(k8s/resource-pool): unusable RP access management (#4810)

    (cherry picked from commit e401724d43)

commit e4605d990d
Author: yi-portainer <yi.chen@portainer.io>
Date:   Tue Feb 2 17:42:57 2021 +1300

    * update portainer version

commit 768697157c
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Tue Feb 2 05:00:19 2021 +0100

    sec(app): remove unused and vulnerable dependencies (#4801)

commit d3086da139
Author: cong meng <mcpacino@gmail.com>
Date:   Tue Feb 2 15:10:06 2021 +1300

    fix(k8s) trigger port validation while changing protocol (ce#394) (#4804)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 95894e8047
Author: cong meng <mcpacino@gmail.com>
Date:   Tue Feb 2 15:03:11 2021 +1300

    fix(k8s) parse empty configuration as empty string yaml instead of {} (ce#395) (#4805)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 81de55fedd
Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
Date:   Tue Feb 2 11:12:40 2021 +1300

    * fix missing kubectl download (#4802)

commit 84827b8782
Author: Steven Kang <skan070@gmail.com>
Date:   Sun Jan 31 17:32:30 2021 +1300

    feat(build): introducing buildx for Windows (#4792)

    * feat(build): introducing buildx for Windows

    * feat(build): re-ordered USER

    * feat(build): Fixed Typo

    * feat(build): fixed typo

commit a71e71f481
Author: Dmitry Salakhov <to@dimasalakhov.com>
Date:   Mon Jan 25 19:16:53 2021 +0000

    feat(compose): add docker-compose wrapper (#4713)

    * feat(compose): add docker-compose wrapper

    ce-187

    * fix(compose): pick compose implementation upon startup

    * Add static compose build for linux

    * Fix wget

    * Fix platofrm specific docker-compose download

    * Keep amd64 architecture as download parameter

    * Add tmp folder for docker-compose

    * fix: line endings

    * add proxy server

    * logs

    * Proxy

    * Add lite transport for compose

    * Fix local deployment

    * refactor: pass proxyManager by ref

    * fix: string conversion

    * refactor: compose wrapper remove unused code

    * fix: tests

    * Add edge

    * Fix merge issue

    * refactor: remove unused code

    * Move server to proxy implementation

    * Cleanup wrapper and manager

    * feat: pass max supported compose syntax version with each endpoint

    * fix: pick compose syntax version

    * fix: store wrapper version in portainer

    * Get and show composeSyntaxMaxVersion at stack creation screen

    * Get and show composeSyntaxMaxVersion at stack editor screen

    * refactor: proxy server

    * Fix used tmp

    * Bump docker-compose to 1.28.0

    * remove message for docker compose limitation

    * fix: markup typo

    * Rollback docker compose to 1.27.4

    * * attempt to fix the windows build issue

    * * attempt to debug grunt issue

    * * use console log in grunt file

    * fix: try to fix windows build by removing indirect deps from go.mod

    * Remove tmp folder

    * Remove builder stage

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose - fixed verbose output

    * refactor: renames

    * fix(stack): get endpoint by EndpointProvider

    * fix(stack): use margin to add space between line instead of using br tag

    Co-authored-by: Stéphane Busso <stephane.busso@gmail.com>
    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: yi-portainer <yi.chen@portainer.io>
    Co-authored-by: Steven Kang <skan070@gmail.com>

commit 83f4c5ec0b
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Mon Jan 25 02:43:54 2021 +0100

    fix(k8s/app): remove advanced deployment panel from app details view (#4730)

commit 41308d570d
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Mon Jan 25 02:14:35 2021 +0100

    feat(configurations): Review UI/UX configurations (#4691)

    * feat(configurations): Review UI/UX configurations

    * feat(configurations): fix binary secret value

    * fix(frontend): populate data between simple and advanced modes (#4503)

    * fix(configuration): parseYaml before create configuration

    * fix(configurations): change c to C in ConfigurationOwner

    * fix(application): change configuration index to configuration key in the view

    * fix(configuration): resolve problem in application create with configuration not overriden.

    * fix(configuration): fix bad import in helper

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 46ff8a01bc
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Fri Jan 22 03:08:08 2021 +0200

    fix(kubernetes/pods): save note (#4675)

    * feat(kubernetes/pods): introduce patch api

    * feat(k8s/pods): pod converter

    * feat(kubernetes/pods): introduce patch api

    * feat(k8s/pod): add annotations only if needed

    * fix(k8s/pod): replace class with factory function

commit 2b257d2785
Author: yi-portainer <yi.chen@portainer.io>
Date:   Thu Jan 21 00:02:22 2021 +1300

    Squashed commit of the following 2.0.1 release fixes:

    commit f90d6b55d6
    Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
    Date:   Wed Jan 13 00:56:19 2021 +0200

        feat(service): clear source volume when change type (#4627)

        * feat(service): clear source volume when change type

        * feat(service): init volume source to the correct value

    commit 1b82b450d7
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Thu Jan 7 14:47:32 2021 +1300

        * bump the APIVersion to 2.0.1 (#4688)

    commit b78d804881
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Wed Dec 30 23:03:43 2020 +1300

        Revert "chore(build): bump Kompose version (#4475)" (#4676)

        This reverts commit 380f106571.

        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    commit 51b72c12f9
    Author: Anthony Lapenna <anthony.lapenna@portainer.io>
    Date:   Wed Dec 23 14:45:32 2020 +1300

        fix(docker/stack-details): do not display editor tab for external stack (#4650)

    commit 58c04bdbe3
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Tue Dec 22 13:47:11 2020 +1300

        + silently continue when downloading artifacts in windows (#4637)

    commit a6320d5222
    Author: cong meng <mcpacino@gmail.com>
    Date:   Tue Dec 22 13:38:54 2020 +1300

        fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)

        * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

        * fix(frontend) rephrase comments (#4629)

        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

        Co-authored-by: Simon Meng <simon.meng@portainer.io>
        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

commit da41dbb79a
Author: cong meng <mcpacino@gmail.com>
Date:   Wed Jan 20 15:19:35 2021 +1300

    fix(stack): stacks created via API are incorrectly marked as private with no owner (#3721) (#4725)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 68d42617f2
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Wed Jan 20 01:02:18 2021 +0100

    feat(placement): Add a warning notification under the placement tab when an application cannot be scheduled on any node in the cluster (#4525)

    * feat(placement): Add a warning notification under the placement tab when an application cannot be scheduled on any node in the cluster

    * fix(applications): if there is at least one node the application can schedule on, then do not show the warning

commit 8323e22309
Author: Anthony McMahon <75223906+Anthony-Portainer@users.noreply.github.com>
Date:   Wed Jan 20 12:06:25 2021 +1300

    Update issue templates

    Adding auto labelling to Bug Report (kind/bug, bug/unconfirmed) and Question (kind/question)

commit 20d4341170
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 19 00:10:08 2021 +0200

    fix(state): check validity of state (#4609)

commit 832cafc933
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Mon Jan 18 02:59:57 2021 +0200

    fix(registries): update password only when not empty (#4669)

commit f3c537ac2c
Author: cong meng <mcpacino@gmail.com>
Date:   Mon Jan 18 13:02:16 2021 +1300

    chore(build): bump Kompose version (#4473) (#4724)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 958baf6283
Author: Anthony McMahon <75223906+Anthony-Portainer@users.noreply.github.com>
Date:   Mon Jan 18 09:30:17 2021 +1300

    Update README.md

commit 08e392378e
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Sun Jan 17 09:28:09 2021 +0200

    chore(app): fail on angular components missing nginject (#4224)

commit a2d9734b8b
Author: Alice Groux <alice.grx@gmail.com>
Date:   Sun Jan 17 04:50:22 2021 +0100

    fix(k8s/datatables): reduce size of collapse/expand column for stacks datatable and storage datatable (#4511)

    * fix(k8s/datatables): reduce size of collapse/expand column for stacks datatable and storage datatable

    * fix(k8s/datatables): reduce size of expand/collapse column

commit 15aed9fc6f
Author: DarkAEther <30438425+DarkAEther@users.noreply.github.com>
Date:   Sun Jan 17 06:23:32 2021 +0530

    feat(area/kubernetes): show shared access policy in volume details (#4707)

commit 121d33538d
Author: Alice Groux <alice.grx@gmail.com>
Date:   Fri Jan 15 02:51:36 2021 +0100

    fix(k8s/application): validate load balancer ports inputs (#4426)

    * fix(k8s/application): validate load balancer ports inputs

    * fix(k8s/application): allow user to only change the protocol on the first port mapping

commit 7a03351df8
Author: Olli Janatuinen <olljanat@users.noreply.github.com>
Date:   Thu Jan 14 23:05:33 2021 +0200

    dep(api): Support Docker Stack 3.8 (#4333)

    - Linux: Update Docker binary to version 19.03.13
    - Windows: Update Docker binary to version 19.03.12

commit 0c2987893d
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 14 03:04:44 2021 +0100

    feat(app/images): in advanced mode, remove tooltip and add an information message (#4528)

commit d1eddaa188
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 14 00:24:56 2021 +0100

    feat(app/network): rename restrict external acces to the network label and add a tooltip (#4514)

commit d336ada3c2
Author: Anthony Lapenna <anthony.lapenna@portainer.io>
Date:   Wed Jan 13 16:13:27 2021 +1300

    feat(k8s/application): review application creation warning style (#4613)

commit 839198fbff
Author: Avadhut Tanugade <30384908+mrwhoknows55@users.noreply.github.com>
Date:   Wed Jan 13 04:49:18 2021 +0530

commit 486ffa5bbd
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 12 23:40:09 2021 +0200

    chore(webpack): add source maps (#4471)

    * chore(webpack): add source maps

    * feat(build): fetch source maps for 3rd party libs

commit 4cd468ce21
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Tue Jan 12 02:35:59 2021 +0100

    Can't create kubernetes resources with a username longer than 63 characters (#4672)

    * fix(kubernetes): truncate username when we create resource

    * fix(k8s): remove forbidden characters in owner label

commit cbd7fdc62e
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 12 01:38:49 2021 +0200

    feat(docker/stacks): introduce date info for stacks (#4660)

    * feat(docker/stacks): add creation and update dates

    * feat(docker/stacks): put ownership column as the last column

    * feat(docker/stacks): fix the no stacks message

    * refactor(docker/stacks): make external stacks helpers more readable

    * feat(docker/stacks): add updated and created by

    * feat(docker/stacks): toggle updated column

    * refactor(datatable): create column visibility component

    Co-authored-by: alice groux <alice.grx@gmail.com>

commit b9fe8009dd
Author: DarkAEther <30438425+DarkAEther@users.noreply.github.com>
Date:   Mon Jan 11 08:05:19 2021 +0530

    feat(image-details): Show labels in images datatable (#4287)

    * feat(images): show labels in images datatable

    * move labels to image details view

commit 6a504e7134
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Mon Jan 11 14:44:15 2021 +1300

    fix(settings): Use default setting if UserSessionTimeout not set (#4521)

    * fix(settings): Use default settings if UserSessionTimeout not set

    * Update UserSessionTimeout settings in database if set to empty string

commit 51ba0876a5
Author: Alice Groux <alice.grx@gmail.com>
Date:   Mon Jan 11 00:51:46 2021 +0100

    feat(k8s/configuration): rename add ingress controller button and changed information text (#4540)

commit 769e6a4c6c
Author: Alice Groux <alice.grx@gmail.com>
Date:   Sun Jan 10 23:30:31 2021 +0100

    feat(k8s/configuration): add extra information panel when creating a sensitive configuration (#4541)

commit 105d1ae519
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 15:30:43 2021 +1300

    feat(frontend): de-emphasize internal login when OAuth is enabled (#3065) (#4565)

    * feat(frontend): de-emphasize internal login when OAuth is enabled (#3065)

    * feat(frontend): change the "Use internal authentication" style to be primary (#3065)

    * feat(frontend): resize the login with "provider" button to use a 120% font size (#3065)

    * feat(frontend): remove unused css for h1 tag (#3065)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit cf508065ec
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 12:51:27 2021 +1300

    fix(frontend): application edit page initializes the overridenKeyType of new added configuration key  to NONE so that the user can select how to load it (#4548) (#4593)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit eab828279e
Author: itsconquest <william.conquest@portainer.io>
Date:   Fri Jan 8 12:46:57 2021 +1300

    chore(project): exclude refactors (#4689)

commit d5763a970b
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 12:45:06 2021 +1300

    fix(frontend): Resource pool 'created' attribute is showing the time you view it at & not actual creation time (#4568) (#4599)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit c9f68a4d8f
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 11:55:42 2021 +1300

    fix(kubernetes): removes kube client cache when edge proxy is removed (#4487) (#4574)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 7848bcf2f4
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 7 22:29:17 2021 +0100

    feat(k8s/resources-list-view): add advanced deployment panel to resources list view (#4516)

    * feat(k8s/resources-list-view): add advanced deployment panel to applications view, configurations view and volumes view

    * feat(k8s/resources-list-view): move advanced deployment into a template and use it everywhere

commit b924347c5b
Author: Stéphane Busso <stephane.busso@gmail.com>
Date:   Thu Jan 7 14:03:46 2021 +1300

    Bump portainer version

commit 9fbda9fb99
Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
Date:   Thu Jan 7 13:38:01 2021 +1300

    Merge in release fixes to develop (#4687)

    * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)

    * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

    * fix(frontend) rephrase comments (#4629)

    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    * + silently continue when downloading artifacts in windows (#4637)

    * fix(docker/stack-details): do not display editor tab for external stack (#4650)

    * Revert "chore(build): bump Kompose version (#4475)" (#4676)

    This reverts commit 380f106571.

    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    Co-authored-by: cong meng <mcpacino@gmail.com>
    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
    Co-authored-by: Anthony Lapenna <anthony.lapenna@portainer.io>

commit 82f8062784
Author: Anthony Lapenna <lapenna.anthony@gmail.com>
Date:   Wed Jan 6 11:31:05 2021 +1300

    chore(github): update issue template

commit 49982eb98a
Author: knittl <knittl89+github@gmail.com>
Date:   Tue Jan 5 20:49:50 2021 +0100

commit 4be3ac470f
Merge: 7975ef79 a50ab51b
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Thu Dec 24 23:45:53 2020 +1300

    Merge pull request #4658 from portainer/revert-4475-chore-ce-86-bump-kompose-version

    Revert "chore(build): bump Kompose version"

commit a50ab51bef
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Thu Dec 24 12:12:28 2020 +1300

    Revert "chore(build): bump Kompose version (#4475)"

    This reverts commit 380f106571.
2021-02-04 18:08:27 +13:00
yi-portainer
535215833d * version change to 2.1.1 2021-02-04 18:04:18 +13:00
yi-portainer
666b09ad3b Squashed commit of the following:
commit c4a1243af9
Author: Dmitry Salakhov <to@dimasalakhov.com>
Date:   Thu Feb 4 03:00:25 2021 +0000

    fix: docker-compose use custom config.json to access private images (#4820)

commit 305d0d2da0
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Wed Feb 3 06:38:56 2021 +0100

    fix(k8s/resource-pool): unusable RP access management (#4810)

    (cherry picked from commit e401724d43)

commit e4605d990d
Author: yi-portainer <yi.chen@portainer.io>
Date:   Tue Feb 2 17:42:57 2021 +1300

    * update portainer version

commit 768697157c
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Tue Feb 2 05:00:19 2021 +0100

    sec(app): remove unused and vulnerable dependencies (#4801)

commit d3086da139
Author: cong meng <mcpacino@gmail.com>
Date:   Tue Feb 2 15:10:06 2021 +1300

    fix(k8s) trigger port validation while changing protocol (ce#394) (#4804)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 95894e8047
Author: cong meng <mcpacino@gmail.com>
Date:   Tue Feb 2 15:03:11 2021 +1300

    fix(k8s) parse empty configuration as empty string yaml instead of {} (ce#395) (#4805)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 81de55fedd
Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
Date:   Tue Feb 2 11:12:40 2021 +1300

    * fix missing kubectl download (#4802)

commit 84827b8782
Author: Steven Kang <skan070@gmail.com>
Date:   Sun Jan 31 17:32:30 2021 +1300

    feat(build): introducing buildx for Windows (#4792)

    * feat(build): introducing buildx for Windows

    * feat(build): re-ordered USER

    * feat(build): Fixed Typo

    * feat(build): fixed typo

commit a71e71f481
Author: Dmitry Salakhov <to@dimasalakhov.com>
Date:   Mon Jan 25 19:16:53 2021 +0000

    feat(compose): add docker-compose wrapper (#4713)

    * feat(compose): add docker-compose wrapper

    ce-187

    * fix(compose): pick compose implementation upon startup

    * Add static compose build for linux

    * Fix wget

    * Fix platofrm specific docker-compose download

    * Keep amd64 architecture as download parameter

    * Add tmp folder for docker-compose

    * fix: line endings

    * add proxy server

    * logs

    * Proxy

    * Add lite transport for compose

    * Fix local deployment

    * refactor: pass proxyManager by ref

    * fix: string conversion

    * refactor: compose wrapper remove unused code

    * fix: tests

    * Add edge

    * Fix merge issue

    * refactor: remove unused code

    * Move server to proxy implementation

    * Cleanup wrapper and manager

    * feat: pass max supported compose syntax version with each endpoint

    * fix: pick compose syntax version

    * fix: store wrapper version in portainer

    * Get and show composeSyntaxMaxVersion at stack creation screen

    * Get and show composeSyntaxMaxVersion at stack editor screen

    * refactor: proxy server

    * Fix used tmp

    * Bump docker-compose to 1.28.0

    * remove message for docker compose limitation

    * fix: markup typo

    * Rollback docker compose to 1.27.4

    * * attempt to fix the windows build issue

    * * attempt to debug grunt issue

    * * use console log in grunt file

    * fix: try to fix windows build by removing indirect deps from go.mod

    * Remove tmp folder

    * Remove builder stage

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose - fixed verbose output

    * refactor: renames

    * fix(stack): get endpoint by EndpointProvider

    * fix(stack): use margin to add space between line instead of using br tag

    Co-authored-by: Stéphane Busso <stephane.busso@gmail.com>
    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: yi-portainer <yi.chen@portainer.io>
    Co-authored-by: Steven Kang <skan070@gmail.com>

commit 83f4c5ec0b
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Mon Jan 25 02:43:54 2021 +0100

    fix(k8s/app): remove advanced deployment panel from app details view (#4730)

commit 41308d570d
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Mon Jan 25 02:14:35 2021 +0100

    feat(configurations): Review UI/UX configurations (#4691)

    * feat(configurations): Review UI/UX configurations

    * feat(configurations): fix binary secret value

    * fix(frontend): populate data between simple and advanced modes (#4503)

    * fix(configuration): parseYaml before create configuration

    * fix(configurations): change c to C in ConfigurationOwner

    * fix(application): change configuration index to configuration key in the view

    * fix(configuration): resolve problem in application create with configuration not overriden.

    * fix(configuration): fix bad import in helper

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 46ff8a01bc
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Fri Jan 22 03:08:08 2021 +0200

    fix(kubernetes/pods): save note (#4675)

    * feat(kubernetes/pods): introduce patch api

    * feat(k8s/pods): pod converter

    * feat(kubernetes/pods): introduce patch api

    * feat(k8s/pod): add annotations only if needed

    * fix(k8s/pod): replace class with factory function

commit 2b257d2785
Author: yi-portainer <yi.chen@portainer.io>
Date:   Thu Jan 21 00:02:22 2021 +1300

    Squashed commit of the following 2.0.1 release fixes:

    commit f90d6b55d6
    Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
    Date:   Wed Jan 13 00:56:19 2021 +0200

        feat(service): clear source volume when change type (#4627)

        * feat(service): clear source volume when change type

        * feat(service): init volume source to the correct value

    commit 1b82b450d7
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Thu Jan 7 14:47:32 2021 +1300

        * bump the APIVersion to 2.0.1 (#4688)

    commit b78d804881
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Wed Dec 30 23:03:43 2020 +1300

        Revert "chore(build): bump Kompose version (#4475)" (#4676)

        This reverts commit 380f106571.

        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    commit 51b72c12f9
    Author: Anthony Lapenna <anthony.lapenna@portainer.io>
    Date:   Wed Dec 23 14:45:32 2020 +1300

        fix(docker/stack-details): do not display editor tab for external stack (#4650)

    commit 58c04bdbe3
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Tue Dec 22 13:47:11 2020 +1300

        + silently continue when downloading artifacts in windows (#4637)

    commit a6320d5222
    Author: cong meng <mcpacino@gmail.com>
    Date:   Tue Dec 22 13:38:54 2020 +1300

        fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)

        * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

        * fix(frontend) rephrase comments (#4629)

        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

        Co-authored-by: Simon Meng <simon.meng@portainer.io>
        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

commit da41dbb79a
Author: cong meng <mcpacino@gmail.com>
Date:   Wed Jan 20 15:19:35 2021 +1300

    fix(stack): stacks created via API are incorrectly marked as private with no owner (#3721) (#4725)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 68d42617f2
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Wed Jan 20 01:02:18 2021 +0100

    feat(placement): Add a warning notification under the placement tab when an application cannot be scheduled on any node in the cluster (#4525)

    * feat(placement): Add a warning notification under the placement tab when an application cannot be scheduled on any node in the cluster

    * fix(applications): if there is at least one node the application can schedule on, then do not show the warning

commit 8323e22309
Author: Anthony McMahon <75223906+Anthony-Portainer@users.noreply.github.com>
Date:   Wed Jan 20 12:06:25 2021 +1300

    Update issue templates

    Adding auto labelling to Bug Report (kind/bug, bug/unconfirmed) and Question (kind/question)

commit 20d4341170
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 19 00:10:08 2021 +0200

    fix(state): check validity of state (#4609)

commit 832cafc933
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Mon Jan 18 02:59:57 2021 +0200

    fix(registries): update password only when not empty (#4669)

commit f3c537ac2c
Author: cong meng <mcpacino@gmail.com>
Date:   Mon Jan 18 13:02:16 2021 +1300

    chore(build): bump Kompose version (#4473) (#4724)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 958baf6283
Author: Anthony McMahon <75223906+Anthony-Portainer@users.noreply.github.com>
Date:   Mon Jan 18 09:30:17 2021 +1300

    Update README.md

commit 08e392378e
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Sun Jan 17 09:28:09 2021 +0200

    chore(app): fail on angular components missing nginject (#4224)

commit a2d9734b8b
Author: Alice Groux <alice.grx@gmail.com>
Date:   Sun Jan 17 04:50:22 2021 +0100

    fix(k8s/datatables): reduce size of collapse/expand column for stacks datatable and storage datatable (#4511)

    * fix(k8s/datatables): reduce size of collapse/expand column for stacks datatable and storage datatable

    * fix(k8s/datatables): reduce size of expand/collapse column

commit 15aed9fc6f
Author: DarkAEther <30438425+DarkAEther@users.noreply.github.com>
Date:   Sun Jan 17 06:23:32 2021 +0530

    feat(area/kubernetes): show shared access policy in volume details (#4707)

commit 121d33538d
Author: Alice Groux <alice.grx@gmail.com>
Date:   Fri Jan 15 02:51:36 2021 +0100

    fix(k8s/application): validate load balancer ports inputs (#4426)

    * fix(k8s/application): validate load balancer ports inputs

    * fix(k8s/application): allow user to only change the protocol on the first port mapping

commit 7a03351df8
Author: Olli Janatuinen <olljanat@users.noreply.github.com>
Date:   Thu Jan 14 23:05:33 2021 +0200

    dep(api): Support Docker Stack 3.8 (#4333)

    - Linux: Update Docker binary to version 19.03.13
    - Windows: Update Docker binary to version 19.03.12

commit 0c2987893d
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 14 03:04:44 2021 +0100

    feat(app/images): in advanced mode, remove tooltip and add an information message (#4528)

commit d1eddaa188
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 14 00:24:56 2021 +0100

    feat(app/network): rename restrict external acces to the network label and add a tooltip (#4514)

commit d336ada3c2
Author: Anthony Lapenna <anthony.lapenna@portainer.io>
Date:   Wed Jan 13 16:13:27 2021 +1300

    feat(k8s/application): review application creation warning style (#4613)

commit 839198fbff
Author: Avadhut Tanugade <30384908+mrwhoknows55@users.noreply.github.com>
Date:   Wed Jan 13 04:49:18 2021 +0530

commit 486ffa5bbd
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 12 23:40:09 2021 +0200

    chore(webpack): add source maps (#4471)

    * chore(webpack): add source maps

    * feat(build): fetch source maps for 3rd party libs

commit 4cd468ce21
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Tue Jan 12 02:35:59 2021 +0100

    Can't create kubernetes resources with a username longer than 63 characters (#4672)

    * fix(kubernetes): truncate username when we create resource

    * fix(k8s): remove forbidden characters in owner label

commit cbd7fdc62e
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 12 01:38:49 2021 +0200

    feat(docker/stacks): introduce date info for stacks (#4660)

    * feat(docker/stacks): add creation and update dates

    * feat(docker/stacks): put ownership column as the last column

    * feat(docker/stacks): fix the no stacks message

    * refactor(docker/stacks): make external stacks helpers more readable

    * feat(docker/stacks): add updated and created by

    * feat(docker/stacks): toggle updated column

    * refactor(datatable): create column visibility component

    Co-authored-by: alice groux <alice.grx@gmail.com>

commit b9fe8009dd
Author: DarkAEther <30438425+DarkAEther@users.noreply.github.com>
Date:   Mon Jan 11 08:05:19 2021 +0530

    feat(image-details): Show labels in images datatable (#4287)

    * feat(images): show labels in images datatable

    * move labels to image details view

commit 6a504e7134
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Mon Jan 11 14:44:15 2021 +1300

    fix(settings): Use default setting if UserSessionTimeout not set (#4521)

    * fix(settings): Use default settings if UserSessionTimeout not set

    * Update UserSessionTimeout settings in database if set to empty string

commit 51ba0876a5
Author: Alice Groux <alice.grx@gmail.com>
Date:   Mon Jan 11 00:51:46 2021 +0100

    feat(k8s/configuration): rename add ingress controller button and changed information text (#4540)

commit 769e6a4c6c
Author: Alice Groux <alice.grx@gmail.com>
Date:   Sun Jan 10 23:30:31 2021 +0100

    feat(k8s/configuration): add extra information panel when creating a sensitive configuration (#4541)

commit 105d1ae519
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 15:30:43 2021 +1300

    feat(frontend): de-emphasize internal login when OAuth is enabled (#3065) (#4565)

    * feat(frontend): de-emphasize internal login when OAuth is enabled (#3065)

    * feat(frontend): change the "Use internal authentication" style to be primary (#3065)

    * feat(frontend): resize the login with "provider" button to use a 120% font size (#3065)

    * feat(frontend): remove unused css for h1 tag (#3065)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit cf508065ec
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 12:51:27 2021 +1300

    fix(frontend): application edit page initializes the overridenKeyType of new added configuration key  to NONE so that the user can select how to load it (#4548) (#4593)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit eab828279e
Author: itsconquest <william.conquest@portainer.io>
Date:   Fri Jan 8 12:46:57 2021 +1300

    chore(project): exclude refactors (#4689)

commit d5763a970b
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 12:45:06 2021 +1300

    fix(frontend): Resource pool 'created' attribute is showing the time you view it at & not actual creation time (#4568) (#4599)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit c9f68a4d8f
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 11:55:42 2021 +1300

    fix(kubernetes): removes kube client cache when edge proxy is removed (#4487) (#4574)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 7848bcf2f4
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 7 22:29:17 2021 +0100

    feat(k8s/resources-list-view): add advanced deployment panel to resources list view (#4516)

    * feat(k8s/resources-list-view): add advanced deployment panel to applications view, configurations view and volumes view

    * feat(k8s/resources-list-view): move advanced deployment into a template and use it everywhere

commit b924347c5b
Author: Stéphane Busso <stephane.busso@gmail.com>
Date:   Thu Jan 7 14:03:46 2021 +1300

    Bump portainer version

commit 9fbda9fb99
Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
Date:   Thu Jan 7 13:38:01 2021 +1300

    Merge in release fixes to develop (#4687)

    * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)

    * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

    * fix(frontend) rephrase comments (#4629)

    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    * + silently continue when downloading artifacts in windows (#4637)

    * fix(docker/stack-details): do not display editor tab for external stack (#4650)

    * Revert "chore(build): bump Kompose version (#4475)" (#4676)

    This reverts commit 380f106571.

    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    Co-authored-by: cong meng <mcpacino@gmail.com>
    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
    Co-authored-by: Anthony Lapenna <anthony.lapenna@portainer.io>

commit 82f8062784
Author: Anthony Lapenna <lapenna.anthony@gmail.com>
Date:   Wed Jan 6 11:31:05 2021 +1300

    chore(github): update issue template

commit 49982eb98a
Author: knittl <knittl89+github@gmail.com>
Date:   Tue Jan 5 20:49:50 2021 +0100

commit 4be3ac470f
Merge: 7975ef79 a50ab51b
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Thu Dec 24 23:45:53 2020 +1300

    Merge pull request #4658 from portainer/revert-4475-chore-ce-86-bump-kompose-version

    Revert "chore(build): bump Kompose version"

commit a50ab51bef
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Thu Dec 24 12:12:28 2020 +1300

    Revert "chore(build): bump Kompose version (#4475)"

    This reverts commit 380f106571.
2021-02-04 17:28:23 +13:00
Dmitry Salakhov
c4a1243af9 fix: docker-compose use custom config.json to access private images (#4820) 2021-02-04 16:00:25 +13:00
LP B
305d0d2da0 fix(k8s/resource-pool): unusable RP access management (#4810)
(cherry picked from commit e401724d43)
2021-02-04 15:58:32 +13:00
yi-portainer
9af9b70f3e Squashed commit of the following:
commit e4605d990d
Author: yi-portainer <yi.chen@portainer.io>
Date:   Tue Feb 2 17:42:57 2021 +1300

    * update portainer version

commit 768697157c
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Tue Feb 2 05:00:19 2021 +0100

    sec(app): remove unused and vulnerable dependencies (#4801)

commit d3086da139
Author: cong meng <mcpacino@gmail.com>
Date:   Tue Feb 2 15:10:06 2021 +1300

    fix(k8s) trigger port validation while changing protocol (ce#394) (#4804)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 95894e8047
Author: cong meng <mcpacino@gmail.com>
Date:   Tue Feb 2 15:03:11 2021 +1300

    fix(k8s) parse empty configuration as empty string yaml instead of {} (ce#395) (#4805)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 81de55fedd
Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
Date:   Tue Feb 2 11:12:40 2021 +1300

    * fix missing kubectl download (#4802)

commit 84827b8782
Author: Steven Kang <skan070@gmail.com>
Date:   Sun Jan 31 17:32:30 2021 +1300

    feat(build): introducing buildx for Windows (#4792)

    * feat(build): introducing buildx for Windows

    * feat(build): re-ordered USER

    * feat(build): Fixed Typo

    * feat(build): fixed typo

commit a71e71f481
Author: Dmitry Salakhov <to@dimasalakhov.com>
Date:   Mon Jan 25 19:16:53 2021 +0000

    feat(compose): add docker-compose wrapper (#4713)

    * feat(compose): add docker-compose wrapper

    ce-187

    * fix(compose): pick compose implementation upon startup

    * Add static compose build for linux

    * Fix wget

    * Fix platofrm specific docker-compose download

    * Keep amd64 architecture as download parameter

    * Add tmp folder for docker-compose

    * fix: line endings

    * add proxy server

    * logs

    * Proxy

    * Add lite transport for compose

    * Fix local deployment

    * refactor: pass proxyManager by ref

    * fix: string conversion

    * refactor: compose wrapper remove unused code

    * fix: tests

    * Add edge

    * Fix merge issue

    * refactor: remove unused code

    * Move server to proxy implementation

    * Cleanup wrapper and manager

    * feat: pass max supported compose syntax version with each endpoint

    * fix: pick compose syntax version

    * fix: store wrapper version in portainer

    * Get and show composeSyntaxMaxVersion at stack creation screen

    * Get and show composeSyntaxMaxVersion at stack editor screen

    * refactor: proxy server

    * Fix used tmp

    * Bump docker-compose to 1.28.0

    * remove message for docker compose limitation

    * fix: markup typo

    * Rollback docker compose to 1.27.4

    * * attempt to fix the windows build issue

    * * attempt to debug grunt issue

    * * use console log in grunt file

    * fix: try to fix windows build by removing indirect deps from go.mod

    * Remove tmp folder

    * Remove builder stage

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose

    * feat(build/windows): add git for Docker Compose - fixed verbose output

    * refactor: renames

    * fix(stack): get endpoint by EndpointProvider

    * fix(stack): use margin to add space between line instead of using br tag

    Co-authored-by: Stéphane Busso <stephane.busso@gmail.com>
    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: yi-portainer <yi.chen@portainer.io>
    Co-authored-by: Steven Kang <skan070@gmail.com>

commit 83f4c5ec0b
Author: LP B <xAt0mZ@users.noreply.github.com>
Date:   Mon Jan 25 02:43:54 2021 +0100

    fix(k8s/app): remove advanced deployment panel from app details view (#4730)

commit 41308d570d
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Mon Jan 25 02:14:35 2021 +0100

    feat(configurations): Review UI/UX configurations (#4691)

    * feat(configurations): Review UI/UX configurations

    * feat(configurations): fix binary secret value

    * fix(frontend): populate data between simple and advanced modes (#4503)

    * fix(configuration): parseYaml before create configuration

    * fix(configurations): change c to C in ConfigurationOwner

    * fix(application): change configuration index to configuration key in the view

    * fix(configuration): resolve problem in application create with configuration not overriden.

    * fix(configuration): fix bad import in helper

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 46ff8a01bc
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Fri Jan 22 03:08:08 2021 +0200

    fix(kubernetes/pods): save note (#4675)

    * feat(kubernetes/pods): introduce patch api

    * feat(k8s/pods): pod converter

    * feat(kubernetes/pods): introduce patch api

    * feat(k8s/pod): add annotations only if needed

    * fix(k8s/pod): replace class with factory function

commit 2b257d2785
Author: yi-portainer <yi.chen@portainer.io>
Date:   Thu Jan 21 00:02:22 2021 +1300

    Squashed commit of the following 2.0.1 release fixes:

    commit f90d6b55d6
    Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
    Date:   Wed Jan 13 00:56:19 2021 +0200

        feat(service): clear source volume when change type (#4627)

        * feat(service): clear source volume when change type

        * feat(service): init volume source to the correct value

    commit 1b82b450d7
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Thu Jan 7 14:47:32 2021 +1300

        * bump the APIVersion to 2.0.1 (#4688)

    commit b78d804881
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Wed Dec 30 23:03:43 2020 +1300

        Revert "chore(build): bump Kompose version (#4475)" (#4676)

        This reverts commit 380f106571.

        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    commit 51b72c12f9
    Author: Anthony Lapenna <anthony.lapenna@portainer.io>
    Date:   Wed Dec 23 14:45:32 2020 +1300

        fix(docker/stack-details): do not display editor tab for external stack (#4650)

    commit 58c04bdbe3
    Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
    Date:   Tue Dec 22 13:47:11 2020 +1300

        + silently continue when downloading artifacts in windows (#4637)

    commit a6320d5222
    Author: cong meng <mcpacino@gmail.com>
    Date:   Tue Dec 22 13:38:54 2020 +1300

        fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)

        * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

        * fix(frontend) rephrase comments (#4629)

        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

        Co-authored-by: Simon Meng <simon.meng@portainer.io>
        Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

commit da41dbb79a
Author: cong meng <mcpacino@gmail.com>
Date:   Wed Jan 20 15:19:35 2021 +1300

    fix(stack): stacks created via API are incorrectly marked as private with no owner (#3721) (#4725)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 68d42617f2
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Wed Jan 20 01:02:18 2021 +0100

    feat(placement): Add a warning notification under the placement tab when an application cannot be scheduled on any node in the cluster (#4525)

    * feat(placement): Add a warning notification under the placement tab when an application cannot be scheduled on any node in the cluster

    * fix(applications): if there is at least one node the application can schedule on, then do not show the warning

commit 8323e22309
Author: Anthony McMahon <75223906+Anthony-Portainer@users.noreply.github.com>
Date:   Wed Jan 20 12:06:25 2021 +1300

    Update issue templates

    Adding auto labelling to Bug Report (kind/bug, bug/unconfirmed) and Question (kind/question)

commit 20d4341170
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 19 00:10:08 2021 +0200

    fix(state): check validity of state (#4609)

commit 832cafc933
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Mon Jan 18 02:59:57 2021 +0200

    fix(registries): update password only when not empty (#4669)

commit f3c537ac2c
Author: cong meng <mcpacino@gmail.com>
Date:   Mon Jan 18 13:02:16 2021 +1300

    chore(build): bump Kompose version (#4473) (#4724)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 958baf6283
Author: Anthony McMahon <75223906+Anthony-Portainer@users.noreply.github.com>
Date:   Mon Jan 18 09:30:17 2021 +1300

    Update README.md

commit 08e392378e
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Sun Jan 17 09:28:09 2021 +0200

    chore(app): fail on angular components missing nginject (#4224)

commit a2d9734b8b
Author: Alice Groux <alice.grx@gmail.com>
Date:   Sun Jan 17 04:50:22 2021 +0100

    fix(k8s/datatables): reduce size of collapse/expand column for stacks datatable and storage datatable (#4511)

    * fix(k8s/datatables): reduce size of collapse/expand column for stacks datatable and storage datatable

    * fix(k8s/datatables): reduce size of expand/collapse column

commit 15aed9fc6f
Author: DarkAEther <30438425+DarkAEther@users.noreply.github.com>
Date:   Sun Jan 17 06:23:32 2021 +0530

    feat(area/kubernetes): show shared access policy in volume details (#4707)

commit 121d33538d
Author: Alice Groux <alice.grx@gmail.com>
Date:   Fri Jan 15 02:51:36 2021 +0100

    fix(k8s/application): validate load balancer ports inputs (#4426)

    * fix(k8s/application): validate load balancer ports inputs

    * fix(k8s/application): allow user to only change the protocol on the first port mapping

commit 7a03351df8
Author: Olli Janatuinen <olljanat@users.noreply.github.com>
Date:   Thu Jan 14 23:05:33 2021 +0200

    dep(api): Support Docker Stack 3.8 (#4333)

    - Linux: Update Docker binary to version 19.03.13
    - Windows: Update Docker binary to version 19.03.12

commit 0c2987893d
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 14 03:04:44 2021 +0100

    feat(app/images): in advanced mode, remove tooltip and add an information message (#4528)

commit d1eddaa188
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 14 00:24:56 2021 +0100

    feat(app/network): rename restrict external acces to the network label and add a tooltip (#4514)

commit d336ada3c2
Author: Anthony Lapenna <anthony.lapenna@portainer.io>
Date:   Wed Jan 13 16:13:27 2021 +1300

    feat(k8s/application): review application creation warning style (#4613)

commit 839198fbff
Author: Avadhut Tanugade <30384908+mrwhoknows55@users.noreply.github.com>
Date:   Wed Jan 13 04:49:18 2021 +0530

commit 486ffa5bbd
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 12 23:40:09 2021 +0200

    chore(webpack): add source maps (#4471)

    * chore(webpack): add source maps

    * feat(build): fetch source maps for 3rd party libs

commit 4cd468ce21
Author: Maxime Bajeux <max.bajeux@gmail.com>
Date:   Tue Jan 12 02:35:59 2021 +0100

    Can't create kubernetes resources with a username longer than 63 characters (#4672)

    * fix(kubernetes): truncate username when we create resource

    * fix(k8s): remove forbidden characters in owner label

commit cbd7fdc62e
Author: Chaim Lev-Ari <chiptus@users.noreply.github.com>
Date:   Tue Jan 12 01:38:49 2021 +0200

    feat(docker/stacks): introduce date info for stacks (#4660)

    * feat(docker/stacks): add creation and update dates

    * feat(docker/stacks): put ownership column as the last column

    * feat(docker/stacks): fix the no stacks message

    * refactor(docker/stacks): make external stacks helpers more readable

    * feat(docker/stacks): add updated and created by

    * feat(docker/stacks): toggle updated column

    * refactor(datatable): create column visibility component

    Co-authored-by: alice groux <alice.grx@gmail.com>

commit b9fe8009dd
Author: DarkAEther <30438425+DarkAEther@users.noreply.github.com>
Date:   Mon Jan 11 08:05:19 2021 +0530

    feat(image-details): Show labels in images datatable (#4287)

    * feat(images): show labels in images datatable

    * move labels to image details view

commit 6a504e7134
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Mon Jan 11 14:44:15 2021 +1300

    fix(settings): Use default setting if UserSessionTimeout not set (#4521)

    * fix(settings): Use default settings if UserSessionTimeout not set

    * Update UserSessionTimeout settings in database if set to empty string

commit 51ba0876a5
Author: Alice Groux <alice.grx@gmail.com>
Date:   Mon Jan 11 00:51:46 2021 +0100

    feat(k8s/configuration): rename add ingress controller button and changed information text (#4540)

commit 769e6a4c6c
Author: Alice Groux <alice.grx@gmail.com>
Date:   Sun Jan 10 23:30:31 2021 +0100

    feat(k8s/configuration): add extra information panel when creating a sensitive configuration (#4541)

commit 105d1ae519
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 15:30:43 2021 +1300

    feat(frontend): de-emphasize internal login when OAuth is enabled (#3065) (#4565)

    * feat(frontend): de-emphasize internal login when OAuth is enabled (#3065)

    * feat(frontend): change the "Use internal authentication" style to be primary (#3065)

    * feat(frontend): resize the login with "provider" button to use a 120% font size (#3065)

    * feat(frontend): remove unused css for h1 tag (#3065)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit cf508065ec
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 12:51:27 2021 +1300

    fix(frontend): application edit page initializes the overridenKeyType of new added configuration key  to NONE so that the user can select how to load it (#4548) (#4593)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit eab828279e
Author: itsconquest <william.conquest@portainer.io>
Date:   Fri Jan 8 12:46:57 2021 +1300

    chore(project): exclude refactors (#4689)

commit d5763a970b
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 12:45:06 2021 +1300

    fix(frontend): Resource pool 'created' attribute is showing the time you view it at & not actual creation time (#4568) (#4599)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit c9f68a4d8f
Author: cong meng <mcpacino@gmail.com>
Date:   Fri Jan 8 11:55:42 2021 +1300

    fix(kubernetes): removes kube client cache when edge proxy is removed (#4487) (#4574)

    Co-authored-by: Simon Meng <simon.meng@portainer.io>

commit 7848bcf2f4
Author: Alice Groux <alice.grx@gmail.com>
Date:   Thu Jan 7 22:29:17 2021 +0100

    feat(k8s/resources-list-view): add advanced deployment panel to resources list view (#4516)

    * feat(k8s/resources-list-view): add advanced deployment panel to applications view, configurations view and volumes view

    * feat(k8s/resources-list-view): move advanced deployment into a template and use it everywhere

commit b924347c5b
Author: Stéphane Busso <stephane.busso@gmail.com>
Date:   Thu Jan 7 14:03:46 2021 +1300

    Bump portainer version

commit 9fbda9fb99
Author: Yi Chen <69284638+yi-portainer@users.noreply.github.com>
Date:   Thu Jan 7 13:38:01 2021 +1300

    Merge in release fixes to develop (#4687)

    * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)

    * fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

    * fix(frontend) rephrase comments (#4629)

    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    * + silently continue when downloading artifacts in windows (#4637)

    * fix(docker/stack-details): do not display editor tab for external stack (#4650)

    * Revert "chore(build): bump Kompose version (#4475)" (#4676)

    This reverts commit 380f106571.

    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

    Co-authored-by: cong meng <mcpacino@gmail.com>
    Co-authored-by: Simon Meng <simon.meng@portainer.io>
    Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
    Co-authored-by: Anthony Lapenna <anthony.lapenna@portainer.io>

commit 82f8062784
Author: Anthony Lapenna <lapenna.anthony@gmail.com>
Date:   Wed Jan 6 11:31:05 2021 +1300

    chore(github): update issue template

commit 49982eb98a
Author: knittl <knittl89+github@gmail.com>
Date:   Tue Jan 5 20:49:50 2021 +0100

commit 4be3ac470f
Merge: 7975ef79 a50ab51b
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Thu Dec 24 23:45:53 2020 +1300

    Merge pull request #4658 from portainer/revert-4475-chore-ce-86-bump-kompose-version

    Revert "chore(build): bump Kompose version"

commit a50ab51bef
Author: Stéphane Busso <sbusso@users.noreply.github.com>
Date:   Thu Dec 24 12:12:28 2020 +1300

    Revert "chore(build): bump Kompose version (#4475)"

    This reverts commit 380f106571.
2021-02-02 17:54:02 +13:00
yi-portainer
e4605d990d * update portainer version 2021-02-02 17:42:57 +13:00
LP B
768697157c sec(app): remove unused and vulnerable dependencies (#4801) 2021-02-02 17:02:06 +13:00
cong meng
d3086da139 fix(k8s) trigger port validation while changing protocol (ce#394) (#4804)
Co-authored-by: Simon Meng <simon.meng@portainer.io>
2021-02-02 15:10:06 +13:00
cong meng
95894e8047 fix(k8s) parse empty configuration as empty string yaml instead of {} (ce#395) (#4805)
Co-authored-by: Simon Meng <simon.meng@portainer.io>
2021-02-02 15:03:11 +13:00
Yi Chen
81de55fedd * fix missing kubectl download (#4802) 2021-02-02 11:12:40 +13:00
Steven Kang
84827b8782 feat(build): introducing buildx for Windows (#4792)
* feat(build): introducing buildx for Windows

* feat(build): re-ordered USER

* feat(build): Fixed Typo

* feat(build): fixed typo
2021-01-31 17:32:30 +13:00
yi-portainer
fa38af5d81 Merge remote-tracking branch 'origin/release/2.0.1' 2021-01-07 14:56:52 +13:00
Yi Chen
1b82b450d7 * bump the APIVersion to 2.0.1 (#4688) 2021-01-07 14:47:32 +13:00
Yi Chen
b78d804881 Revert "chore(build): bump Kompose version (#4475)" (#4676)
This reverts commit 380f106571.

Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
2020-12-30 23:03:43 +13:00
Anthony Lapenna
51b72c12f9 fix(docker/stack-details): do not display editor tab for external stack (#4650) 2020-12-23 14:45:32 +13:00
Yi Chen
58c04bdbe3 + silently continue when downloading artifacts in windows (#4637) 2020-12-22 13:47:11 +13:00
cong meng
a6320d5222 fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180) (#4618)
* fix(frontend) unable to retrieve config map error when trying to manage newly created resource pool (ce#180)

* fix(frontend) rephrase comments (#4629)

Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>

Co-authored-by: Simon Meng <simon.meng@portainer.io>
Co-authored-by: Stéphane Busso <sbusso@users.noreply.github.com>
2020-12-22 13:38:54 +13:00
Anthony Lapenna
cb4b4a43e6 update pull dog configuration 2020-08-31 18:09:19 +12:00
Anthony Lapenna
1e5a1d5bdd Merge branch 'develop' 2020-08-31 18:06:50 +12:00
Anthony Lapenna
5ed0d21c39 Merge branch 'ee-pulldog' 2020-08-28 15:26:30 +12:00
Anthony Lapenna
2972dbeafb feat(build/pulldog): review pulldog configuration 2020-08-18 12:36:01 +12:00
46 changed files with 185 additions and 759 deletions

View File

@@ -4,7 +4,6 @@ about: Create a bug report
title: ''
labels: bug/need-confirmation, kind/bug
assignees: ''
---
<!--

View File

@@ -4,8 +4,8 @@ about: Ask us a question about Portainer usage or deployment
title: ''
labels: ''
assignees: ''
---
Before you start, we need a little bit more information from you:
Use Case (delete as appropriate): Using Portainer at Home, Using Portainer in a Commerical setup.

View File

@@ -76,7 +76,7 @@ func initDataStore(dataStorePath string, fileService portainer.FileService) port
}
func initComposeStackManager(assetsPath string, dataStorePath string, reverseTunnelService portainer.ReverseTunnelService, proxyManager *proxy.Manager) portainer.ComposeStackManager {
composeWrapper := exec.NewComposeWrapper(assetsPath, proxyManager)
composeWrapper := exec.NewComposeWrapper(assetsPath, dataStorePath, proxyManager)
if composeWrapper != nil {
return composeWrapper
}

View File

@@ -16,17 +16,19 @@ import (
// ComposeWrapper is a wrapper for docker-compose binary
type ComposeWrapper struct {
binaryPath string
dataPath string
proxyManager *proxy.Manager
}
// NewComposeWrapper returns a docker-compose wrapper if corresponding binary present, otherwise nil
func NewComposeWrapper(binaryPath string, proxyManager *proxy.Manager) *ComposeWrapper {
func NewComposeWrapper(binaryPath, dataPath string, proxyManager *proxy.Manager) *ComposeWrapper {
if !IsBinaryPresent(programPath(binaryPath, "docker-compose")) {
return nil
}
return &ComposeWrapper{
binaryPath: binaryPath,
dataPath: dataPath,
proxyManager: proxyManager,
}
}
@@ -84,6 +86,8 @@ func (w *ComposeWrapper) command(command []string, stack *portainer.Stack, endpo
var stderr bytes.Buffer
cmd := exec.Command(program, args...)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, fmt.Sprintf("DOCKER_CONFIG=%s", w.dataPath))
cmd.Stderr = &stderr
out, err := cmd.Output()

View File

@@ -42,7 +42,7 @@ func Test_UpAndDown(t *testing.T) {
stack, endpoint := setup(t)
w := NewComposeWrapper("", nil)
w := NewComposeWrapper("", "", nil)
err := w.Up(stack, endpoint)
if err != nil {

View File

@@ -77,5 +77,5 @@ func (handler *Handler) proxyRequestsToKubernetesAPI(w http.ResponseWriter, r *h
}
func isKubernetesRequest(requestURL string) bool {
return strings.HasPrefix(requestURL, "/api")
return strings.HasPrefix(requestURL, "/api") || strings.HasPrefix(requestURL, "/healthz")
}

View File

@@ -23,6 +23,36 @@ func (transport *Transport) proxyContainerGroupRequest(request *http.Request) (*
}
func (transport *Transport) proxyContainerGroupPutRequest(request *http.Request) (*http.Response, error) {
//add a lock before processing existense check
transport.mutex.Lock()
defer transport.mutex.Unlock()
//generate a temp http GET request based on the current PUT request
validationRequest := &http.Request{
Method: http.MethodGet,
URL: request.URL,
Header: http.Header{
"Authorization": []string{request.Header.Get("Authorization")},
},
}
//fire the request to Azure API to validate if there is an existing container instance with the same name
//positive - reject the request
//negative - continue the process
validationResponse, err := http.DefaultTransport.RoundTrip(validationRequest)
if err != nil {
return validationResponse, err
}
if validationResponse.StatusCode >= 200 && validationResponse.StatusCode < 300 {
resp := &http.Response{}
errObj := map[string]string{
"message": "A container instance with the same name already exists inside the selected resource group",
}
err = responseutils.RewriteResponse(resp, errObj, http.StatusConflict)
return resp, err
}
response, err := http.DefaultTransport.RoundTrip(request)
if err != nil {
return response, err

View File

@@ -336,7 +336,7 @@ type (
// Whether non-administrator should be able to use container capabilities
AllowContainerCapabilitiesForRegularUsers bool `json:"allowContainerCapabilitiesForRegularUsers" example:"true"`
// Whether non-administrator should be able to use sysctl settings
AllowSysctlSettingForRegularUsers bool `json:"AllowSysctlSettingForRegularUsers" example:"true"`
AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers" example:"true"`
// Whether host management features are enabled
EnableHostManagementFeatures bool `json:"enableHostManagementFeatures" example:"true"`
}
@@ -1327,7 +1327,7 @@ type (
const (
// APIVersion is the version number of the Portainer API
APIVersion = "2.4.0"
APIVersion = "2.5.0"
// DBVersion is the version number of the Portainer database
DBVersion = 27
// ComposeSyntaxMaxVersion is a maximum supported version of the docker compose syntax

View File

@@ -23,6 +23,7 @@ export default class porImageRegistryContainerController {
} catch (e) {
// eslint-disable-next-line no-console
console.error('Failed loading DockerHub pull rate limits', e);
this.setValidity(true);
}
} else {
this.setValidity(true);

View File

@@ -1,6 +1,6 @@
<!-- use registry -->
<div ng-if="$ctrl.model.UseRegistry">
<div class="form-group">
<div>
<div class="form-group" ng-if="$ctrl.model.UseRegistry">
<label for="image_registry" class="control-label text-left" ng-class="$ctrl.labelClass">
Registry
</label>

View File

@@ -972,9 +972,7 @@ angular.module('portainer.docker').controller('CreateContainerController', [
}
async function shouldShowSysctls() {
const { allowSysctlSettingForRegularUsers } = $scope.applicationState.application;
return allowSysctlSettingForRegularUsers || Authentication.isAdmin();
return endpoint.SecuritySettings.allowSysctlSettingForRegularUsers || Authentication.isAdmin();
}
async function checkIfContainerCapabilitiesEnabled() {

View File

@@ -499,7 +499,7 @@ angular.module('portainer.docker').controller('CreateServiceController', [
const resourceControl = data.Portainer.ResourceControl;
const userId = Authentication.getUserDetails().ID;
const rcPromise = ResourceControlService.applyResourceControl(userId, accessControlData, resourceControl);
const webhookPromise = $q.when(endpoint.Type !== 4 && $scope.formValues.Webhook && WebhookService.createServiceWebhook(serviceId, endpoint.ID));
const webhookPromise = $q.when(endpoint.Type !== 4 && $scope.formValues.Webhook && WebhookService.createServiceWebhook(serviceId, endpoint.Id));
return $q.all([rcPromise, webhookPromise]);
})
.then(function success() {

View File

@@ -5,7 +5,9 @@ export class EditEdgeStackFormController {
}
editorUpdate(cm) {
this.model.StackFileContent = cm.getValue();
this.isEditorDirty = true;
if (this.model.StackFileContent.replace(/(\r\n|\n|\r)/gm, '') !== cm.getValue().replace(/(\r\n|\n|\r)/gm, '')) {
this.model.StackFileContent = cm.getValue();
this.isEditorDirty = true;
}
}
}

View File

@@ -100,16 +100,6 @@ angular.module('portainer.kubernetes', ['portainer.app']).config([
},
};
const applicationStats = {
name: 'kubernetes.applications.application.stats',
url: '/:pod/:container/stats',
views: {
'content@': {
component: 'kubernetesApplicationStatsView',
},
},
};
const stacks = {
name: 'kubernetes.stacks',
url: '/stacks',
@@ -269,7 +259,6 @@ angular.module('portainer.kubernetes', ['portainer.app']).config([
$stateRegistryProvider.register(applicationEdit);
$stateRegistryProvider.register(applicationConsole);
$stateRegistryProvider.register(applicationLogs);
$stateRegistryProvider.register(applicationStats);
$stateRegistryProvider.register(stacks);
$stateRegistryProvider.register(stack);
$stateRegistryProvider.register(stackLogs);

View File

@@ -131,13 +131,6 @@
</td>
<td>{{ item.CreationDate | getisodate }}</td>
<td>
<a
ng-if="item.Status === 'Running' && $ctrl.useServerMetrics"
ui-sref="kubernetes.applications.application.stats({ pod: item.PodName, container: item.Name })"
style="margin-right: 10px;"
>
<i class="fa fa-chart-area" aria-hidden="true"></i> Stats
</a>
<a ui-sref="kubernetes.applications.application.logs({ pod: item.PodName, container: item.Name })"> <i class="fa fa-file-alt" aria-hidden="true"></i> Logs </a>
<a ng-if="item.Status === 'Running'" ui-sref="kubernetes.applications.application.console({ pod: item.PodName, container: item.Name })" style="margin-left: 10px;">
<i class="fa fa-terminal" aria-hidden="true"></i> Console

View File

@@ -9,6 +9,5 @@ angular.module('portainer.kubernetes').component('kubernetesContainersDatatable'
orderBy: '@',
refreshCallback: '<',
isPod: '<',
useServerMetrics: '<',
},
});

View File

@@ -43,8 +43,10 @@ class KubernetesConfigurationDataController {
}
async editorUpdateAsync(cm) {
this.formValues.DataYaml = cm.getValue();
this.isEditorDirty = true;
if (this.formValues.DataYaml !== cm.getValue()) {
this.formValues.DataYaml = cm.getValue();
this.isEditorDirty = true;
}
}
editorUpdate(cm) {

View File

@@ -3,7 +3,8 @@
<div style="margin: 15px;">
<span class="btn btn-primary btn-sm" ng-click="$ctrl.copyYAML()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy to clipboard</span>
<span class="btn btn-primary btn-sm space-left" ng-click="$ctrl.toggleYAMLInspectorExpansion()">
<i class="fa fa-{{ $ctrl.expanded ? 'minus' : 'plus' }} space-right" aria-hidden="true"></i>{{ $ctrl.expanded ? 'Collapse' : 'Expand' }}</span>
<i class="fa fa-{{ $ctrl.expanded ? 'minus' : 'plus' }} space-right" aria-hidden="true"></i>{{ $ctrl.expanded ? 'Collapse' : 'Expand' }}</span
>
<span id="copyNotificationYAML" style="margin-left: 7px; display: none; color: #23ae89;" class="small"> <i class="fa fa-check" aria-hidden="true"></i> copied </span>
</div>
</div>

View File

@@ -132,14 +132,4 @@ angular
};
return values[text] || text;
};
})
.filter('kubernetesApplicationIngressEmptyHostname', function () {
'use strict';
return function (value) {
if (value === '') {
return '<use IP>';
} else {
return value;
}
};
});

View File

@@ -16,7 +16,7 @@ class KubernetesFormValidationHelper {
const groupped = _.groupBy(names);
const res = {};
_.forEach(names, (name, index) => {
if (name && groupped[name].length > 1) {
if (groupped[name].length > 1 && name) {
res[index] = name;
}
});

View File

@@ -29,8 +29,6 @@ class KubernetesResourceReservationHelper {
let res = parseInt(cpu, 10);
if (_.endsWith(cpu, 'm')) {
res /= 1000;
} else if (_.endsWith(cpu, 'n')) {
res /= 1000000000;
}
return res;
}

View File

@@ -2,18 +2,22 @@ import _ from 'lodash-es';
import * as JsonPatch from 'fast-json-patch';
import KubernetesCommonHelper from 'Kubernetes/helpers/commonHelper';
import {
KubernetesResourcePoolIngressClassAnnotationFormValue,
KubernetesResourcePoolIngressClassFormValue,
KubernetesResourcePoolIngressClassHostFormValue,
} from 'Kubernetes/models/resource-pool/formValues';
import { KubernetesResourcePoolIngressClassAnnotationFormValue, KubernetesResourcePoolIngressClassFormValue } from 'Kubernetes/models/resource-pool/formValues';
import { KubernetesIngress, KubernetesIngressRule } from './models';
import { KubernetesIngressCreatePayload, KubernetesIngressRuleCreatePayload, KubernetesIngressRulePathCreatePayload } from './payloads';
import { KubernetesIngressClassAnnotation, KubernetesIngressClassRewriteTargetAnnotations } from './constants';
export class KubernetesIngressConverter {
// TODO: refactor @LP
// currently only allows the first non-empty host to be used as the "configured" host.
// As we currently only allow a single host to be used for a Portianer-managed ingress
// it's working as the only non-empty host will be the one defined by the admin
// but it will take a random existing host for non Portainer ingresses (CLI deployed)
// Also won't support multiple hosts if we make it available in the future
static apiToModel(data) {
let host = undefined;
const paths = _.flatMap(data.spec.rules, (rule) => {
host = host || rule.host; // TODO: refactor @LP - read above
return !rule.http
? []
: _.map(rule.http.paths, (path) => {
@@ -37,11 +41,7 @@ export class KubernetesIngressConverter {
? data.metadata.annotations[KubernetesIngressClassAnnotation]
: data.spec.ingressClassName;
res.Paths = paths;
res.Hosts = _.uniq(_.map(data.spec.rules, 'host'));
const idx = _.findIndex(res.Hosts, (h) => h === undefined);
if (idx >= 0) {
res.Hosts.splice(idx, 1, '');
}
res.Host = host;
return res;
}
@@ -79,7 +79,7 @@ export class KubernetesIngressConverter {
_.extend(res.Annotations, KubernetesIngressClassRewriteTargetAnnotations[formValues.IngressClass.Type]);
}
res.Annotations[KubernetesIngressClassAnnotation] = formValues.IngressClass.Name;
res.Hosts = formValues.Hosts;
res.Host = formValues.Host;
res.Paths = formValues.Paths;
return res;
}
@@ -96,13 +96,7 @@ export class KubernetesIngressConverter {
if (ingress) {
fv.Selected = true;
fv.WasSelected = true;
fv.Hosts = _.map(ingress.Hosts, (host) => {
const hfv = new KubernetesResourcePoolIngressClassHostFormValue();
hfv.Host = host;
hfv.PreviousHost = host;
hfv.IsNew = false;
return hfv;
});
fv.Host = ingress.Host;
const [[rewriteKey]] = _.toPairs(KubernetesIngressClassRewriteTargetAnnotations[ic.Type]);
const annotations = _.map(_.toPairs(ingress.Annotations), ([key, value]) => {
if (key === rewriteKey) {
@@ -134,17 +128,16 @@ export class KubernetesIngressConverter {
p.Host = '';
}
});
const hostsWithRules = [];
const groups = _.groupBy(data.Paths, 'Host');
let rules = _.map(groups, (paths, host) => {
const updatedHost = _.find(data.Hosts, (h) => {
return h === host || h.PreviousHost === host;
});
host = updatedHost.Host || updatedHost;
if (updatedHost.NeedsDeletion) {
return;
}
const rules = _.map(groups, (paths, host) => {
const rule = new KubernetesIngressRuleCreatePayload();
if (host === 'undefined' || _.isEmpty(host)) {
host = data.Host;
}
if (host === data.PreviousHost && host !== data.Host) {
host = data.Host;
}
KubernetesCommonHelper.assignOrDeleteIfEmpty(rule, 'host', host);
rule.http.paths = _.map(paths, (p) => {
const path = new KubernetesIngressRulePathCreatePayload();
@@ -153,27 +146,11 @@ export class KubernetesIngressConverter {
path.backend.servicePort = p.Port;
return path;
});
hostsWithRules.push(host);
return rule;
});
rules = _.without(rules, undefined);
const keptHosts = _.without(
_.map(data.Hosts, (h) => (h.NeedsDeletion ? undefined : h.Host || h)),
undefined
);
const hostsWithoutRules = _.without(keptHosts, ...hostsWithRules);
const emptyRules = _.map(hostsWithoutRules, (host) => {
return { host: host };
});
rules = _.concat(rules, emptyRules);
KubernetesCommonHelper.assignOrDeleteIfEmpty(res, 'spec.rules', rules);
} else if (data.Hosts) {
res.spec.rules = [];
_.forEach(data.Hosts, (host) => {
if (!host.NeedsDeletion) {
res.spec.rules.push({ host: host.Host });
}
});
} else if (data.Host) {
res.spec.rules = [{ host: data.Host }];
} else {
delete res.spec.rules;
}

View File

@@ -3,9 +3,8 @@ export function KubernetesIngress() {
Name: '',
Namespace: '',
Annotations: {},
// Host: undefined,
Hosts: [],
// PreviousHost: undefined, // only use for RP ingress host edit
Host: undefined,
PreviousHost: undefined, // only use for RP ingress host edit
Paths: [],
IngressClassName: '',
};

View File

@@ -77,12 +77,11 @@ export function KubernetesIngressService($async, KubernetesIngresses) {
});
}
function _delete(ingress) {
function _delete(namespace, ingressClassName) {
return $async(async () => {
try {
const params = new KubernetesCommonParams();
params.id = ingress.Name;
const namespace = ingress.Namespace;
params.id = ingressClassName;
await KubernetesIngresses(namespace).delete(params).$promise;
} catch (err) {
throw new PortainerError('Unable to delete ingress', err);

View File

@@ -1,53 +0,0 @@
import angular from 'angular';
import PortainerError from 'Portainer/error';
import { KubernetesCommonParams } from 'Kubernetes/models/common/params';
class KubernetesMetricsService {
/* @ngInject */
constructor($async, KubernetesMetrics) {
this.$async = $async;
this.KubernetesMetrics = KubernetesMetrics;
this.capabilitiesAsync = this.capabilitiesAsync.bind(this);
this.getPodAsync = this.getPodAsync.bind(this);
}
/**
* GET
*/
async capabilitiesAsync(endpointID) {
try {
await this.KubernetesMetrics().capabilities({ endpointId: endpointID }).$promise;
} catch (err) {
throw new PortainerError('Unable to retrieve metrics', err);
}
}
capabilities(endpointID) {
return this.$async(this.capabilitiesAsync, endpointID);
}
/**
* Stats
*
* @param {string} namespace
* @param {string} podName
*/
async getPodAsync(namespace, podName) {
try {
const params = new KubernetesCommonParams();
params.id = podName;
const data = await this.KubernetesMetrics(namespace).getPod(params).$promise;
return data;
} catch (err) {
throw new PortainerError('Unable to retrieve pod stats', err);
}
}
getPod(namespace, podName) {
return this.$async(this.getPodAsync, namespace, podName);
}
}
export default KubernetesMetricsService;
angular.module('portainer.kubernetes').service('KubernetesMetricsService', KubernetesMetricsService);

View File

@@ -1,27 +0,0 @@
angular.module('portainer.kubernetes').factory('KubernetesMetrics', [
'$resource',
'API_ENDPOINT_ENDPOINTS',
'EndpointProvider',
function KubernetesMetrics($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) {
'use strict';
return function (namespace) {
const url = API_ENDPOINT_ENDPOINTS + '/:endpointId/kubernetes/apis/metrics.k8s.io/v1beta1';
const podUrl = `${url}${namespace ? '/namespaces/:namespace' : ''}/pods/:id`;
return $resource(
url,
{
endpointId: EndpointProvider.endpointID,
namespace: namespace,
},
{
capabilities: { method: 'GET' },
getPod: {
method: 'GET',
url: podUrl,
},
}
);
};
},
]);

View File

@@ -17,7 +17,7 @@ export function KubernetesResourcePoolIngressClassFormValue(ingressClass) {
IngressClass: ingressClass,
RewriteTarget: false,
Annotations: [], // KubernetesResourcePoolIngressClassAnnotationFormValue
Hosts: [],
Host: undefined,
Selected: false,
WasSelected: false,
AdvancedConfig: false,
@@ -31,12 +31,3 @@ export function KubernetesResourcePoolIngressClassAnnotationFormValue() {
Value: '',
};
}
export function KubernetesResourcePoolIngressClassHostFormValue() {
return {
Host: '',
PreviousHost: '',
NeedsDeletion: false,
IsNew: true,
};
}

View File

@@ -93,7 +93,7 @@ export function KubernetesResourcePoolService($async, KubernetesNamespaceService
const patch = _.without(newIngresses, ...create);
const createPromises = _.map(create, (i) => KubernetesIngressService.create(i));
const delPromises = _.map(del, (i) => KubernetesIngressService.delete(i));
const delPromises = _.map(del, (i) => KubernetesIngressService.delete(i.Namespace, i.Name));
const patchPromises = _.map(patch, (ing) => {
const old = _.find(oldIngresses, { Name: ing.Name });
ing.Paths = angular.copy(old.Paths);

View File

@@ -1264,14 +1264,7 @@
tooltip-enable="ctrl.disableLoadBalancerEdit()"
uib-tooltip="Edition is not allowed while the Load Balancer is in 'Pending' state"
>
<div
class="input-group input-group-sm"
ng-class="{
striked: publishedPort.NeedsDeletion,
'col-sm-2': ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS,
'col-sm-3': ctrl.formValues.PublishingType !== ctrl.ApplicationPublishingTypes.INGRESS
}"
>
<div class="col-sm-3 input-group input-group-sm" ng-class="{ striked: publishedPort.NeedsDeletion }">
<span class="input-group-addon">container port</span>
<input
type="number"
@@ -1334,7 +1327,7 @@
</div>
<div
class="col-sm-2 input-group input-group-sm"
class="col-sm-3 input-group input-group-sm"
ng-class="{ striked: publishedPort.NeedsDeletion }"
ng-if="
(publishedPort.IsNew && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS) ||
@@ -1356,28 +1349,7 @@
</div>
<div
class="col-sm-2 input-group input-group-sm"
ng-class="{ striked: publishedPort.NeedsDeletion }"
ng-if="
(publishedPort.IsNew && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS) ||
(!publishedPort.IsNew && ctrl.savedFormValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS)
"
>
<span class="input-group-addon">hostname</span>
<select
class="form-control"
name="ingress_hostname_{{ $index }}"
ng-model="publishedPort.IngressHost"
ng-options="host as (host | kubernetesApplicationIngressEmptyHostname) for host in ctrl.ingressHostnames"
ng-change="ctrl.onChangePublishedPorts()"
ng-disabled="ctrl.disableLoadBalancerEdit() || ctrl.isEditAndNotNewPublishedPort($index)"
>
<option selected disabled hidden value="">Select a hostname</option>
</select>
</div>
<div
class="col-sm-2 input-group input-group-sm"
class="col-sm-3 input-group input-group-sm"
ng-class="{ striked: publishedPort.NeedsDeletion }"
ng-if="
(publishedPort.IsNew && ctrl.formValues.PublishingType === ctrl.ApplicationPublishingTypes.INGRESS) ||

View File

@@ -320,7 +320,7 @@ class KubernetesCreateApplicationController {
const p = new KubernetesApplicationPublishedPortFormValue();
const ingresses = this.filteredIngresses;
p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined;
p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined;
p.IngressHost = ingresses && ingresses.length ? ingresses[0].Host : undefined;
if (this.formValues.PublishedPorts.length) {
p.Protocol = this.formValues.PublishedPorts[0].Protocol;
}
@@ -331,7 +331,7 @@ class KubernetesCreateApplicationController {
const ingresses = this.filteredIngresses;
_.forEach(this.formValues.PublishedPorts, (p) => {
p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined;
p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined;
p.IngressHost = ingresses && ingresses.length ? ingresses[0].Host : undefined;
});
}
@@ -388,8 +388,7 @@ class KubernetesCreateApplicationController {
onChangePortMappingIngress(index) {
const publishedPort = this.formValues.PublishedPorts[index];
const ingress = _.find(this.filteredIngresses, { Name: publishedPort.IngressName });
this.ingressHostnames = ingress.Hosts;
publishedPort.IngressHost = this.ingressHostnames.length ? this.ingressHostnames[0] : [];
publishedPort.IngressHost = ingress.Host;
this.onChangePublishedPorts();
}
@@ -781,7 +780,6 @@ class KubernetesCreateApplicationController {
refreshIngresses(namespace) {
this.filteredIngresses = _.filter(this.ingresses, { Namespace: namespace });
this.ingressHostnames = this.filteredIngresses.length ? this.filteredIngresses[0].Hosts : [];
if (!this.publishViaIngressEnabled()) {
if (this.savedFormValues) {
this.formValues.PublishingType = this.savedFormValues.PublishingType;

View File

@@ -587,7 +587,6 @@
table-key="kubernetes.application.containers"
is-pod="ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD"
order-by="{{ ctrl.application.ApplicationType === ctrl.KubernetesApplicationTypes.POD ? 'Name' : 'PodName' }}"
use-server-metrics="ctrl.state.useServerMetrics"
>
</kubernetes-containers-datatable>
</div>

View File

@@ -106,8 +106,7 @@ class KubernetesApplicationController {
KubernetesStackService,
KubernetesPodService,
KubernetesNodeService,
KubernetesNamespaceHelper,
EndpointProvider
KubernetesNamespaceHelper
) {
this.$async = $async;
this.$state = $state;
@@ -126,8 +125,6 @@ class KubernetesApplicationController {
this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes;
this.KubernetesApplicationTypes = KubernetesApplicationTypes;
this.EndpointProvider = EndpointProvider;
this.ApplicationDataAccessPolicies = KubernetesApplicationDataAccessPolicies;
this.KubernetesServiceTypes = KubernetesServiceTypes;
this.KubernetesPodContainerTypes = KubernetesPodContainerTypes;
@@ -338,7 +335,6 @@ class KubernetesApplicationController {
placementWarning: false,
expandedNote: false,
useIngress: false,
useServerMetrics: this.EndpointProvider.currentEndpoint().Kubernetes.Configuration.UseServerMetrics,
};
this.state.activeTab = this.LocalStorage.getActiveTab('application');

View File

@@ -1,82 +0,0 @@
<kubernetes-view-header title="Application stats" state="kubernetes.applications.application.stats" view-ready="ctrl.state.viewReady">
<a ui-sref="kubernetes.resourcePools">Resource pools</a> &gt;
<a ui-sref="kubernetes.resourcePools.resourcePool({ id: ctrl.state.transition.namespace })">{{ ctrl.state.transition.namespace }}</a> &gt;
<a ui-sref="kubernetes.applications">Applications</a> &gt;
<a ui-sref="kubernetes.applications.application({ name: ctrl.state.transition.applicationName, namespace: ctrl.state.transition.namespace })">{{
ctrl.state.transition.applicationName
}}</a>
&gt; Pods &gt; {{ ctrl.state.transition.podName }} &gt; Containers &gt; {{ ctrl.state.transition.containerName }} &gt; Stats
</kubernetes-view-header>
<kubernetes-view-loading view-ready="ctrl.state.viewReady"></kubernetes-view-loading>
<div ng-if="ctrl.state.viewReady">
<information-panel ng-if="!ctrl.state.getMetrics" title-text="Unable to retrieve container metrics">
<span class="small text-muted">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
Portainer was unable to retrieve any metrics associated to that container. Please contact your administrator to ensure that the Kubernetes metrics feature is properly
configured.
</span>
</information-panel>
<div class="row" ng-if="ctrl.state.getMetrics">
<div class="col-md-12">
<rd-widget>
<rd-widget-header icon="fa-info-circle" title-text="About statistics"> </rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">
This view displays real-time statistics about the container <b>{{ ctrl.state.transition.containerName | trimcontainername }}</b
>.
</span>
</div>
</div>
<div class="form-group">
<label for="refreshRate" class="col-sm-3 col-md-2 col-lg-2 margin-sm-top control-label text-left">
Refresh rate
</label>
<div class="col-sm-3 col-md-2">
<select id="refreshRate" ng-model="ctrl.state.refreshRate" ng-change="ctrl.changeUpdateRepeater()" class="form-control">
<option value="30">30s</option>
<option value="60">60s</option>
</select>
</div>
<span>
<i id="refreshRateChange" class="fa fa-check green-icon" aria-hidden="true" style="margin-top: 7px; display: none;"></i>
</span>
</div>
<div class="form-group" ng-if="ctrl.state.networkStatsUnavailable">
<div class="col-sm-12">
<span class="small text-muted"> <i class="fa fa-exclamation-triangle orange-icon" aria-hidden="true"></i> Network stats are unavailable for this container. </span>
</div>
</div>
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row" ng-if="ctrl.state.getMetrics">
<div class="col-lg-6 col-md-12 col-sm-12">
<rd-widget>
<rd-widget-header icon="fa-chart-area" title-text="Memory usage"></rd-widget-header>
<rd-widget-body>
<div class="chart-container" style="position: relative;">
<canvas id="memoryChart" width="770" height="300"></canvas>
</div>
</rd-widget-body>
</rd-widget>
</div>
<div class="col-lg-6 col-md-12 col-sm-12" ng-if="!ctrl.state.networkStatsUnavailable">
<rd-widget>
<rd-widget-header icon="fa-chart-area" title-text="CPU usage"></rd-widget-header>
<rd-widget-body>
<div class="chart-container" style="position: relative;">
<canvas id="cpuChart" width="770" height="300"></canvas>
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>

View File

@@ -1,8 +0,0 @@
angular.module('portainer.kubernetes').component('kubernetesApplicationStatsView', {
templateUrl: './stats.html',
controller: 'KubernetesApplicationStatsController',
controllerAs: 'ctrl',
bindings: {
$transition$: '<',
},
});

View File

@@ -1,164 +0,0 @@
import angular from 'angular';
import moment from 'moment';
import _ from 'lodash-es';
import filesizeParser from 'filesize-parser';
import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceReservationHelper';
import KubernetesPodConverter from 'Kubernetes/pod/converter';
class KubernetesApplicationStatsController {
/* @ngInject */
constructor($async, $state, $interval, $document, Notifications, KubernetesPodService, KubernetesNodeService, KubernetesMetricsService, ChartService) {
this.$async = $async;
this.$state = $state;
this.$interval = $interval;
this.$document = $document;
this.Notifications = Notifications;
this.KubernetesPodService = KubernetesPodService;
this.KubernetesNodeService = KubernetesNodeService;
this.KubernetesMetricsService = KubernetesMetricsService;
this.ChartService = ChartService;
this.onInit = this.onInit.bind(this);
}
changeUpdateRepeater() {
var cpuChart = this.cpuChart;
var memoryChart = this.memoryChart;
this.stopRepeater();
this.setUpdateRepeater(cpuChart, memoryChart);
$('#refreshRateChange').show();
$('#refreshRateChange').fadeOut(1500);
}
updateCPUChart() {
const label = moment(this.stats.read).format('HH:mm:ss');
this.ChartService.UpdateCPUChart(label, this.stats.CPUUsage, this.cpuChart);
}
updateMemoryChart() {
const label = moment(this.stats.read).format('HH:mm:ss');
this.ChartService.UpdateMemoryChart(label, this.stats.MemoryUsage, this.stats.MemoryCache, this.memoryChart);
}
stopRepeater() {
var repeater = this.repeater;
if (angular.isDefined(repeater)) {
this.$interval.cancel(repeater);
repeater = undefined;
}
}
setUpdateRepeater() {
const refreshRate = this.state.refreshRate;
this.repeater = this.$interval(async () => {
try {
await this.getStats();
this.updateCPUChart();
this.updateMemoryChart();
} catch (error) {
this.stopRepeater();
this.Notifications.error('Failure', error);
}
}, refreshRate * 1000);
}
initCharts() {
const cpuChartCtx = $('#cpuChart');
const cpuChart = this.ChartService.CreateCPUChart(cpuChartCtx);
this.cpuChart = cpuChart;
const memoryChartCtx = $('#memoryChart');
const memoryChart = this.ChartService.CreateMemoryChart(memoryChartCtx);
this.memoryChart = memoryChart;
this.updateCPUChart();
this.updateMemoryChart();
this.setUpdateRepeater();
}
getStats() {
return this.$async(async () => {
try {
const stats = await this.KubernetesMetricsService.getPod(this.state.transition.namespace, this.state.transition.podName);
const container = _.find(stats.containers, { name: this.state.transition.containerName });
if (container) {
const memory = filesizeParser(container.usage.memory);
const cpu = KubernetesResourceReservationHelper.parseCPU(container.usage.cpu);
this.stats = {
read: stats.timestamp,
preread: '',
MemoryCache: 0,
MemoryUsage: memory,
NumProcs: '',
isWindows: false,
PreviousCPUTotalUsage: 0,
CPUUsage: (cpu / this.nodeCPU) * 100,
CPUCores: 0,
};
}
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to retrieve application stats');
}
});
}
$onDestroy() {
this.stopRepeater();
}
async onInit() {
this.state = {
autoRefresh: false,
refreshRate: '30',
viewReady: false,
transition: {
podName: this.$transition$.params().pod,
containerName: this.$transition$.params().container,
namespace: this.$transition$.params().namespace,
applicationName: this.$transition$.params().name,
},
getMetrics: false,
};
try {
await this.KubernetesMetricsService.getPod(this.state.transition.namespace, this.state.transition.podName);
} catch (error) {
this.state.getMetrics = false;
this.state.viewReady = true;
return;
}
try {
const podRaw = await this.KubernetesPodService.get(this.state.transition.namespace, this.state.transition.podName);
const pod = KubernetesPodConverter.apiToModel(podRaw.Raw);
if (pod) {
const node = await this.KubernetesNodeService.get(pod.Node);
this.nodeCPU = node.CPU;
} else {
throw new Error('Unable to find pod');
}
await this.getStats();
this.state.getMetrics = true;
this.$document.ready(() => {
this.initCharts();
});
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to retrieve application stats');
} finally {
this.state.viewReady = true;
}
}
$onInit() {
return this.$async(this.onInit);
}
}
export default KubernetesApplicationStatsController;
angular.module('portainer.kubernetes').controller('KubernetesApplicationStatsController', KubernetesApplicationStatsController);

View File

@@ -196,27 +196,7 @@
<label class="control-label text-left">
Enable features using metrics server
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="ctrl.formValues.UseServerMetrics" ng-change="ctrl.enableMetricsServer()" /><i></i>
</label>
</div>
<div ng-if="ctrl.state.metrics.pending && ctrl.state.metrics.userClick" class="col-sm-12 small text-muted" style="margin-top: 5px;">
Checking metrics API... <i class="fa fa-spinner fa-spin" style="margin-left: 2px;"></i>
</div>
<div
ng-if="!ctrl.state.metrics.pending && ctrl.state.metrics.isServerRunning && ctrl.state.metrics.userClick"
class="col-sm-12 small text-muted"
style="margin-top: 5px;"
>
<i class="fa fa-check green-icon" aria-hidden="true" style="margin-right: 2px;"></i> Successfully reached metrics API
</div>
<div
ng-if="!ctrl.state.metrics.pending && !ctrl.state.metrics.isServerRunning && ctrl.state.metrics.userClick"
class="col-sm-12 small text-muted"
style="margin-top: 5px;"
>
<i class="fa fa-times red-icon" aria-hidden="true" style="margin-right: 2px;"></i> Unable to reach metrics API, make sure metrics server is properly deployed inside
that cluster.
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="ctrl.formValues.UseServerMetrics" /><i></i> </label>
</div>
</div>

View File

@@ -28,8 +28,7 @@ class KubernetesConfigureController {
ModalService,
KubernetesNamespaceHelper,
KubernetesResourcePoolService,
KubernetesIngressService,
KubernetesMetricsService
KubernetesIngressService
) {
this.$async = $async;
this.$state = $state;
@@ -42,7 +41,6 @@ class KubernetesConfigureController {
this.KubernetesNamespaceHelper = KubernetesNamespaceHelper;
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
this.KubernetesIngressService = KubernetesIngressService;
this.KubernetesMetricsService = KubernetesMetricsService;
this.IngressClassTypes = KubernetesIngressClassTypes;
@@ -152,7 +150,7 @@ class KubernetesConfigureController {
ingressesToDel.forEach((ingress) => {
resourcePools.forEach((resourcePool) => {
promises.push(this.KubernetesIngressService.delete({ IngressClass: ingress, Namespace: resourcePool.Namespace.Name }));
promises.push(this.KubernetesIngressService.delete(resourcePool.Namespace.Name, ingress.Name));
});
});
@@ -163,27 +161,6 @@ class KubernetesConfigureController {
}
});
}
enableMetricsServer() {
if (this.formValues.UseServerMetrics) {
this.state.metrics.userClick = true;
this.state.metrics.pending = true;
this.KubernetesMetricsService.capabilities(this.endpoint.Id)
.then(() => {
this.state.metrics.isServerRunning = true;
this.state.metrics.pending = false;
this.formValues.UseServerMetrics = true;
})
.catch(() => {
this.state.metrics.isServerRunning = false;
this.state.metrics.pending = false;
this.formValues.UseServerMetrics = false;
});
} else {
this.state.metrics.userClick = false;
this.formValues.UseServerMetrics = false;
}
}
async configureAsync() {
try {
@@ -245,11 +222,6 @@ class KubernetesConfigureController {
duplicates: {
ingressClasses: new KubernetesFormValidationReferences(),
},
metrics: {
pending: false,
isServerRunning: false,
userClick: false,
},
};
this.formValues = {

View File

@@ -208,7 +208,7 @@
</div>
</div>
<div class="form-group" ng-repeat-start="ic in ctrl.formValues.IngressClasses track by ic.IngressClass.Name">
<div class="form-group" ng-repeat-start="ic in ctrl.formValues.IngressClasses">
<div class="text-muted col-sm-12" style="width: 100%;">
<div style="border-bottom: 1px solid #cdcdcd; padding-bottom: 5px;">
<i class="fa fa-route" aria-hidden="true" style="margin-right: 2px;"></i> {{ ic.IngressClass.Name }}
@@ -225,58 +225,30 @@
<div ng-if="ic.Selected">
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Hostnames
<portainer-tooltip
position="bottom"
message="Hostnames associated to the ingress inside this resource pool. Users will be able to expose and access their applications over the ingress via one of these hostname."
>
</portainer-tooltip>
</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="ctrl.addHostname(ic)">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add hostname
</span>
</div>
<div class="col-sm-12" style="margin-top: 10px;">
<div ng-repeat="item in ic.Hosts track by $index" style="margin-top: 2px;">
<div class="form-inline">
<div class="col-sm-10 input-group input-group-sm">
<span class="input-group-addon">Hostname</span>
<input
type="text"
class="form-control"
name="hostname_{{ ic.IngressClass.Name }}_{{ $index }}"
ng-model="item.Host"
ng-change="ctrl.onChangeIngressHostname()"
placeholder="foo"
required
/>
</div>
<div class="col-sm-1 input-group input-group-sm" ng-if="$index > 0">
<button class="btn btn-sm btn-danger" type="button" ng-click="ctrl.removeHostname(ic, $index)">
<i class="fa fa-trash-alt" aria-hidden="true"></i>
</button>
</div>
</div>
<div
class="small text-warning"
style="margin-top: 5px;"
ng-show="
resourcePoolCreationForm['hostname_' + ic.IngressClass.Name + '_' + $index].$invalid ||
ctrl.state.duplicates.ingressHosts.refs[ic.IngressClass.Name][$index] !== undefined
"
>
<ng-messages for="resourcePoolCreationForm['hostname_' + ic.IngressClass.Name + '_' + $index].$error">
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Hostname is required.</p>
</ng-messages>
<p ng-if="ctrl.state.duplicates.ingressHosts.refs[ic.IngressClass.Name][$index] !== undefined">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This hostname is already used.
</p>
</div>
</div>
<label class="control-label text-left col-sm-2">
Hostname
<portainer-tooltip
position="bottom"
message="Hostname associated to the ingress inside this resource pool. Users will be able to expose and access their applications over the ingress via this hostname."
>
</portainer-tooltip>
</label>
<div class="col-sm-10">
<input class="form-control" name="ingress_host_{{ $index }}" ng-model="ic.Host" placeholder="host.com" ng-change="ctrl.onChangeIngressHostname()" required />
</div>
</div>
<div class="form-group" ng-show="resourcePoolCreationForm['ingress_host_' + $index].$invalid || ctrl.state.duplicates.ingressHosts.refs[$index] !== undefined">
<div class="col-sm-12 small text-warning">
<div ng-messages="resourcePoolCreationForm['ingress_host_' + $index].$error">
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
</div>
<p ng-if="ctrl.state.duplicates.ingressHosts.refs[$index] !== undefined">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
This host is already used.
</p>
</div>
</div>
<div class="form-group" ng-if="ic.IngressClass.Type === ctrl.IngressClassTypes.NGINX">
<div class="col-sm-12">
<label class="control-label text-left">

View File

@@ -3,11 +3,7 @@ import _ from 'lodash-es';
import filesizeParser from 'filesize-parser';
import { KubernetesResourceQuotaDefaults } from 'Kubernetes/models/resource-quota/models';
import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceReservationHelper';
import {
KubernetesResourcePoolFormValues,
KubernetesResourcePoolIngressClassAnnotationFormValue,
KubernetesResourcePoolIngressClassHostFormValue,
} from 'Kubernetes/models/resource-pool/formValues';
import { KubernetesResourcePoolFormValues, KubernetesResourcePoolIngressClassAnnotationFormValue } from 'Kubernetes/models/resource-pool/formValues';
import { KubernetesIngressConverter } from 'Kubernetes/ingress/converter';
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
import { KubernetesFormValidationReferences } from 'Kubernetes/models/application/formValues';
@@ -38,43 +34,17 @@ class KubernetesCreateResourcePoolController {
onChangeIngressHostname() {
const state = this.state.duplicates.ingressHosts;
const hosts = _.flatMap(this.formValues.IngressClasses, 'Hosts');
const hostnames = _.map(hosts, 'Host');
const hostnamesWithoutRemoved = _.filter(hostnames, (h) => !h.NeedsDeletion);
const allHosts = _.flatMap(this.allIngresses, 'Hosts');
const formDuplicates = KubernetesFormValidationHelper.getDuplicates(hostnamesWithoutRemoved);
_.forEach(hostnames, (host, idx) => {
if (host !== undefined && _.includes(allHosts, host)) {
formDuplicates[idx] = host;
const hosts = _.map(this.formValues.IngressClasses, 'Host');
const allHosts = _.map(this.allIngresses, 'Host');
const duplicates = KubernetesFormValidationHelper.getDuplicates(hosts);
_.forEach(hosts, (host, idx) => {
if (_.includes(allHosts, host) && host !== undefined) {
duplicates[idx] = host;
}
});
const duplicates = {};
let count = 0;
_.forEach(this.formValues.IngressClasses, (ic) => {
duplicates[ic.IngressClass.Name] = {};
_.forEach(ic.Hosts, (hostFV, hostIdx) => {
if (hostFV.Host === formDuplicates[count]) {
duplicates[ic.IngressClass.Name][hostIdx] = hostFV.Host;
}
count++;
});
});
state.refs = duplicates;
state.hasRefs = false;
_.forIn(duplicates, (value) => {
if (Object.keys(value).length > 0) {
state.hasRefs = true;
}
});
}
addHostname(ingressClass) {
ingressClass.Hosts.push(new KubernetesResourcePoolIngressClassHostFormValue());
}
removeHostname(ingressClass, index) {
ingressClass.Hosts.splice(index, 1);
this.onChangeIngressHostname();
state.hasRefs = Object.keys(duplicates).length > 0;
}
/* #region ANNOTATIONS MANAGEMENT */
@@ -198,11 +168,6 @@ class KubernetesCreateResourcePoolController {
const ingressClasses = endpoint.Kubernetes.Configuration.IngressClasses;
this.formValues.IngressClasses = KubernetesIngressConverter.ingressClassesToFormValues(ingressClasses);
}
_.forEach(this.formValues.IngressClasses, (ic) => {
if (ic.Hosts.length === 0) {
ic.Hosts.push(new KubernetesResourcePoolIngressClassHostFormValue());
}
});
} catch (err) {
this.Notifications.error('Failure', err, 'Unable to load view data');
} finally {

View File

@@ -167,7 +167,7 @@
</div>
</div>
<div class="form-group" ng-repeat-start="ic in ctrl.formValues.IngressClasses track by ic.IngressClass.Name">
<div class="form-group" ng-repeat-start="ic in ctrl.formValues.IngressClasses">
<div class="text-muted col-sm-12" style="width: 100%;">
<div style="border-bottom: 1px solid #cdcdcd; padding-bottom: 5px;">
<i class="fa fa-route" aria-hidden="true" style="margin-right: 2px;"></i> {{ ic.IngressClass.Name }}
@@ -184,57 +184,34 @@
<div ng-if="ic.Selected">
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Hostnames
<portainer-tooltip
position="bottom"
message="Hostnames associated to the ingress inside this resource pool. Users will be able to expose and access their applications over the ingress via one of these hostname."
>
</portainer-tooltip>
</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="ctrl.addHostname(ic)">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add hostname
</span>
<label class="control-label text-left col-sm-2">
Hostname
<portainer-tooltip
position="bottom"
message="Hostname associated to the ingress inside this resource pool. Users will be able to expose and access their applications over the ingress via this hostname."
>
</portainer-tooltip>
</label>
<div class="col-sm-10">
<input
class="form-control"
name="ingress_host_{{ $index }}"
ng-model="ic.Host"
placeholder="host.com"
ng-change="ctrl.onChangeIngressHostname()"
required
/>
</div>
<div class="col-sm-12" style="margin-top: 10px;">
<div ng-repeat="item in ic.Hosts track by $index" style="margin-top: 2px;">
<div class="form-inline">
<div class="col-sm-10 input-group input-group-sm" ng-class="{ striked: item.NeedsDeletion }">
<span class="input-group-addon">Hostname</span>
<input
type="text"
class="form-control"
name="hostname_{{ ic.IngressClass.Name }}_{{ $index }}"
ng-model="item.Host"
ng-change="ctrl.onChangeIngressHostname()"
placeholder="foo"
required
/>
</div>
<div class="col-sm-1 input-group input-group-sm" ng-if="$index > 0">
<button ng-if="!item.NeedsDeletion" class="btn btn-sm btn-danger" type="button" ng-click="ctrl.removeHostname(ic, $index)">
<i class="fa fa-trash-alt" aria-hidden="true"></i>
</button>
<button ng-if="item.NeedsDeletion" class="btn btn-sm btn-primary" type="button" ng-click="ctrl.restoreHostname(item)">
<i class="fa fa-trash-restore" aria-hidden="true"></i>
</button>
</div>
</div>
<div
class="small text-warning"
style="margin-top: 5px;"
ng-show="resourcePoolEditForm['hostname_' + ic.IngressClass.Name + '_' + $index].$invalid || item.Duplicate"
>
<ng-messages for="resourcePoolEditForm['hostname_' + ic.IngressClass.Name + '_' + $index].$error">
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Hostname is required.</p>
</ng-messages>
<p ng-if="item.Duplicate">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
This hostname is already used.
</p>
</div>
</div>
<div class="form-group" ng-show="resourcePoolEditForm['ingress_host_' + $index].$invalid || ctrl.state.duplicates.ingressHosts.refs[$index] !== undefined">
<div class="col-sm-12 small text-warning">
<div ng-messages="resourcePoolEditForm['ingress_host_' + $index].$error">
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
</div>
<p ng-if="ctrl.state.duplicates.ingressHosts.refs[$index] !== undefined">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
This host is already used.
</p>
</div>
</div>

View File

@@ -4,11 +4,7 @@ import filesizeParser from 'filesize-parser';
import { KubernetesResourceQuota, KubernetesResourceQuotaDefaults } from 'Kubernetes/models/resource-quota/models';
import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceReservationHelper';
import KubernetesEventHelper from 'Kubernetes/helpers/eventHelper';
import {
KubernetesResourcePoolFormValues,
KubernetesResourcePoolIngressClassAnnotationFormValue,
KubernetesResourcePoolIngressClassHostFormValue,
} from 'Kubernetes/models/resource-pool/formValues';
import { KubernetesResourcePoolFormValues, KubernetesResourcePoolIngressClassAnnotationFormValue } from 'Kubernetes/models/resource-pool/formValues';
import { KubernetesIngressConverter } from 'Kubernetes/ingress/converter';
import { KubernetesFormValidationReferences } from 'Kubernetes/models/application/formValues';
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
@@ -66,6 +62,22 @@ class KubernetesResourcePoolController {
}
/* #endregion */
onChangeIngressHostname() {
const state = this.state.duplicates.ingressHosts;
const hosts = _.map(this.formValues.IngressClasses, 'Host');
const otherIngresses = _.without(this.allIngresses, ...this.ingresses);
const allHosts = _.map(otherIngresses, 'Host');
const duplicates = KubernetesFormValidationHelper.getDuplicates(hosts);
_.forEach(hosts, (host, idx) => {
if (_.includes(allHosts, host) && host !== undefined) {
duplicates[idx] = host;
}
});
state.refs = duplicates;
state.hasRefs = Object.keys(duplicates).length > 0;
}
/* #region ANNOTATIONS MANAGEMENT */
addAnnotation(ingressClass) {
ingressClass.Annotations.push(new KubernetesResourcePoolIngressClassAnnotationFormValue());
@@ -73,59 +85,9 @@ class KubernetesResourcePoolController {
removeAnnotation(ingressClass, index) {
ingressClass.Annotations.splice(index, 1);
this.onChangeIngressHostname();
}
/* #endregion */
/* #region INGRESS MANAGEMENT */
onChangeIngressHostname() {
const state = this.state.duplicates.ingressHosts;
const otherIngresses = _.without(this.allIngresses, ...this.ingresses);
const allHosts = _.flatMap(otherIngresses, 'Hosts');
const hosts = _.flatMap(this.formValues.IngressClasses, 'Hosts');
const hostsWithoutRemoved = _.filter(hosts, { NeedsDeletion: false });
const hostnames = _.map(hostsWithoutRemoved, 'Host');
const formDuplicates = KubernetesFormValidationHelper.getDuplicates(hostnames);
_.forEach(hostnames, (host, idx) => {
if (host !== undefined && _.includes(allHosts, host)) {
formDuplicates[idx] = host;
}
});
const duplicatedHostnames = Object.values(formDuplicates);
state.hasRefs = false;
_.forEach(this.formValues.IngressClasses, (ic) => {
_.forEach(ic.Hosts, (hostFV) => {
if (_.includes(duplicatedHostnames, hostFV.Host) && hostFV.NeedsDeletion === false) {
hostFV.Duplicate = true;
state.hasRefs = true;
} else {
hostFV.Duplicate = false;
}
});
});
}
addHostname(ingressClass) {
ingressClass.Hosts.push(new KubernetesResourcePoolIngressClassHostFormValue());
}
removeHostname(ingressClass, index) {
if (!ingressClass.Hosts[index].IsNew) {
ingressClass.Hosts[index].NeedsDeletion = true;
} else {
ingressClass.Hosts.splice(index, 1);
}
this.onChangeIngressHostname();
}
restoreHostname(host) {
if (!host.IsNew) {
host.NeedsDeletion = false;
}
}
/* #endregion*/
selectTab(index) {
this.LocalStorage.storeActiveTab('resourcePool', index);
}
@@ -350,11 +312,6 @@ class KubernetesResourcePoolController {
await this.getIngresses();
const ingressClasses = endpoint.Kubernetes.Configuration.IngressClasses;
this.formValues.IngressClasses = KubernetesIngressConverter.ingressClassesToFormValues(ingressClasses, this.ingresses);
_.forEach(this.formValues.IngressClasses, (ic) => {
if (ic.Hosts.length === 0) {
ic.Hosts.push(new KubernetesResourcePoolIngressClassHostFormValue());
}
});
}
this.savedFormValues = angular.copy(this.formValues);
} catch (err) {

View File

@@ -96,8 +96,10 @@ class EditCustomTemplateViewController {
}
editorUpdate(cm) {
this.formValues.FileContent = cm.getValue();
this.state.isEditorDirty = true;
if (this.formValues.FileContent.replace(/(\r\n|\n|\r)/gm, '') !== cm.getValue().replace(/(\r\n|\n|\r)/gm, '')) {
this.formValues.FileContent = cm.getValue();
this.state.isEditorDirty = true;
}
}
async uiCanExit() {

View File

@@ -201,12 +201,11 @@ angular.module('portainer.app').controller('StackController', [
};
$scope.editorUpdate = function (cm) {
if ($scope.stackFileContent !== cm.getValue()) {
if ($scope.stackFileContent.replace(/(\r\n|\n|\r)/gm, '') !== cm.getValue().replace(/(\r\n|\n|\r)/gm, '')) {
$scope.state.isEditorDirty = true;
$scope.stackFileContent = cm.getValue();
$scope.state.yamlError = StackHelper.validateYAML($scope.stackFileContent, $scope.containerNames);
}
$scope.stackFileContent = cm.getValue();
$scope.state.yamlError = StackHelper.validateYAML($scope.stackFileContent, $scope.containerNames);
$scope.state.isEditorDirty = true;
};
$scope.stopStack = stopStack;
@@ -269,8 +268,7 @@ angular.module('portainer.app').controller('StackController', [
var stack = data.stack;
$scope.groups = data.groups;
$scope.stack = stack;
$scope.containers = data.containers;
$scope.containerNames = ContainerHelper.getContainerNames($scope.containers);
$scope.containerNames = ContainerHelper.getContainerNames(data.containers);
let resourcesPromise = Promise.resolve({});
if (stack.Status === 1) {

View File

@@ -1,6 +1,6 @@
ARG OSVERSION
FROM --platform=linux/amd64 gcr.io/k8s-staging-e2e-test-images/windows-servercore-cache:1.0-linux-amd64-${OSVERSION} as core
FROM --platform=linux/amd64 alpine:3 as downloader
FROM --platform=linux/amd64 alpine:3.13.0 as downloader
ENV GIT_VERSION 2.30.0
ENV GIT_PATCH_VERSION 2

View File

@@ -191,7 +191,7 @@ function shell_download_docker_binary(p, a) {
var ip = ps[p] === undefined ? p : ps[p];
var ia = as[a] === undefined ? a : as[a];
var binaryVersion = p === 'windows' ? '<%= binaries.dockerWindowsVersion %>' : '<%= binaries.dockerLinuxVersion %>';
return [
'if [ -f dist/docker ] || [ -f dist/docker.exe ]; then',
'echo "docker binary exists";',
@@ -207,7 +207,7 @@ function shell_download_docker_compose_binary(p, a) {
var ip = ps[p] || p;
var ia = as[a] || a;
var binaryVersion = p === 'windows' ? '<%= binaries.dockerWindowsComposeVersion %>' : '<%= binaries.dockerLinuxComposeVersion %>';
return [
'if [ -f dist/docker-compose ] || [ -f dist/docker-compose.exe ]; then',
'echo "Docker Compose binary exists";',
@@ -219,7 +219,7 @@ function shell_download_docker_compose_binary(p, a) {
function shell_download_kompose_binary(p, a) {
var binaryVersion = '<%= binaries.komposeVersion %>';
return [
'if [ -f dist/kompose ] || [ -f dist/kompose.exe ]; then',
'echo "kompose binary exists";',
@@ -231,7 +231,7 @@ function shell_download_kompose_binary(p, a) {
function shell_download_kubectl_binary(p, a) {
var binaryVersion = '<%= binaries.kubectlVersion %>';
return [
'if [ -f dist/kubectl ] || [ -f dist/kubectl.exe ]; then',
'echo "kubectl binary exists";',

View File

@@ -2,7 +2,7 @@
"author": "Portainer.io",
"name": "portainer",
"homepage": "http://portainer.io",
"version": "2.4.0",
"version": "2.5.0",
"repository": {
"type": "git",
"url": "git@github.com:portainer/portainer.git"