7 Commits

Author SHA1 Message Date
zc 501821bedd support ca automatic base64 decoding 2022-11-17 09:33:38 +08:00
zc 73e34c8f47 support file patterns 2022-11-15 16:04:27 +08:00
zc 8fae8bd31f support config files to parse env 2022-11-14 17:00:54 +08:00
zc 6932f82e7c support sprig template funcs and all envs 2022-11-14 14:59:38 +08:00
zc 4f0c2ee15b add action docker cache 2022-11-11 10:29:07 +08:00
zc ec0a62a0fa remove redundant output 2022-11-11 09:30:24 +08:00
zc a675739e91 fix service update 2022-11-10 17:31:27 +08:00
10 changed files with 218 additions and 76 deletions
+17 -4
View File
@@ -30,7 +30,15 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@master
uses: docker/setup-buildx-action@v2
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to Docker Hub
uses: docker/login-action@v2
@@ -39,15 +47,20 @@ jobs:
password: ${{ secrets.DOCKER_SECRET }}
- name: Build and publish ${{ matrix.target.Dockerfile }}
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
push: true
builder: ${{ steps.buildx.outputs.name }}
file: ${{ matrix.target.Dockerfile }}
platforms: linux/amd64,linux/arm64,linux/arm
cache-from: type=gha,scope=${{ github.workflow }}
cache-to: type=gha,mode=max,scope=${{ github.workflow }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
tags: |
zc2638/drone-k8s-plugin:${{ steps.prepare.outputs.full_tag_name }}
zc2638/drone-k8s-plugin:${{ steps.prepare.outputs.latest_tag }}
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
+20 -16
View File
@@ -20,21 +20,21 @@ docker run --rm \
### Environments
| name | required | type | description |
|:--------------------|:--------:|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| kubernetes_server | ✔️ | string | The address and port of the Kubernetes API server. |
| k8s_server | | string | The same as `kubernetes_server`. |
| kubernetes_token | ✔️ | string | Token from ServiceAccount for authentication to the API server. |
| k8s_token | | string | The same as `kubernetes_token`. |
| kubernetes_ca_crt | | string | Certificate from ServiceAccount for authentication to the API server. |
| k8s_ca_crt | | string | The same as `kubernetes_ca_crt`. |
| kubernetes_skip_tls | | bool | If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. |
| k8s_skip_tls | | bool | The same as `kubernetes_skip_tls_verify`. |
| init_templates | | []string | Path to Kubernetes Resource yaml based definition file (e.g. ConfigMap, Deployment or others), used to initialize some resources. |
| templates | | []string | Path to Kubernetes Resource yaml based definition file (e.g. ConfigMap, Deployment or others). |
| config_files | | []string | Config file paths for automatic creation/update of ConfigMap.The syntax is expressed as `namespace:name:file_path:file_name` or `namespace:name:file_path`, when file_name is not specified, it will default to the file name of file_path. |
| namespace | | string | Default namespace to use when namespace is not set. |
| debug | | bool | Used to enable debug level logging. |
| name | required | type | description |
|:--------------------|:--------:|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| kubernetes_server | ✔️ | string | The address and port of the Kubernetes API server. |
| k8s_server | | string | The same as `kubernetes_server`. |
| kubernetes_token | ✔️ | string | Token from ServiceAccount for authentication to the API server. The value must be base64 encoded. |
| k8s_token | | string | The same as `kubernetes_token`. |
| kubernetes_ca_crt | | string | Certificate from ServiceAccount for authentication to the API server. The value must be base64 encoded. |
| k8s_ca_crt | | string | The same as `kubernetes_ca_crt`. |
| kubernetes_skip_tls | | bool | If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. |
| k8s_skip_tls | | bool | The same as `kubernetes_skip_tls_verify`. |
| init_templates | | []string | Path to Kubernetes Resource yaml based definition file (e.g. ConfigMap, Deployment or others), used to initialize some resources. |
| templates | | []string | Path to Kubernetes Resource yaml based definition file (e.g. ConfigMap, Deployment or others). |
| config_files | | []string | Config file paths for automatic creation/update of ConfigMap.The syntax is expressed as `namespace:name:file_path:file_name` or `namespace:name:file_path`, when file_name is not specified, it will default to the file name of file_path. |
| namespace | | string | Default namespace to use when namespace is not set. |
| debug | | bool | Used to enable debug level logging. |
## Drone Example
@@ -56,15 +56,19 @@ steps:
from_secret: k8s_ca_crt
k8s_skip_tls: false
namespace: default
init_templates:
- testdata/namespace.yaml
config_files:
- default:test-config:testdata/config.yaml
- default:test-config:testdata/config.yaml:a.yaml
templates:
- testdata/deployment.yaml
- testdata/service.yaml
- testdata/*.yaml
app_name: ${DRONE_REPO_NAME}
```
OR
OR
```yaml
kind: pipeline
+18 -6
View File
@@ -3,15 +3,24 @@ module github.com/zc2638/drone-k8s-plugin
go 1.19
require (
github.com/99nil/gopkg v0.0.0-20221020090523-251ae5920751
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/a8m/envsubst v1.3.0
github.com/bmatcuk/doublestar/v4 v4.4.0
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.14.0
golang.org/x/sync v0.1.0
k8s.io/api v0.25.3
k8s.io/apimachinery v0.25.3
k8s.io/client-go v0.25.3
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -25,12 +34,17 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -41,11 +55,11 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/crypto v0.2.0 // indirect
golang.org/x/net v0.2.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/term v0.2.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
google.golang.org/appengine v1.6.7 // indirect
@@ -54,8 +68,6 @@ require (
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.25.3 // indirect
k8s.io/apimachinery v0.25.3 // indirect
k8s.io/klog/v2 v2.70.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
+31 -6
View File
@@ -36,12 +36,24 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/99nil/gopkg v0.0.0-20221020090523-251ae5920751 h1:Iebp4akbVu6Sf2WlFqb9/aBl7mxH1jTgkG0zHJFrzw8=
github.com/99nil/gopkg v0.0.0-20221020090523-251ae5920751/go.mod h1:qbZsXE0O2/hY9mWK0tOOCbg8FrFarc3Ym/39i7V9akQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/a8m/envsubst v1.3.0 h1:GmXKmVssap0YtlU3E230W98RWtWCyIZzjtf1apWWyAg=
github.com/a8m/envsubst v1.3.0/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
github.com/bmatcuk/doublestar/v4 v4.4.0 h1:LmAwNwhjEbYtyVLzjcP/XeVw4nhuScHGkF/XWXnvIic=
github.com/bmatcuk/doublestar/v4 v4.4.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@@ -145,6 +157,8 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -152,8 +166,12 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -178,10 +196,14 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -251,6 +273,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE=
golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -316,8 +340,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -377,11 +401,11 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -558,6 +582,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+8 -2
View File
@@ -17,6 +17,7 @@ package kube
import (
"encoding/base64"
"errors"
"fmt"
"strings"
"k8s.io/client-go/rest"
@@ -39,7 +40,7 @@ func NewRestConfig(config *Config) (*rest.Config, error) {
token := strings.ReplaceAll(config.Token, " ", "")
tokenBytes, err := base64.StdEncoding.DecodeString(token)
if err != nil {
return nil, err
return nil, fmt.Errorf("base64 decode token failed: %v", err)
}
restConfig = &rest.Config{
BearerToken: string(tokenBytes),
@@ -49,8 +50,13 @@ func NewRestConfig(config *Config) (*rest.Config, error) {
},
}
if !config.SkipTLS {
caCrt := strings.ReplaceAll(config.CaCrt, " ", "")
caCrtBytes, err := base64.StdEncoding.DecodeString(caCrt)
if err != nil {
return nil, fmt.Errorf("base64 decode ca failed: %v", err)
}
restConfig.Insecure = false
restConfig.CAData = []byte(config.CaCrt)
restConfig.CAData = caCrtBytes
}
restConfig.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(1000, 1000)
+37 -2
View File
@@ -15,7 +15,9 @@
package plugin
import (
"fmt"
"os"
"strings"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -46,10 +48,14 @@ func NewCommand() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
cfg := opt.Config()
cfg.BindEnvs()
logrus.Infof("Config Path: %s", opt.ConfigPath)
if err := cfg.Parse(opt.ConfigPath, constants.ProjectName); err != nil {
logrus.Fatal(err)
}
if err := cfg.Validate(); err != nil {
envMap := getEnvMap()
envs := envToSlice(envMap)
if err := cfg.Validate(envs); err != nil {
logrus.Fatal(err)
}
if cfg.Debug {
@@ -69,7 +75,7 @@ func NewCommand() *cobra.Command {
if err != nil {
logrus.Fatal(err)
}
if err := run(cfg, kubeClient, dynamicClient); err != nil {
if err := run(cfg, kubeClient, dynamicClient, envMap); err != nil {
logrus.Fatal(err)
}
},
@@ -79,3 +85,32 @@ func NewCommand() *cobra.Command {
"config file (default is $HOME/.drone-plugin/config.yaml)")
return cmd
}
func getEnvMap() map[string]string {
envMap := make(map[string]string)
envs := os.Environ()
for _, v := range envs {
if pluginExp.MatchString(v) {
matches := pluginExp.FindStringSubmatch(v)
key := strings.ToLower(matches[1])
envMap[key] = matches[2]
logrus.Debugf("env: %s=%s", key, matches[2])
}
parts := strings.SplitN(v, "=", 2)
if len(parts) != 2 {
continue
}
envMap[parts[0]] = parts[1]
logrus.Debugf("env: %s=%s", parts[0], parts[1])
}
return envMap
}
func envToSlice(set map[string]string) []string {
env := make([]string, 0, len(set))
for k, v := range set {
env = append(env, fmt.Sprintf("%s=%s", k, v))
}
return env
}
+14 -6
View File
@@ -21,6 +21,8 @@ import (
"path/filepath"
"strings"
"github.com/a8m/envsubst/parse"
"github.com/zc2638/drone-k8s-plugin/pkg/constants"
"github.com/zc2638/drone-k8s-plugin/pkg/kube"
@@ -83,29 +85,35 @@ func (c *Config) GetConfigFiles() []ConfigFile {
return c.configFiles[:]
}
func (c *Config) Validate() error {
func (c *Config) Validate(envs []string) error {
if len(c.InitTemplates) == 0 && len(c.ConfigFiles) == 0 && len(c.Templates) == 0 {
return errors.New("at least one of init_templates, config_files and templates is defined")
}
parser := parse.New("string", envs, &parse.Restrictions{})
cfs := make([]ConfigFile, 0, len(c.ConfigFiles))
for _, v := range c.ConfigFiles {
val, err := parser.Parse(v)
if err != nil {
return fmt.Errorf("parse env variable failed: %v", err)
}
cf := ConfigFile{}
parts := strings.Split(v, ":")
parts := strings.Split(val, ":")
switch len(parts) {
case 3:
case 4:
cf.FileName = parts[3]
default:
return fmt.Errorf("config file (%s) format error, please use `namespace:name:file` or `namespace:name:filepath:filename` to define", v)
return fmt.Errorf("config file (%s) format error, please use `namespace:name:file` or `namespace:name:filepath:filename` to define", val)
}
cf.Namespace = parts[0]
cf.Name = parts[1]
cf.FilePath = parts[2]
_, err := os.Stat(cf.FilePath)
if err != nil {
return err
if _, err := os.Stat(cf.FilePath); err != nil {
return fmt.Errorf("stat config file(%s) failed: %v", val, err)
}
cfs = append(cfs, cf)
}
+66 -29
View File
@@ -21,7 +21,12 @@ import (
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/99nil/gopkg/sets"
"github.com/bmatcuk/doublestar/v4"
pkgruntime "k8s.io/apimachinery/pkg/runtime"
v1 "k8s.io/api/core/v1"
@@ -39,27 +44,14 @@ import (
"github.com/zc2638/drone-k8s-plugin/pkg/tpl"
)
var (
pluginExp = regexp.MustCompile(`^PLUGIN_(.*)=(.*)`)
droneExp = regexp.MustCompile(`^DRONE_(.*)=(.*)`)
)
func run(cfg *Config, kubeClient kubernetes.Interface, dynamicClient dynamic.Interface) error {
envMap := make(map[string]string)
envs := os.Environ()
for _, v := range envs {
if pluginExp.MatchString(v) {
matches := pluginExp.FindStringSubmatch(v)
key := strings.ToLower(matches[1])
envMap[key] = matches[2]
}
if droneExp.MatchString(v) {
matches := droneExp.FindStringSubmatch(v)
key := strings.ToLower(matches[1])
envMap[key] = matches[2]
}
}
var pluginExp = regexp.MustCompile(`^PLUGIN_(.*)=(.*)`)
func run(
cfg *Config,
kubeClient kubernetes.Interface,
dynamicClient dynamic.Interface,
envMap map[string]string,
) error {
initObjSet, err := parseObjectSet(cfg.InitTemplates, envMap)
if err != nil {
return fmt.Errorf("parse init_templates failed: %v", err)
@@ -75,15 +67,15 @@ func run(cfg *Config, kubeClient kubernetes.Interface, dynamicClient dynamic.Int
}
mapping := restmapper.NewDiscoveryRESTMapper(gr)
logrus.Debug("start to apply resources from init templates")
logrus.Debug("Start to apply resources from init templates")
if err := applyResources(dynamicClient, mapping, initObjSet, cfg.Namespace); err != nil {
return err
}
logrus.Debug("start to apply configmaps from config files")
logrus.Debug("Start to apply configmaps from config files")
if err := applyForConfig(kubeClient, cfg.GetConfigFiles()); err != nil {
return err
}
logrus.Debug("start to apply resources from templates")
logrus.Debug("Start to apply resources from templates")
if err := applyResources(dynamicClient, mapping, objSet, cfg.Namespace); err != nil {
return err
}
@@ -91,16 +83,26 @@ func run(cfg *Config, kubeClient kubernetes.Interface, dynamicClient dynamic.Int
}
func parseObjectSet(templates []string, envMap map[string]string) ([][]unstructured.Unstructured, error) {
if len(templates) == 0 {
fileSet := sets.New[string]()
for _, v := range templates {
matches, err := doublestar.FilepathGlob(v)
if err != nil {
return nil, err
}
fileSet.Add(matches...)
}
files := fileSet.List()
if len(files) == 0 {
return nil, nil
}
objSet := make([][]unstructured.Unstructured, 0, len(templates))
for _, v := range templates {
objSet := make([][]unstructured.Unstructured, 0, len(files))
for _, v := range files {
ext := filepath.Ext(v)
isYamlFile := ext == ".yaml" || ext == ".yml"
if !isYamlFile {
logrus.Warnf("Ignore file (%s), not a yaml or yml file", v)
logrus.Warnf("Ignore dir or file (%s), not a yaml or yml file", v)
continue
}
@@ -140,7 +142,7 @@ func applyResources(
WithField("kind", gvk.Kind).
WithField("namespace", objCopy.GetNamespace()).
WithField("name", objCopy.GetName()).
Info("Apply resource")
Info("Apply Resource")
restMapping, err := mapping.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
@@ -172,6 +174,15 @@ func applyResources(
},
})
if err == nil {
switch objCopy.GetKind() {
case "Service":
objCopy, err = completeService(origin, objCopy)
if err != nil {
return err
}
default:
}
rv, _ := strconv.ParseInt(origin.GetResourceVersion(), 10, 64)
objCopy.SetResourceVersion(strconv.FormatInt(rv, 10))
if _, err = resourceInter.Update(ctx, objCopy, metav1.UpdateOptions{}); err != nil {
@@ -194,6 +205,32 @@ func applyResources(
}
return nil
}
func completeService(origin, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
var (
originSvc v1.Service
objSvc v1.Service
)
if err := pkgruntime.DefaultUnstructuredConverter.FromUnstructured(origin.UnstructuredContent(), &originSvc); err != nil {
return nil, fmt.Errorf("convert origin unstructured object %s to Service failed: %v", obj.GetName(), err)
}
if err := pkgruntime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &objSvc); err != nil {
return nil, fmt.Errorf("convert unstructured object %s to Service failed: %v", obj.GetName(), err)
}
objSvc.Spec.ClusterIP = originSvc.Spec.ClusterIP
objSvc.Spec.ClusterIPs = originSvc.Spec.ClusterIPs
unstructuredContent, err := pkgruntime.DefaultUnstructuredConverter.ToUnstructured(&objSvc)
if err != nil {
return nil, fmt.Errorf("convert Service %s to unstructured object failed: %v", objSvc.GetName(), err)
}
current := &unstructured.Unstructured{}
current.SetUnstructuredContent(unstructuredContent)
return current, nil
}
func applyForConfig(kubeClient kubernetes.Interface, cfs []ConfigFile) error {
if len(cfs) == 0 {
return nil
+3 -1
View File
@@ -18,10 +18,12 @@ import (
"bytes"
"text/template"
"github.com/Masterminds/sprig"
"github.com/zc2638/drone-k8s-plugin/pkg/constants"
)
var tpl = template.New(constants.ProjectName)
var tpl = template.New(constants.ProjectName).Funcs(sprig.TxtFuncMap())
func Render(in []byte, envMap map[string]string) ([]byte, error) {
t, err := tpl.Parse(string(in))
+4 -4
View File
@@ -1,14 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ app_name }}
namespace: {{ app_namespace }}
name: {{ .env.app_name }}
namespace: {{ .env.app_namespace }}
labels:
app: {{ app_name }}
app: {{ .env.app_name }}
spec:
ports:
- nodePort: 30090
port: 9090
selector:
app: {{ app_name }}
app: {{ .env.app_name }}
type: NodePort