mirror of https://github.com/knative/func.git
Compare commits
753 Commits
Author | SHA1 | Date |
---|---|---|
|
9e117217a6 | |
|
208801aecb | |
|
f6e6021693 | |
|
c48dbc1b7b | |
|
88c0dd6f8d | |
|
c13214d21f | |
|
0bc78a612c | |
|
3efb11c9a7 | |
|
94fb8cc916 | |
|
e4bd40bf20 | |
|
46266c9a5c | |
|
775a5f7926 | |
|
1aecc549ec | |
|
61ecd623a2 | |
|
ac3e634673 | |
|
065006cfb1 | |
|
aeb51b3f61 | |
|
13c7e76d94 | |
|
cac432e0dd | |
|
7fb68ef9d6 | |
|
2e49dd0de8 | |
|
df09ae9ec9 | |
|
80d05981a8 | |
|
719b2863ca | |
|
5f7666213c | |
|
f889e2cc93 | |
|
c7c55da940 | |
|
21ab7f4ead | |
|
5ec715f7ac | |
|
bdaa7df1e0 | |
|
d04ff0a378 | |
|
e06397d5c7 | |
|
285913345a | |
|
27caba92af | |
|
0157893d8e | |
|
860e063c85 | |
|
c41c9022a2 | |
|
a3dac70419 | |
|
837988484f | |
|
6d85dee462 | |
|
4c0fa017b7 | |
|
f096936c98 | |
|
211df1657f | |
|
30315ea15e | |
|
589bbe80fe | |
|
7799a697cf | |
|
00535383aa | |
|
5a6b4dcb5a | |
|
e3759ec0fb | |
|
d9389fb2fb | |
|
6a3ef466f4 | |
|
630064caef | |
|
bb1623fc78 | |
|
668175bdcc | |
|
6dae0f4604 | |
|
713aabb666 | |
|
c1358dada1 | |
|
7eeef5785a | |
|
96269d0308 | |
|
879233d668 | |
|
18a119abff | |
|
a18f763b6a | |
|
00fb58a3d9 | |
|
648c7cd346 | |
|
f9ab674651 | |
|
dfe2109f56 | |
|
58fb81a41a | |
|
f9bf9fe9cc | |
|
65de4ac2fc | |
|
a93cbe6785 | |
|
84d2ad08ad | |
|
1b83f0b294 | |
|
9c992c9409 | |
|
56e1b0f7f5 | |
|
69bdcbbecd | |
|
ec66c1a496 | |
|
243059b25b | |
|
c865638225 | |
|
e8ccb1bdcf | |
|
ffd997c448 | |
|
c990659a11 | |
|
a384d6e728 | |
|
347a901c16 | |
|
238e061a1c | |
|
b31a3a4ad3 | |
|
a90f07fdfb | |
|
9a71fa4725 | |
|
d47949c685 | |
|
327e404908 | |
|
824911c55f | |
|
1cccfd3220 | |
|
edd66501d4 | |
|
e9e88e5264 | |
|
20479af33c | |
|
90ed2421a0 | |
|
e5b34ecb1f | |
|
f43b09b74d | |
|
3da9704df8 | |
|
0ed0efbe27 | |
|
fd73021f34 | |
|
13444c3238 | |
|
33ab476607 | |
|
01b5c3eef6 | |
|
22e4f6d53a | |
|
3150fedb57 | |
|
f598fa45d0 | |
|
15b30dcd05 | |
|
70720edadc | |
|
535d6de273 | |
|
0ce5759cef | |
|
805cb5dcc5 | |
|
4c4fd28c23 | |
|
a062cd2872 | |
|
8a9583e30f | |
|
ecdcf868cb | |
|
55df89a874 | |
|
ff63772166 | |
|
bcd141d7cb | |
|
7467ce1f39 | |
|
76519f5bc7 | |
|
688a39ec24 | |
|
e3a957662f | |
|
c6c6aa2e12 | |
|
41666714f2 | |
|
f6b5e39b7c | |
|
de6022bf43 | |
|
e013e6ed31 | |
|
4e9fc0922f | |
|
3d4d7da487 | |
|
69cbc75f7b | |
|
ace7703e29 | |
|
0e1be8d1ed | |
|
d0deccb81b | |
|
8eb33ded0c | |
|
69a21a8e31 | |
|
370ca50313 | |
|
179ba2fcaa | |
|
0892ac62ee | |
|
c2b5d49ed4 | |
|
dfc317563a | |
|
0921e950eb | |
|
ce44678262 | |
|
33b9f15654 | |
|
8e0b752edc | |
|
36e27203a9 | |
|
09c934dcb0 | |
|
f12acd34de | |
|
0896b9011d | |
|
d02801355d | |
|
100d9ce56c | |
|
a518101187 | |
|
c12828fd08 | |
|
b67d8d4405 | |
|
910e862804 | |
|
841555ab0a | |
|
8a061c4ed1 | |
|
fffde39adb | |
|
c93de80381 | |
|
3e75e25506 | |
|
c98b9f67c3 | |
|
e720bbcc8c | |
|
a2469fe9da | |
|
aae2683231 | |
|
fc750a283a | |
|
2d3962401d | |
|
9f6a135702 | |
|
36803160d5 | |
|
b6bfb2d960 | |
|
c7a95dd81b | |
|
d8f6ceba07 | |
|
d4506e32dd | |
|
335b6c29fa | |
|
234c442421 | |
|
e9dfba995c | |
|
7216de194d | |
|
77e43bc8c6 | |
|
598c5e237f | |
|
817c77bbec | |
|
525761a199 | |
|
24a7fedadd | |
|
90624a8725 | |
|
a351afdc9b | |
|
a051e829e2 | |
|
180b1eea0e | |
|
f66b67aa8f | |
|
e0e79957f1 | |
|
2b831f9b2e | |
|
fa79d313e0 | |
|
7e357eb574 | |
|
0bb27b7bcc | |
|
4ade4ab3d9 | |
|
51a14ccf23 | |
|
7ce6373fd0 | |
|
fd43db95a6 | |
|
04100c8dd8 | |
|
c14ff995c6 | |
|
d4cfaa93e0 | |
|
e81df11734 | |
|
91daa09682 | |
|
0f0b53630b | |
|
809ccc6db6 | |
|
98fd887cac | |
|
a1589c9130 | |
|
cad00d7a16 | |
|
8ab6083972 | |
|
9ef6c337f7 | |
|
c4e4cc7119 | |
|
3239d06c9b | |
|
8d056d0ece | |
|
65e3812a45 | |
|
d649adaf56 | |
|
104e90ce5c | |
|
68deddf80b | |
|
88afd64d40 | |
|
d7f4b8341f | |
|
1d26629b51 | |
|
d548e3fe45 | |
|
f38fbab231 | |
|
67d17c2d51 | |
|
9c01642552 | |
|
a9cb5b7a93 | |
|
c28d5ba441 | |
|
a25e3274d7 | |
|
bc6fad7635 | |
|
de0d248e2f | |
|
9c0c216193 | |
|
f8db896f85 | |
|
c34974e3a1 | |
|
6c57bfaa6d | |
|
e6ebd1c2f5 | |
|
2228c9dbe0 | |
|
d20eb9685f | |
|
4b1cc39731 | |
|
e1758e86f6 | |
|
dbdc5ca671 | |
|
18ce3488e8 | |
|
ee3a2b9f39 | |
|
60d9126dc7 | |
|
4de372564a | |
|
23668cbf36 | |
|
20a173a6de | |
|
e024ae699c | |
|
0cbf721539 | |
|
020dd96d61 | |
|
d2aa94d30a | |
|
6c5b7613a1 | |
|
56099e7017 | |
|
fe8ca74840 | |
|
527b917f07 | |
|
68cd559356 | |
|
02b331d8d2 | |
|
a72c3301bd | |
|
09e2eef5c9 | |
|
f734f82385 | |
|
59a442c03f | |
|
28225ceede | |
|
cd59f97595 | |
|
7bf35e599c | |
|
7412b1a6e1 | |
|
39bfc3b1e1 | |
|
3b414f3197 | |
|
a3c8645c91 | |
|
8d8d4f3803 | |
|
00ddf7af83 | |
|
e2474a6bf1 | |
|
cb53c62391 | |
|
bf603390b6 | |
|
8d7b4e90e6 | |
|
e9b8b37e40 | |
|
05d94420d2 | |
|
8dd856c1e3 | |
|
b4f862ffbe | |
|
8475f864b9 | |
|
1122bf76f4 | |
|
e3a24d3c4e | |
|
77489858d0 | |
|
770949b7d2 | |
|
d5dc82c34b | |
|
d05857a9f3 | |
|
5d9dafbffe | |
|
8dc529f80b | |
|
cc550c47cf | |
|
e5aea14162 | |
|
b033bb5a4f | |
|
6384d079ae | |
|
03079c6bab | |
|
70f96bb8ac | |
|
90626ab4c0 | |
|
0742d9be96 | |
|
582536f922 | |
|
0e150e0a4b | |
|
3d19d9bda3 | |
|
cd24d856e5 | |
|
9a6bb271ec | |
|
1926b3d062 | |
|
61ddbac37a | |
|
0d92f6f401 | |
|
0d9c329de5 | |
|
8815c53e79 | |
|
319462a354 | |
|
a537f9ca2b | |
|
1dd2e43344 | |
|
27110e1655 | |
|
2fd4982e05 | |
|
bf9a70a648 | |
|
c95f77ed2a | |
|
b553a2b2c8 | |
|
05c0fc2bea | |
|
1ba63b39af | |
|
459aa0c0b6 | |
|
407c22d66a | |
|
ff6053a92d | |
|
2b83bac27f | |
|
b95785db32 | |
|
97bd9e0be4 | |
|
3b349a0a73 | |
|
53428b1449 | |
|
ba18c79720 | |
|
d395b6c8d6 | |
|
0e8a754b27 | |
|
09e597ced0 | |
|
462cdc2d9b | |
|
6c17586a9b | |
|
096878d4bc | |
|
e8b18f9387 | |
|
b67289415f | |
|
c48a01c716 | |
|
b3b038bcdb | |
|
e2621f6637 | |
|
59aa11c4dd | |
|
e97a6925aa | |
|
47ccd6c4f3 | |
|
d7d688e2ab | |
|
35eb3a434b | |
|
12f61f01e4 | |
|
f3369409ba | |
|
be3a8a07b6 | |
|
6ee178199c | |
|
d481289397 | |
|
62ca4c7a09 | |
|
075bc9bed4 | |
|
e4d9b3d10f | |
|
ba3bd79a51 | |
|
783d04d0b0 | |
|
1702c8e3c4 | |
|
674a27ad54 | |
|
8eee93f4e9 | |
|
eb17ea77e8 | |
|
63e3e52294 | |
|
2312afce77 | |
|
1937499775 | |
|
c489f7f32a | |
|
c18b0084f7 | |
|
42ed4d8096 | |
|
3cbcc257d6 | |
|
06a18f92cc | |
|
d6ba18a676 | |
|
84f4caf724 | |
|
81169a4d80 | |
|
636eacd895 | |
|
95c2013ea8 | |
|
29fd2eaacc | |
|
04aac41c83 | |
|
cdb15e0a4c | |
|
cbf98fdd23 | |
|
749f755522 | |
|
92856e5627 | |
|
1638f62a14 | |
|
a965c0fe0a | |
|
8dce9bcaa7 | |
|
dacb3ee02e | |
|
2286e87bde | |
|
f4bd1d8ae0 | |
|
8e4acdd35e | |
|
a13056e4ee | |
|
799de30aea | |
|
e937035dae | |
|
2e4d157162 | |
|
82d0653d8e | |
|
82541511e5 | |
|
ca61712d4b | |
|
bbb3c47b4b | |
|
8f7dd2c2b2 | |
|
4775ad973c | |
|
c6c215e321 | |
|
2a6317c272 | |
|
2f852d1b32 | |
|
0f2bdfa605 | |
|
ad6ba2e48a | |
|
b23e16b17e | |
|
9e75491546 | |
|
7e9c878f75 | |
|
3668b5f608 | |
|
ce67f86d45 | |
|
edaad509b5 | |
|
e6856fca51 | |
|
72f41cd064 | |
|
d8d8fe2235 | |
|
ae4c7d927c | |
|
3c1490b351 | |
|
a511cd9301 | |
|
5752e8e9c6 | |
|
2fdca6cc0f | |
|
7a75fecfec | |
|
531af8fd72 | |
|
3fa143ec06 | |
|
8d4a254926 | |
|
362bdf64c8 | |
|
aed23cf9a1 | |
|
c093c38239 | |
|
e5eba96164 | |
|
bda9487aa8 | |
|
6a75f57923 | |
|
e641bba0b5 | |
|
8da75c4909 | |
|
4d96d7d3b0 | |
|
4dbe11376b | |
|
210950ec55 | |
|
a2a97dbd85 | |
|
03a2e24d85 | |
|
f8c54a5698 | |
|
98dac41400 | |
|
5dfa8c076a | |
|
7a46ca51ac | |
|
61508c44ca | |
|
df90a4f680 | |
|
e08155dd0c | |
|
f004ce031b | |
|
3eab5fc25d | |
|
d7c4f1bbb1 | |
|
3e8dc4ddc1 | |
|
3ef5608a05 | |
|
a24a8e3d03 | |
|
9f6a87585a | |
|
64d73de82b | |
|
a1536e5e4a | |
|
d2554649ab | |
|
fdd17a8301 | |
|
bbdd66b0f3 | |
|
6f19506822 | |
|
40eb0eb304 | |
|
9b30089a00 | |
|
5c9cc0b4a0 | |
|
ff97fe2a7c | |
|
f249714bfe | |
|
398610de93 | |
|
c1c7fa5e19 | |
|
4d00523e76 | |
|
3900d52ea5 | |
|
472adbe15d | |
|
2ac73da081 | |
|
74bc6bb2e6 | |
|
75e500bf55 | |
|
044f82850e | |
|
f72b666bd6 | |
|
6bb9a3eafe | |
|
001aadd8ff | |
|
c8cf5dfe97 | |
|
9f7eac80ce | |
|
ac63d528a7 | |
|
d6b1822543 | |
|
75ee35a728 | |
|
a18957db0a | |
|
2e7154ca84 | |
|
d8793d48d9 | |
|
a898fe79e0 | |
|
f7451b1a9a | |
|
1e7dd33251 | |
|
80d0e21481 | |
|
056f3ff744 | |
|
059f788061 | |
|
ef2edc5009 | |
|
698a1d0806 | |
|
0647fc4976 | |
|
2aec66735f | |
|
aa909bdc44 | |
|
a2bc6f6ffd | |
|
91a4ccbf63 | |
|
05a6534c46 | |
|
d3b8847792 | |
|
125e4b6665 | |
|
c8bc46945c | |
|
0857f0c98b | |
|
1997a232dc | |
|
e04ede8f8d | |
|
3db3af91f5 | |
|
619be59d86 | |
|
aed0f9c247 | |
|
a4622de232 | |
|
7276955847 | |
|
feb06f52b0 | |
|
33073d6061 | |
|
b0418f95bb | |
|
e6fa020f78 | |
|
e35f75b5c0 | |
|
9d766ee8b2 | |
|
47a9f37fb9 | |
|
0967035e3e | |
|
17c15023f9 | |
|
98af389ce3 | |
|
98e9d45a70 | |
|
e0354f4dd6 | |
|
46f6f08feb | |
|
276f881e53 | |
|
1a17594eb4 | |
|
6dc929c554 | |
|
6649579eb1 | |
|
527ef6cce6 | |
|
3e7c406f5b | |
|
f594551317 | |
|
f739aa66c1 | |
|
eebea9fcb0 | |
|
e3db53309f | |
|
59940185af | |
|
4787d9c8de | |
|
7c87e0c4b8 | |
|
d72233b458 | |
|
9e489e4e28 | |
|
1aed6e04d3 | |
|
acae72d7fd | |
|
323176e3af | |
|
d77c3bebac | |
|
409cbae9ab | |
|
b5232942ea | |
|
a0b9d358ab | |
|
6292fb7c71 | |
|
cf433243cb | |
|
27c1744d62 | |
|
568d3092ab | |
|
5a2e58441d | |
|
bc1463773b | |
|
e4010db028 | |
|
31bebd1bfc | |
|
c6548e68b7 | |
|
701e258acf | |
|
87a027338e | |
|
7914454763 | |
|
db0a6edf3d | |
|
617e95b6e1 | |
|
ff2757d63d | |
|
8ced6269af | |
|
6b78b7f5c5 | |
|
9beea04064 | |
|
9daaea37be | |
|
6abc5e6527 | |
|
c5fcabab4a | |
|
e0c4d7bf91 | |
|
24ed28b27a | |
|
ba8733e3fd | |
|
1d0d7611b2 | |
|
8f3f718a5a | |
|
940027e366 | |
|
4f48549c8a | |
|
4d73d8d055 | |
|
09537e382d | |
|
1d4dc68aba | |
|
3f20faa4e9 | |
|
508539e119 | |
|
1745bea865 | |
|
f01c709472 | |
|
9bfefd5dba | |
|
8010f88277 | |
|
26da996b98 | |
|
a2d55b0a07 | |
|
475c17161f | |
|
10153edcb1 | |
|
d3c24a22b2 | |
|
c9cdfad8d7 | |
|
5b51bc7f48 | |
|
fc351c0a7c | |
|
100349580a | |
|
1a0b421595 | |
|
ab2bbffb07 | |
|
7bf3e1008b | |
|
cf51602fe4 | |
|
50818214a7 | |
|
a4a4148379 | |
|
e2ea83ca8e | |
|
7e95ca2181 | |
|
fcdafd7d1b | |
|
51f7a70b9a | |
|
e3576d3225 | |
|
267a03c8c8 | |
|
32b9492300 | |
|
0adbbfbf9b | |
|
9ca1b6d709 | |
|
b97d841b34 | |
|
e0a8a2840f | |
|
d2fb76c39d | |
|
acee46ac4f | |
|
76f680e359 | |
|
c684748863 | |
|
6cb76a1c65 | |
|
bd4a334b04 | |
|
c50d9d33e3 | |
|
d04b7ad76a | |
|
0d586b5bd6 | |
|
cfd1358f2d | |
|
822c7d2b32 | |
|
37285a053a | |
|
fe9e0577a9 | |
|
69aaed9c77 | |
|
17bf178f02 | |
|
e2d8e273d1 | |
|
fdfa1f4e65 | |
|
6b7708f19e | |
|
df0c0c6fc6 | |
|
a700b89b10 | |
|
5caabf2087 | |
|
73c08a9f11 | |
|
00dabe3242 | |
|
2f3a04845e | |
|
ca64536ca7 | |
|
bcaaebf9c6 | |
|
c252c4f537 | |
|
8e56c521bd | |
|
e6c53eb083 | |
|
8107d7167f | |
|
443b8f3d55 | |
|
6c3221381b | |
|
e4430de1f2 | |
|
8ecf77d4c4 | |
|
b29f702d79 | |
|
98e5b255ea | |
|
2ebaf5739e | |
|
7f44e712b3 | |
|
152d00901b | |
|
cc0121f118 | |
|
d57c454453 | |
|
4daa88531d | |
|
32f6d8de7d | |
|
b9c11c3a5f | |
|
c4d0bc6ca1 | |
|
76fde174de | |
|
9f1568cf9f | |
|
fa77c2897d | |
|
7ebf92dc5b | |
|
284da86f51 | |
|
890ba933a0 | |
|
a8bbec33e7 | |
|
623c61ff93 | |
|
f8a428464a | |
|
d3821fb74c | |
|
6f0b90d8aa | |
|
e5f7fa7db3 | |
|
39155b73b6 | |
|
ad9d9d676a | |
|
7199c0edcd | |
|
5335347a48 | |
|
d526272b8d | |
|
7af58b5eb4 | |
|
c949e00207 | |
|
4a2150595c | |
|
feaa62df91 | |
|
5bb373ab2c | |
|
d258a19cda | |
|
e7e9b182b9 | |
|
ad38c17888 | |
|
63490e591e | |
|
ff7dca41f4 | |
|
983e1d8da9 | |
|
a4680b28d7 | |
|
bc1acd1ff3 | |
|
b1b329e639 | |
|
1d94c1afb7 | |
|
7fa331b544 | |
|
cd0bc6ae1e | |
|
487704d41f | |
|
2806882090 | |
|
6a2db8e3c7 | |
|
d65b812266 | |
|
a3ac5e7248 | |
|
6c6730f324 | |
|
b24688723e | |
|
425591b9b0 | |
|
714d5e3fd2 | |
|
5977313e67 | |
|
335de806e7 | |
|
22c807b7c5 | |
|
00591fd1c9 | |
|
4deb1ff219 | |
|
87e9fb3cb9 | |
|
84ad7d7f17 | |
|
3641bfe5d0 | |
|
788f18c61f | |
|
f83c0ee3f5 | |
|
7b09bcd431 | |
|
429d379280 | |
|
9cf1ed7762 | |
|
f832e85646 | |
|
358a816354 | |
|
a7c15586ca | |
|
5ffdf756ae | |
|
b6fb8800d6 | |
|
975cc91b46 | |
|
e7c9695a4f | |
|
8e660e1c21 | |
|
b4ab0cf5bf | |
|
cdcbd0af0f | |
|
4968665e01 | |
|
452ff50418 | |
|
812855a1e9 | |
|
df97bd79e7 | |
|
fb39429496 | |
|
4cbba4a8de | |
|
68f357561b | |
|
a4e4885d6e | |
|
26614eb001 | |
|
97291a4422 | |
|
85ef88d86b | |
|
bcfb83cba4 | |
|
7a7e4bf24a | |
|
1e271ae15f | |
|
60e0c71843 | |
|
1ff01a30ba | |
|
549aee4648 | |
|
4af9c39e36 | |
|
922413464f | |
|
d0fe80c408 | |
|
ae4ccc1786 | |
|
e04c1392c1 | |
|
5135a9205b | |
|
da658c13db | |
|
e4a3b3a633 | |
|
ec6ee77f5a | |
|
49278270ab | |
|
1163a5e5ae | |
|
c8abe3e307 | |
|
718948a3d8 | |
|
67517b738e | |
|
b98bb9bdcd | |
|
cea6ca4039 | |
|
de344241e5 | |
|
efb04bef0f | |
|
399ab7dd17 | |
|
89cf6b7a06 | |
|
a2b7d2c932 | |
|
20a4eb2ba0 | |
|
45d242633a | |
|
e232dc7d66 | |
|
a74e1d73c4 | |
|
c9b0176f01 | |
|
4e0db21b34 | |
|
fe08004b3f | |
|
8630175fc4 | |
|
7ec31cf0a7 | |
|
c565af9393 | |
|
e13d0296f3 | |
|
fc2c04550d | |
|
f183c92b16 | |
|
6eac0d0605 | |
|
2463202f11 | |
|
24fe6d36fa |
|
@ -55,4 +55,4 @@
|
|||
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
|
|
@ -37,4 +37,4 @@ options:
|
|||
- Header
|
||||
notes:
|
||||
keywords:
|
||||
- BREAKING CHANGE
|
||||
- BREAKING CHANGE
|
||||
|
|
|
@ -16,10 +16,12 @@ comment:
|
|||
behavior: default
|
||||
ignore:
|
||||
- "testdata"
|
||||
- "**/zz_*generated*.go"
|
||||
- "**/zz*_generated.go"
|
||||
- "templates"
|
||||
- "hack"
|
||||
- "test"
|
||||
- "generate"
|
||||
- "docs"
|
||||
- "plugin"
|
||||
- "schema"
|
||||
- "third_party"
|
||||
- "vendor"
|
||||
|
||||
|
|
|
@ -5,4 +5,5 @@ templates/typescript/*/package-lock.json ignore-lint=true
|
|||
version.txt linguist-generated=true
|
||||
zz_filesystem_generated.go linguist-generated=true
|
||||
docker/zz_close_guarding_client_generated.go linguist-generated=true
|
||||
pkg/oci/testdata/test-links/* ignore-lint=true
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
name: Func Build
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install Bash 4 on Mac
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
brew update
|
||||
|
||||
brew install bash
|
||||
brew install gnu-sed
|
||||
|
||||
echo "/usr/local/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Build
|
||||
run: make build
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
name: Func Check Source
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check Source
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Check
|
||||
run: make check
|
||||
|
|
@ -8,10 +8,8 @@ jobs:
|
|||
check:
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.20.2"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Lint
|
||||
run: make check && make check-templates
|
||||
- name: Check that 'func.yaml schema' is up-to-date
|
||||
|
@ -22,151 +20,243 @@ jobs:
|
|||
test-unit:
|
||||
strategy:
|
||||
matrix:
|
||||
go: [ 1.20.2 ]
|
||||
java: [ 17 ]
|
||||
java: [ 21 ]
|
||||
os: [ "ubuntu-latest", "windows-latest", "macos-latest" ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: git config --global core.autocrlf false
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'temurin'
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Unit Test
|
||||
run: make test
|
||||
- name: Template Unit Tests
|
||||
run: make test-templates
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: unit-tests-${{ matrix.os }}
|
||||
flags: unit-tests
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
test-integration:
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.20.2"
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Integration Tests
|
||||
run: make test-integration
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: integration-tests
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
e2e-test:
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: E2E Test
|
||||
run: make test-e2e
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: e2e-test
|
||||
flags: e2e-tests
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
e2e-on-cluster-test:
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: imjasonh/setup-ko@v0.6
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
- name: Setup testing func image
|
||||
run: ./hack/create-testing-func-image.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
- name: Deploy Tekton
|
||||
run: ./hack/tekton.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Deploy Test Git Server
|
||||
run: ./test/gitserver.sh
|
||||
run: ./hack/install-git-server.sh
|
||||
- name: E2E On Cluster Test
|
||||
env:
|
||||
E2E_RUNTIMES: ""
|
||||
run: make test-e2e-on-cluster
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: e2e-test-oncluster
|
||||
flags: e2e-tests
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
build:
|
||||
needs: [check, test-unit, test-integration, e2e-test, e2e-on-cluster-test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.20.2"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
# Standard build tasks
|
||||
- name: Build
|
||||
run: make cross-platform
|
||||
# Upload all build artifacts
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OSX Binary (AMD)
|
||||
path: func_darwin_amd64
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OSX Binary (ARM)
|
||||
path: func_darwin_arm64
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux Binary (AMD)
|
||||
path: func_linux_amd64
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux Binary (ARM)
|
||||
path: func_linux_arm64
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux Binary (PPC64LE)
|
||||
path: func_linux_ppc64le
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux Binary (S390X)
|
||||
path: func_linux_s390x
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows Binary
|
||||
path: func_windows_amd64.exe
|
||||
|
||||
publish-utils-image:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
run: |
|
||||
for a in amd64 arm64 ppc64le s390x; do
|
||||
CGO_ENABLED=0 GOARCH="$a" go build -o "func-util-$a" -trimpath -ldflags '-w -s' ./cmd/func-util
|
||||
done
|
||||
docker buildx create --name multiarch --driver docker-container --use
|
||||
docker buildx build . -f Dockerfile.utils \
|
||||
--platform=linux/ppc64le,linux/s390x,linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
-t "ghcr.io/knative/func-utils:v2" \
|
||||
--annotation index:org.opencontainers.image.description="Knative Func Utils Image" \
|
||||
--annotation index:org.opencontainers.image.source="https://github.com/knative/func" \
|
||||
--annotation index:org.opencontainers.image.vendor="https://github.com/knative/func" \
|
||||
--annotation index:org.opencontainers.image.url="https://github.com/knative/func/pkgs/container/func-utils"
|
||||
|
||||
publish-image:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.20.2"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: imjasonh/setup-ko@v0.6
|
||||
- run: ko build -B ./cmd/func
|
||||
- run: ko build --platform=linux/ppc64le,linux/s390x,linux/amd64,linux/arm64 -B ./cmd/func
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright 2020 The Knative Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This file is automagically synced here from github.com/knative-sandbox/knobots
|
||||
# This file is automagically synced here from github.com/knative-extensions/knobots
|
||||
|
||||
name: Build
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright 2022 The Knative Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This file is automagically synced here from github.com/knative-sandbox/knobots
|
||||
# This file is automagically synced here from github.com/knative-extensions/knobots
|
||||
|
||||
name: Test
|
||||
|
||||
|
@ -15,3 +15,5 @@ on:
|
|||
jobs:
|
||||
test:
|
||||
uses: knative/actions/.github/workflows/reusable-go-test.yaml@main
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright 2020 The Knative Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This file is automagically synced here from github.com/knative-sandbox/knobots
|
||||
# This file is automagically synced here from github.com/knative-extensions/knobots
|
||||
|
||||
name: 'Security'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright 2020 The Knative Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This file is automagically synced here from github.com/knative-sandbox/knobots
|
||||
# This file is automagically synced here from github.com/knative-extensions/knobots
|
||||
name: 'Close stale'
|
||||
|
||||
on:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright 2020 The Knative Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# This file is automagically synced here from github.com/knative-sandbox/knobots
|
||||
# This file is automagically synced here from github.com/knative-extensions/knobots
|
||||
|
||||
name: Code Style
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This file is automagically synced here from github.com/knative-sandbox/.github
|
||||
# repo by knobots: https://github.com/knative-sandbox/knobots and will be overwritten.
|
||||
# This file is automagically synced here from github.com/knative-extensions/.github
|
||||
# repo by knobots: https://github.com/knative-extensions/knobots and will be overwritten.
|
||||
|
||||
name: Verify
|
||||
|
||||
|
|
|
@ -7,13 +7,10 @@ jobs:
|
|||
name: Check Schema
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Check that 'func.yaml schema' is up-to-date
|
||||
run: make schema-check
|
||||
|
|
|
@ -5,32 +5,60 @@ on: [pull_request]
|
|||
jobs:
|
||||
test:
|
||||
name: On Cluster RT Test
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
func_builder: ["pack", "s2i"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: imjasonh/setup-ko@v0.6
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
- name: Setup testing func image
|
||||
run: ./hack/create-testing-func-image.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
- name: Deploy Tekton
|
||||
run: ./hack/tekton.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Deploy Test Git Server
|
||||
run: ./test/gitserver.sh
|
||||
run: ./hack/install-git-server.sh
|
||||
- name: E2E On Cluster Test (Runtimes)
|
||||
env:
|
||||
TEST_TAGS: runtime
|
||||
E2E_REGISTRY_URL: registry.default.svc.cluster.local:5000
|
||||
FUNC_REPO_REF: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
FUNC_REPO_BRANCH_REF: ${{ github.head_ref }}
|
||||
FUNC_BUILDER: ${{ matrix.func_builder }}
|
||||
run: make test-e2e-on-cluster
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: e2e-test-oncluster-runtime
|
||||
- name: Dump Cluster Logs
|
||||
if: always()
|
||||
run: |
|
||||
echo "::group::cluster events"
|
||||
kubectl get events -A
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::cluster containers logs"
|
||||
stern '.*' --all-namespaces --no-follow
|
||||
echo "::endgroup::"
|
||||
|
|
|
@ -7,30 +7,49 @@ jobs:
|
|||
name: On Cluster Test
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: imjasonh/setup-ko@v0.6
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
- name: Setup testing func image
|
||||
run: ./hack/create-testing-func-image.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
- name: Deploy Tekton
|
||||
run: ./hack/tekton.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Deploy Test Git Server
|
||||
run: ./test/gitserver.sh
|
||||
run: ./hack/install-git-server.sh
|
||||
- name: E2E On Cluster Test
|
||||
env:
|
||||
E2E_RUNTIMES: ""
|
||||
E2E_REGISTRY_URL: registry.default.svc.cluster.local:5000
|
||||
FUNC_REPO_REF: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
FUNC_REPO_BRANCH_REF: ${{ github.head_ref }}
|
||||
run: make test-e2e-on-cluster
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: e2e-test-oncluster
|
||||
flags: e2e-tests
|
||||
|
|
|
@ -9,26 +9,70 @@ concurrency:
|
|||
jobs:
|
||||
test:
|
||||
name: E2E Test
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
runtime: ["node", "go", "python", "quarkus", "springboot", "typescript"]
|
||||
runs-on: ubuntu-latest
|
||||
os: [ "ubuntu-latest", "ubuntu-24.04-arm" ]
|
||||
runtime: ["go", "quarkus"]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
runtime: node
|
||||
- os: ubuntu-latest
|
||||
runtime: typescript
|
||||
- os: ubuntu-latest
|
||||
runtime: springboot
|
||||
- os: ubuntu-latest
|
||||
runtime: rust
|
||||
- os: ubuntu-24.04-arm
|
||||
arch: arm64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.20.2
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt for ${{matrix.runtime}} ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: Build
|
||||
run: make
|
||||
- name: E2E runtime for ${{ matrix.runtime }}
|
||||
run: make test-e2e-runtime runtime=${{ matrix.runtime }}
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: e2e-test-runtime-${{ matrix.runtime }}
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt for ${{matrix.runtime}} ------------------"
|
||||
make test-e2e-runtime runtime=${{ matrix.runtime }} && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
|
|
|
@ -7,23 +7,41 @@ jobs:
|
|||
name: E2E Test
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: E2E Test
|
||||
run: make test-e2e
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: e2e-test
|
||||
flags: e2e-tests
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
name: Func Embedded FS Test
|
||||
name: Func Check Embedded FS
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Func Embedded FS Test
|
||||
name: Func Check Embedded FS
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Check embedded templates content
|
||||
run: |
|
||||
if ! go test -run "^\QTestFileSystems\E$/^\Qembedded\E$" ./pkg/filesystem; then
|
||||
if ! make check-embedded-fs; then
|
||||
echo "Content of templates directory and embedded FS (zz_filesystem_generated.go) doesn't match!"
|
||||
echo "Consult https://github.com/knative/func/blob/main/docs/CONTRIBUTING.md#templates ."
|
||||
echo "Consult https:.github.com/knative/func/blob/main/docs/CONTRIBUTING.md#templates ."
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
@ -7,53 +7,78 @@ jobs:
|
|||
name: Integration Test
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- uses: imjasonh/setup-ko@v0.6
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
- name: Setup testing func image
|
||||
run: ./hack/create-testing-func-image.sh
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
- name: Patch S2I Task
|
||||
run: ./hack/patch-s2i-task.sh
|
||||
- name: Install Tekton
|
||||
run: ./hack/tekton.sh
|
||||
- name: Set up environment variables
|
||||
- name: Remove Unnecessary Software
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet || true
|
||||
sudo rm -rf /usr/local/lib/android || true
|
||||
sudo rm -rf /opt/ghc || true
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
echo "TEKTON_TESTS_ENABLED=1" >> "$GITHUB_ENV"
|
||||
echo "GITLAB_TESTS_ENABLED=1" >> "$GITHUB_ENV"
|
||||
echo "GITLAB_HOSTNAME=gitlab.127.0.0.1.sslip.io" >> "$GITHUB_ENV"
|
||||
echo "GITLAB_HOSTNAME=gitlab.localtest.me" >> "$GITHUB_ENV"
|
||||
echo "GITLAB_ROOT_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32})" >> "$GITHUB_ENV"
|
||||
echo "PAC_CONTROLLER_HOSTNAME=pac-ctr.127.0.0.1.sslip.io" >> "$GITHUB_ENV"
|
||||
- name: Install Pipelines as Code
|
||||
run: ./hack/install-pac.sh
|
||||
echo "PAC_CONTROLLER_HOSTNAME=pac-ctr.localtest.me" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: imjasonh/setup-ko@v0.6
|
||||
- name: Install Binaries
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Install Gitlab
|
||||
run: ./hack/install-gitlab.sh
|
||||
- name: Patch Hosts
|
||||
run: ./hack/patch-hosts.sh
|
||||
- name: Integration Test
|
||||
env:
|
||||
FUNC_REPO_REF: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
FUNC_REPO_BRANCH_REF: ${{ github.head_ref }}
|
||||
run: make test-integration
|
||||
- name: Dump Cluster Logs
|
||||
if: always()
|
||||
run: |
|
||||
echo "::group::cluster events"
|
||||
kubectl get events -A
|
||||
echo "::endgroup::"
|
||||
echo "::group::cluster events" >> cluster_log.txt
|
||||
kubectl get events -A >> cluster_log.txt 2>&1
|
||||
echo "::endgroup::" >> cluster_log.txt
|
||||
|
||||
echo "::group::cluster containers logs"
|
||||
stern '.*' --all-namespaces --no-follow
|
||||
echo "::endgroup::"
|
||||
- uses: codecov/codecov-action@v3
|
||||
echo "::group::cluster containers logs" >> cluster_log.txt
|
||||
stern '.*' --all-namespaces --no-follow >> cluster_log.txt 2>&1
|
||||
echo "::endgroup::" >> cluster_log.txt
|
||||
- name: "Archive log results"
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cluster-logs
|
||||
path: ./cluster_log.txt
|
||||
retention-days: 7
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: integration-tests
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
name: Func Podman Next Test
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Podman Next Test
|
||||
strategy:
|
||||
matrix:
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Remove Unnecessary Software
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet || true
|
||||
sudo rm -rf /usr/local/lib/android || true
|
||||
sudo rm -rf /opt/ghc || true
|
||||
- name: Install Podman Next (Nightly Build)
|
||||
env:
|
||||
FEDORA_RELEASE: 41
|
||||
BASE_ARCH: x86_64
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo mkdir -p /etc/yum.repos.d
|
||||
sudo apt install dnf -y
|
||||
sudo apt install dnf-plugins-core -y
|
||||
sudo apt install alien -y
|
||||
sudo touch /etc/yum.repos.d/fedora.repo
|
||||
sudo chmod 666 /etc/yum.repos.d/fedora.repo
|
||||
cat << EOF >> /etc/yum.repos.d/fedora.repo
|
||||
[fedora]
|
||||
name=Fedora $FEDORA_RELEASE
|
||||
metalink=https://mirrors.fedoraproject.org/metalink?repo=fedora-$FEDORA_RELEASE&arch=$BASE_ARCH
|
||||
enabled=1
|
||||
countme=1
|
||||
metadata_expire=7d
|
||||
repo_gpgcheck=0
|
||||
type=rpm
|
||||
gpgcheck=0
|
||||
EOF
|
||||
sudo chmod 644 /etc/yum.repos.d/fedora.repo
|
||||
sudo dnf copr enable rhcontainerbot/podman-next fedora-$FEDORA_RELEASE-$BASE_ARCH --releasever=$FEDORA_RELEASE -y
|
||||
sudo dnf download crun conmon podman --releasever=$FEDORA_RELEASE -y
|
||||
sudo alien --to-deb $(ls -1 crun*.rpm) --install
|
||||
sudo alien --to-deb $(ls -1 conmon*.rpm) --install
|
||||
sudo alien --to-deb $(ls -1 podman*.rpm) --install
|
||||
podman info
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Install Binaries
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Integration Test Podman
|
||||
env:
|
||||
FUNC_REPO_REF: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
FUNC_REPO_BRANCH_REF: ${{ github.head_ref }}
|
||||
run: ./hack/test-integration-podman.sh
|
|
@ -7,35 +7,48 @@ jobs:
|
|||
name: Podman Test
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
os: ["ubuntu-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- name: Set Environment Variables
|
||||
run: |
|
||||
echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
|
||||
echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Install Podman
|
||||
run: |
|
||||
# TODO uncomment following once https://github.com/containers/podman/pull/16781 is in the kubic repository
|
||||
#. /etc/os-release
|
||||
#sudo mkdir -p /etc/apt/keyrings
|
||||
#curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_${VERSION_ID}/Release.key \
|
||||
# | gpg --dearmor \
|
||||
# | sudo tee /etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg > /dev/null
|
||||
#echo \
|
||||
# "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg]\
|
||||
# https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_${VERSION_ID}/ /" \
|
||||
# | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list > /dev/null
|
||||
#sudo apt-get update -qq
|
||||
sudo apt-get -qq -y install podman
|
||||
sudo apt update
|
||||
sudo apt install podman -y
|
||||
podman info
|
||||
- name: Install Binaries
|
||||
run: ./hack/binaries.sh
|
||||
run: ./hack/install-binaries.sh
|
||||
- name: Allocate Cluster
|
||||
run: ./hack/allocate.sh
|
||||
run: |
|
||||
attempt=0
|
||||
max_attempts=5
|
||||
until [ $attempt -ge $max_attempts ]
|
||||
do
|
||||
attempt=$((attempt+1))
|
||||
echo "------------------ Attempt $attempt ------------------"
|
||||
./hack/allocate.sh && break
|
||||
echo "------------------ failed, retrying... ------------------"
|
||||
if [ $attempt -ge $max_attempts ]; then
|
||||
echo "------------------ max # of retries reached, exiting ------------------"
|
||||
exit 1
|
||||
fi
|
||||
./hack/delete.sh
|
||||
echo "------------------ sleep for 5 minutes ------------------"
|
||||
sleep 300
|
||||
done
|
||||
echo "------------------ finished! attempt $attempt ------------------"
|
||||
- name: Local Registry
|
||||
run: ./hack/registry.sh
|
||||
- name: Setup testing images
|
||||
run: ./hack/setup-testing-images.sh
|
||||
- name: Integration Test Podman
|
||||
env:
|
||||
FUNC_REPO_REF: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
FUNC_REPO_BRANCH_REF: ${{ github.head_ref }}
|
||||
run: ./hack/test-integration-podman.sh
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@ jobs:
|
|||
name: Unit Test
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.20.2]
|
||||
java: [17]
|
||||
java: [21]
|
||||
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
@ -24,18 +23,28 @@ jobs:
|
|||
echo "/usr/local/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
|
||||
- run: git config --global core.autocrlf false
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'temurin'
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- name: Core Unit Tests
|
||||
run: make test
|
||||
env:
|
||||
FUNC_REPO_REF: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
FUNC_REPO_BRANCH_REF: ${{ github.head_ref }}
|
||||
- name: Template Unit Tests on Ubuntu
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
python3 -m venv ${{ github.workspace }}/.venv
|
||||
. ${{ github.workspace }}/.venv/bin/activate
|
||||
make test-templates
|
||||
- name: Template Unit Tests
|
||||
if: matrix.os != 'ubuntu-latest'
|
||||
run: make test-templates
|
||||
- uses: codecov/codecov-action@v3
|
||||
- uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
flags: unit-tests-${{ matrix.os }}
|
||||
flags: unit-tests
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
name: Update builder-jammy-full image
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 * * * *'
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Build and Push
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
docker run -d -p 5000:5000 --name registry registry:2.7
|
||||
echo '{"insecure-registries" : "localhost:5000" }' | \
|
||||
sudo tee /etc/docker/daemon.json
|
||||
mkdir -p "$HOME/.config/containers/"
|
||||
echo -e '\n[[registry]]\nlocation = "localhost:5000"\ninsecure = true\n' >> \
|
||||
"$HOME/.config/containers/registries.conf"
|
||||
skopeo login ghcr.io -u gh-action -p "$GITHUB_TOKEN"
|
||||
docker login ghcr.io -u gh-action -p "$GITHUB_TOKEN"
|
||||
make __update-builder
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
name: Update CA bundle in embedded templates
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */4 * * *'
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: Update CA bundle
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install NPM deps.
|
||||
run: npm install octokit@3.2.1
|
||||
- name: Create PR
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: node ./hack/update-ca-bundle.js
|
||||
|
|
@ -13,15 +13,17 @@ jobs:
|
|||
name: Update Quarkus Platform
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
distribution: 'temurin'
|
||||
- name: Install NPM deps.
|
||||
run: npm install axios xml2js octokit
|
||||
run: npm install xml2js octokit@3.2.1
|
||||
- name: Create PR
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
|
|
@ -13,15 +13,17 @@ jobs:
|
|||
name: Update Spring Boot Platform
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: actions/setup-java@v1
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
distribution: 'temurin'
|
||||
- name: Install NPM deps.
|
||||
run: npm install axios xml2js octokit
|
||||
run: npm install xml2js octokit@3.2.1 yaml semver
|
||||
- name: Create PR
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
|
|
@ -2,31 +2,39 @@
|
|||
/func
|
||||
/func_*
|
||||
/cmd/func.yaml
|
||||
/templates/typescript/cloudevents/build
|
||||
/templates/typescript/http/build
|
||||
/templates/go/cloudevents/go.sum
|
||||
/coverage.out
|
||||
/coverage.txt
|
||||
/.coverage
|
||||
/bin
|
||||
/target
|
||||
/hack/bin
|
||||
/.artifacts
|
||||
|
||||
# Nodejs
|
||||
/pkg/functions/testdata/migrations/*/.gitignore
|
||||
/pkg/functions/testdata/default_home/go
|
||||
/pkg/functions/testdata/default_home/.cache
|
||||
/pkg/functions/testdata/migrations/*/.gitignore
|
||||
|
||||
# Go
|
||||
/templates/go/cloudevents/go.sum
|
||||
|
||||
# JS
|
||||
node_modules
|
||||
/templates/typescript/cloudevents/build
|
||||
/templates/typescript/http/build
|
||||
|
||||
# Python
|
||||
__pycache__
|
||||
/templates/python/cloudevents/.venv
|
||||
/templates/python/http/.venv
|
||||
|
||||
# VSCode
|
||||
# E2E Tests
|
||||
/e2e/testdata/default_home/go
|
||||
/e2e/testdata/default_home/.cache
|
||||
|
||||
# Editors
|
||||
.vscode
|
||||
|
||||
# IntelliJ
|
||||
.idea
|
||||
|
||||
# Operating system temporary files
|
||||
.DS_Store
|
||||
|
||||
# Non relevant vendor files
|
||||
BUILD.bazel
|
||||
OWNERS
|
||||
OWNERS_ALIASES
|
||||
|
|
|
@ -1,31 +1,37 @@
|
|||
#
|
||||
# golangci-lint
|
||||
#
|
||||
# For defaults, see:
|
||||
# https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
|
||||
#
|
||||
#
|
||||
#
|
||||
run:
|
||||
timeout: 5m
|
||||
|
||||
version: "2"
|
||||
linters:
|
||||
enable:
|
||||
- unconvert
|
||||
- prealloc
|
||||
- bodyclose
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
- linters:
|
||||
- staticcheck
|
||||
# Error Text:
|
||||
# "SA9004: only the first constant in this group has an explicit type"
|
||||
# Efect:
|
||||
# Allows short-hand first constant type declarations:
|
||||
# Example:
|
||||
# const (
|
||||
# Name Type = "value"
|
||||
# Name2 = "value2"
|
||||
# )
|
||||
text: "SA9004:"
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- linters:
|
||||
- staticcheck
|
||||
# Error Text:
|
||||
# "SA9004: only the first constant in this group has an explicit type"
|
||||
# Efect:
|
||||
# Allows short-hand first constant type declarations:
|
||||
# Example:
|
||||
# const (
|
||||
# Name Type = "value"
|
||||
# Name2 = "value2"
|
||||
# )
|
||||
text: 'SA9004:'
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
scan_exclude = [
|
||||
# Readme in vendor dir line=17,title=unicode control characters ['\u200d']
|
||||
r'vendor/github\.com/rivo/uniseg/README\.md',
|
||||
# doc.go in vendor dir line=34,title=unicode control characters ['\u200d']
|
||||
r'./vendor/github\.com/rivo/uniseg/doc\.go']
|
||||
]
|
||||
|
|
562
CHANGELOG.md
562
CHANGELOG.md
|
@ -2,131 +2,131 @@
|
|||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [0.26.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.25.0...v0.26.0) (2022-08-26)
|
||||
## [0.26.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.25.0...v0.26.0) (2022-08-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add OpenShift related Annotations & Labels ([#1106](https://github.com/knative-sandbox/kn-plugin-func/issues/1106)) ([b4b4cc3](https://github.com/knative-sandbox/kn-plugin-func/commit/b4b4cc34c3b32ad5f00d90ee8244702bef9e3673))
|
||||
* add runtime icons on OpenShift ([#1116](https://github.com/knative-sandbox/kn-plugin-func/issues/1116)) ([a7671e4](https://github.com/knative-sandbox/kn-plugin-func/commit/a7671e45a791b88bed464becc79d419ed8eb803c))
|
||||
* always store namespace in func.yaml and warn if current ns & func.yaml ns is different ([#1118](https://github.com/knative-sandbox/kn-plugin-func/issues/1118)) ([8cb7080](https://github.com/knative-sandbox/kn-plugin-func/commit/8cb70808f59dc0a4e19fc7d1b2f1ff3389bed4f2))
|
||||
* build for Linux ARM64 ([#1123](https://github.com/knative-sandbox/kn-plugin-func/issues/1123)) ([819b433](https://github.com/knative-sandbox/kn-plugin-func/commit/819b433edbb313f4119d88cdf066b48813333a27))
|
||||
* deploy Tekton task supports optional `image` parameter ([#1140](https://github.com/knative-sandbox/kn-plugin-func/issues/1140)) ([65c30ab](https://github.com/knative-sandbox/kn-plugin-func/commit/65c30abb39e05eaa6b4ebf9ba25d5cdfc0971cee))
|
||||
* func deploy accepts image digest in --image ([#1098](https://github.com/knative-sandbox/kn-plugin-func/issues/1098)) ([c57af36](https://github.com/knative-sandbox/kn-plugin-func/commit/c57af36f7413e670d44f5111acd477e733aea2e4))
|
||||
* languages list command ([#1114](https://github.com/knative-sandbox/kn-plugin-func/issues/1114)) ([d1f935f](https://github.com/knative-sandbox/kn-plugin-func/commit/d1f935fde991639c80b369797733e9e48b82805e))
|
||||
* persist builder value in func.yaml ([#1099](https://github.com/knative-sandbox/kn-plugin-func/issues/1099)) ([b1fd9f7](https://github.com/knative-sandbox/kn-plugin-func/commit/b1fd9f71b16bd5d83d37cbaed47890775886d807))
|
||||
* S2I strategy for on cluster build ([#1191](https://github.com/knative-sandbox/kn-plugin-func/issues/1191)) ([1112aaa](https://github.com/knative-sandbox/kn-plugin-func/commit/1112aaa2fe5fb5aa349251a34c2fccc529498b0d))
|
||||
* templates list command ([#1134](https://github.com/knative-sandbox/kn-plugin-func/issues/1134)) ([2f8d82b](https://github.com/knative-sandbox/kn-plugin-func/commit/2f8d82bec283ad29e67bdeaef80f039d87f1a523))
|
||||
* add OpenShift related Annotations & Labels ([#1106](https://github.com/knative-extensions/kn-plugin-func/issues/1106)) ([b4b4cc3](https://github.com/knative-extensions/kn-plugin-func/commit/b4b4cc34c3b32ad5f00d90ee8244702bef9e3673))
|
||||
* add runtime icons on OpenShift ([#1116](https://github.com/knative-extensions/kn-plugin-func/issues/1116)) ([a7671e4](https://github.com/knative-extensions/kn-plugin-func/commit/a7671e45a791b88bed464becc79d419ed8eb803c))
|
||||
* always store namespace in func.yaml and warn if current ns & func.yaml ns is different ([#1118](https://github.com/knative-extensions/kn-plugin-func/issues/1118)) ([8cb7080](https://github.com/knative-extensions/kn-plugin-func/commit/8cb70808f59dc0a4e19fc7d1b2f1ff3389bed4f2))
|
||||
* build for Linux ARM64 ([#1123](https://github.com/knative-extensions/kn-plugin-func/issues/1123)) ([819b433](https://github.com/knative-extensions/kn-plugin-func/commit/819b433edbb313f4119d88cdf066b48813333a27))
|
||||
* deploy Tekton task supports optional `image` parameter ([#1140](https://github.com/knative-extensions/kn-plugin-func/issues/1140)) ([65c30ab](https://github.com/knative-extensions/kn-plugin-func/commit/65c30abb39e05eaa6b4ebf9ba25d5cdfc0971cee))
|
||||
* func deploy accepts image digest in --image ([#1098](https://github.com/knative-extensions/kn-plugin-func/issues/1098)) ([c57af36](https://github.com/knative-extensions/kn-plugin-func/commit/c57af36f7413e670d44f5111acd477e733aea2e4))
|
||||
* languages list command ([#1114](https://github.com/knative-extensions/kn-plugin-func/issues/1114)) ([d1f935f](https://github.com/knative-extensions/kn-plugin-func/commit/d1f935fde991639c80b369797733e9e48b82805e))
|
||||
* persist builder value in func.yaml ([#1099](https://github.com/knative-extensions/kn-plugin-func/issues/1099)) ([b1fd9f7](https://github.com/knative-extensions/kn-plugin-func/commit/b1fd9f71b16bd5d83d37cbaed47890775886d807))
|
||||
* S2I strategy for on cluster build ([#1191](https://github.com/knative-extensions/kn-plugin-func/issues/1191)) ([1112aaa](https://github.com/knative-extensions/kn-plugin-func/commit/1112aaa2fe5fb5aa349251a34c2fccc529498b0d))
|
||||
* templates list command ([#1134](https://github.com/knative-extensions/kn-plugin-func/issues/1134)) ([2f8d82b](https://github.com/knative-extensions/kn-plugin-func/commit/2f8d82bec283ad29e67bdeaef80f039d87f1a523))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add languages command to cmd root ([#1127](https://github.com/knative-sandbox/kn-plugin-func/issues/1127)) ([59df756](https://github.com/knative-sandbox/kn-plugin-func/commit/59df756e49eda6717d82caf8c8f54422fc79fcb0))
|
||||
* correct error in OpenShift reg.cred.provider ([#1104](https://github.com/knative-sandbox/kn-plugin-func/issues/1104)) ([a197f8b](https://github.com/knative-sandbox/kn-plugin-func/commit/a197f8b330d6f5fdbc9c16585e605cdf74f9b8b9))
|
||||
* ensure registry in func.yaml is respected ([#1168](https://github.com/knative-sandbox/kn-plugin-func/issues/1168)) ([80657c9](https://github.com/knative-sandbox/kn-plugin-func/commit/80657c90e3df49bd4a55c61ada0cbadbdff7a56d))
|
||||
* image push authorization check ([#1109](https://github.com/knative-sandbox/kn-plugin-func/issues/1109)) ([3b198cb](https://github.com/knative-sandbox/kn-plugin-func/commit/3b198cb78164e751d293edc6467907cecd626643))
|
||||
* image push authorization check ([#1130](https://github.com/knative-sandbox/kn-plugin-func/issues/1130)) ([36216e7](https://github.com/knative-sandbox/kn-plugin-func/commit/36216e7fed34d3cd20aed951a27ed5fdf995bafb))
|
||||
* performance of template loading ([#1189](https://github.com/knative-sandbox/kn-plugin-func/issues/1189)) ([dca11da](https://github.com/knative-sandbox/kn-plugin-func/commit/dca11dad5bfefeb05b0d3ea2a88bc4f9b159a2b7))
|
||||
* stop build progress loop when build completes ([#1133](https://github.com/knative-sandbox/kn-plugin-func/issues/1133)) ([cf5be9a](https://github.com/knative-sandbox/kn-plugin-func/commit/cf5be9a6161085a92f60d5345b15e8d394d69f0f))
|
||||
* use 0 group id for func-buildpacks Task ([#1105](https://github.com/knative-sandbox/kn-plugin-func/issues/1105)) ([f4537dd](https://github.com/knative-sandbox/kn-plugin-func/commit/f4537dd3d5d5130c27ad8c1d1ff0df92569fbc25))
|
||||
* use creds from creds store first ([#1103](https://github.com/knative-sandbox/kn-plugin-func/issues/1103)) ([e1d5229](https://github.com/knative-sandbox/kn-plugin-func/commit/e1d522990016f46beff26117f8b80ee16b098402))
|
||||
* use space prefix for deploy output text ([#1144](https://github.com/knative-sandbox/kn-plugin-func/issues/1144)) ([3b8c240](https://github.com/knative-sandbox/kn-plugin-func/commit/3b8c24092b0e3c7863715ec9b96c8a86b10af245))
|
||||
* add languages command to cmd root ([#1127](https://github.com/knative-extensions/kn-plugin-func/issues/1127)) ([59df756](https://github.com/knative-extensions/kn-plugin-func/commit/59df756e49eda6717d82caf8c8f54422fc79fcb0))
|
||||
* correct error in OpenShift reg.cred.provider ([#1104](https://github.com/knative-extensions/kn-plugin-func/issues/1104)) ([a197f8b](https://github.com/knative-extensions/kn-plugin-func/commit/a197f8b330d6f5fdbc9c16585e605cdf74f9b8b9))
|
||||
* ensure registry in func.yaml is respected ([#1168](https://github.com/knative-extensions/kn-plugin-func/issues/1168)) ([80657c9](https://github.com/knative-extensions/kn-plugin-func/commit/80657c90e3df49bd4a55c61ada0cbadbdff7a56d))
|
||||
* image push authorization check ([#1109](https://github.com/knative-extensions/kn-plugin-func/issues/1109)) ([3b198cb](https://github.com/knative-extensions/kn-plugin-func/commit/3b198cb78164e751d293edc6467907cecd626643))
|
||||
* image push authorization check ([#1130](https://github.com/knative-extensions/kn-plugin-func/issues/1130)) ([36216e7](https://github.com/knative-extensions/kn-plugin-func/commit/36216e7fed34d3cd20aed951a27ed5fdf995bafb))
|
||||
* performance of template loading ([#1189](https://github.com/knative-extensions/kn-plugin-func/issues/1189)) ([dca11da](https://github.com/knative-extensions/kn-plugin-func/commit/dca11dad5bfefeb05b0d3ea2a88bc4f9b159a2b7))
|
||||
* stop build progress loop when build completes ([#1133](https://github.com/knative-extensions/kn-plugin-func/issues/1133)) ([cf5be9a](https://github.com/knative-extensions/kn-plugin-func/commit/cf5be9a6161085a92f60d5345b15e8d394d69f0f))
|
||||
* use 0 group id for func-buildpacks Task ([#1105](https://github.com/knative-extensions/kn-plugin-func/issues/1105)) ([f4537dd](https://github.com/knative-extensions/kn-plugin-func/commit/f4537dd3d5d5130c27ad8c1d1ff0df92569fbc25))
|
||||
* use creds from creds store first ([#1103](https://github.com/knative-extensions/kn-plugin-func/issues/1103)) ([e1d5229](https://github.com/knative-extensions/kn-plugin-func/commit/e1d522990016f46beff26117f8b80ee16b098402))
|
||||
* use space prefix for deploy output text ([#1144](https://github.com/knative-extensions/kn-plugin-func/issues/1144)) ([3b8c240](https://github.com/knative-extensions/kn-plugin-func/commit/3b8c24092b0e3c7863715ec9b96c8a86b10af245))
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
* replace commands.md with generated text file ([#1089](https://github.com/knative-sandbox/kn-plugin-func/issues/1089)) ([df022f5](https://github.com/knative-sandbox/kn-plugin-func/commit/df022f5c93911687e4356f4c58ccbb5d10b7a895))
|
||||
* replace commands.md with generated text file ([#1089](https://github.com/knative-extensions/kn-plugin-func/issues/1089)) ([df022f5](https://github.com/knative-extensions/kn-plugin-func/commit/df022f5c93911687e4356f4c58ccbb5d10b7a895))
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* add some milliseconds in client tests ([#1178](https://github.com/knative-sandbox/kn-plugin-func/issues/1178)) ([3ac5d46](https://github.com/knative-sandbox/kn-plugin-func/commit/3ac5d468bfdbb326375ebc5bc640729b59fec7f2))
|
||||
* add validation for `builder` ([#1136](https://github.com/knative-sandbox/kn-plugin-func/issues/1136)) ([71b0ddd](https://github.com/knative-sandbox/kn-plugin-func/commit/71b0dddc556bcc6767354e66b25091eb001d0700))
|
||||
* adjust codecov configuration ([#1177](https://github.com/knative-sandbox/kn-plugin-func/issues/1177)) ([a52b7d5](https://github.com/knative-sandbox/kn-plugin-func/commit/a52b7d5ecd895cd65e2844bc5b4d68974d8f3e6f))
|
||||
* **deps:** bump github.com/containerd/containerd from 1.6.0 to 1.6.6 ([#1112](https://github.com/knative-sandbox/kn-plugin-func/issues/1112)) ([7a760fb](https://github.com/knative-sandbox/kn-plugin-func/commit/7a760fbf57925104b7d68dbc987183594cf0bc48))
|
||||
* **deps:** update node/typescript deps in e2e tests ([#1119](https://github.com/knative-sandbox/kn-plugin-func/issues/1119)) ([cccb283](https://github.com/knative-sandbox/kn-plugin-func/commit/cccb2833d1ad8f77cfb200ef4f43a7e4098af92d))
|
||||
* update node and typescript dependencies ([#1110](https://github.com/knative-sandbox/kn-plugin-func/issues/1110)) ([29f3aad](https://github.com/knative-sandbox/kn-plugin-func/commit/29f3aadb47ecd59a0783b2a20643b6963e82af2e))
|
||||
* update Quarkus platform to 2.11.2.Final ([#1157](https://github.com/knative-sandbox/kn-plugin-func/issues/1157)) ([849c2cd](https://github.com/knative-sandbox/kn-plugin-func/commit/849c2cd7a187d37693ba963b6cd1fc9a0377ad4d))
|
||||
* update Quarkus platform version to 2.11.3.Final ([#1187](https://github.com/knative-sandbox/kn-plugin-func/issues/1187)) ([b3ced5e](https://github.com/knative-sandbox/kn-plugin-func/commit/b3ced5ebd5353568a63bbbc0ecdd986ac52ad706))
|
||||
* update Quarkus templates to 2.10.3.Final ([#1132](https://github.com/knative-sandbox/kn-plugin-func/issues/1132)) ([a906b88](https://github.com/knative-sandbox/kn-plugin-func/commit/a906b8866cb97894a676aeada9212df0e76a7ee0))
|
||||
* update springboot dependencies ([#1183](https://github.com/knative-sandbox/kn-plugin-func/issues/1183)) ([e465348](https://github.com/knative-sandbox/kn-plugin-func/commit/e4653482101443ce81949c04f2c011b8470302a0))
|
||||
* use dot as path default rather than absolute path ([#1184](https://github.com/knative-sandbox/kn-plugin-func/issues/1184)) ([fecbc4e](https://github.com/knative-sandbox/kn-plugin-func/commit/fecbc4ef8bc7a1e9007f8bc912af7d7a2cc9d0fa))
|
||||
* use lower case *functions* in all CLI outputs ([#1135](https://github.com/knative-sandbox/kn-plugin-func/issues/1135)) ([e659256](https://github.com/knative-sandbox/kn-plugin-func/commit/e659256005cdc5231759beef2e706466820c129d))
|
||||
* Use NodeJS for script instead of Shell ([#1170](https://github.com/knative-sandbox/kn-plugin-func/issues/1170)) ([62b7232](https://github.com/knative-sandbox/kn-plugin-func/commit/62b723263688336c4d5ff85d9652a2cd460d941a))
|
||||
* add some milliseconds in client tests ([#1178](https://github.com/knative-extensions/kn-plugin-func/issues/1178)) ([3ac5d46](https://github.com/knative-extensions/kn-plugin-func/commit/3ac5d468bfdbb326375ebc5bc640729b59fec7f2))
|
||||
* add validation for `builder` ([#1136](https://github.com/knative-extensions/kn-plugin-func/issues/1136)) ([71b0ddd](https://github.com/knative-extensions/kn-plugin-func/commit/71b0dddc556bcc6767354e66b25091eb001d0700))
|
||||
* adjust codecov configuration ([#1177](https://github.com/knative-extensions/kn-plugin-func/issues/1177)) ([a52b7d5](https://github.com/knative-extensions/kn-plugin-func/commit/a52b7d5ecd895cd65e2844bc5b4d68974d8f3e6f))
|
||||
* **deps:** bump github.com/containerd/containerd from 1.6.0 to 1.6.6 ([#1112](https://github.com/knative-extensions/kn-plugin-func/issues/1112)) ([7a760fb](https://github.com/knative-extensions/kn-plugin-func/commit/7a760fbf57925104b7d68dbc987183594cf0bc48))
|
||||
* **deps:** update node/typescript deps in e2e tests ([#1119](https://github.com/knative-extensions/kn-plugin-func/issues/1119)) ([cccb283](https://github.com/knative-extensions/kn-plugin-func/commit/cccb2833d1ad8f77cfb200ef4f43a7e4098af92d))
|
||||
* update node and typescript dependencies ([#1110](https://github.com/knative-extensions/kn-plugin-func/issues/1110)) ([29f3aad](https://github.com/knative-extensions/kn-plugin-func/commit/29f3aadb47ecd59a0783b2a20643b6963e82af2e))
|
||||
* update Quarkus platform to 2.11.2.Final ([#1157](https://github.com/knative-extensions/kn-plugin-func/issues/1157)) ([849c2cd](https://github.com/knative-extensions/kn-plugin-func/commit/849c2cd7a187d37693ba963b6cd1fc9a0377ad4d))
|
||||
* update Quarkus platform version to 2.11.3.Final ([#1187](https://github.com/knative-extensions/kn-plugin-func/issues/1187)) ([b3ced5e](https://github.com/knative-extensions/kn-plugin-func/commit/b3ced5ebd5353568a63bbbc0ecdd986ac52ad706))
|
||||
* update Quarkus templates to 2.10.3.Final ([#1132](https://github.com/knative-extensions/kn-plugin-func/issues/1132)) ([a906b88](https://github.com/knative-extensions/kn-plugin-func/commit/a906b8866cb97894a676aeada9212df0e76a7ee0))
|
||||
* update springboot dependencies ([#1183](https://github.com/knative-extensions/kn-plugin-func/issues/1183)) ([e465348](https://github.com/knative-extensions/kn-plugin-func/commit/e4653482101443ce81949c04f2c011b8470302a0))
|
||||
* use dot as path default rather than absolute path ([#1184](https://github.com/knative-extensions/kn-plugin-func/issues/1184)) ([fecbc4e](https://github.com/knative-extensions/kn-plugin-func/commit/fecbc4ef8bc7a1e9007f8bc912af7d7a2cc9d0fa))
|
||||
* use lower case *functions* in all CLI outputs ([#1135](https://github.com/knative-extensions/kn-plugin-func/issues/1135)) ([e659256](https://github.com/knative-extensions/kn-plugin-func/commit/e659256005cdc5231759beef2e706466820c129d))
|
||||
* Use NodeJS for script instead of Shell ([#1170](https://github.com/knative-extensions/kn-plugin-func/issues/1170)) ([62b7232](https://github.com/knative-extensions/kn-plugin-func/commit/62b723263688336c4d5ff85d9652a2cd460d941a))
|
||||
|
||||
## [0.24.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.23.0...v0.24.0) (2022-06-01)
|
||||
## [0.24.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.23.0...v0.24.0) (2022-06-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* configurable s2i builder images ([#1024](https://github.com/knative-sandbox/kn-plugin-func/issues/1024)) ([096085d](https://github.com/knative-sandbox/kn-plugin-func/commit/096085d751f105b5592a09c849fef364b84145b3))
|
||||
* enable Paketo builders for Python functions ([#979](https://github.com/knative-sandbox/kn-plugin-func/issues/979)) ([5af934b](https://github.com/knative-sandbox/kn-plugin-func/commit/5af934be8d97b0de676fb7d81e07f7b07a33a9e3))
|
||||
* expose default builder image logic for in-cluster builds ([#1021](https://github.com/knative-sandbox/kn-plugin-func/issues/1021)) ([dc8abf1](https://github.com/knative-sandbox/kn-plugin-func/commit/dc8abf179c63582d197e5a9add2006ad0c026ff6))
|
||||
* improved invoke verbosity ([#1007](https://github.com/knative-sandbox/kn-plugin-func/issues/1007)) ([867d4c2](https://github.com/knative-sandbox/kn-plugin-func/commit/867d4c26d6dd0b4d06cf6428dc932004e20ca981))
|
||||
* invoke verbose metadata ([#944](https://github.com/knative-sandbox/kn-plugin-func/issues/944)) ([c3c1456](https://github.com/knative-sandbox/kn-plugin-func/commit/c3c1456ede7b471a271d0680107657ac0e4f0568))
|
||||
* make templates consistent across runtimes ([#948](https://github.com/knative-sandbox/kn-plugin-func/issues/948)) ([13d4222](https://github.com/knative-sandbox/kn-plugin-func/commit/13d4222461c553d5da1c8448713cba9e4a3e828a))
|
||||
* s2i builder env var interpolation ([#991](https://github.com/knative-sandbox/kn-plugin-func/issues/991)) ([1424831](https://github.com/knative-sandbox/kn-plugin-func/commit/14248311b1254fe8601b394f064e2fdd92dd4ced))
|
||||
* s2i builder quarkus support ([#993](https://github.com/knative-sandbox/kn-plugin-func/issues/993)) ([397ce65](https://github.com/knative-sandbox/kn-plugin-func/commit/397ce65598c1f61d2312c62016ed78453e1299a3))
|
||||
* s2i builder typescript support ([#957](https://github.com/knative-sandbox/kn-plugin-func/issues/957)) ([3be1a77](https://github.com/knative-sandbox/kn-plugin-func/commit/3be1a77388647055dc67e3901da323c240dc77f4))
|
||||
* configurable s2i builder images ([#1024](https://github.com/knative-extensions/kn-plugin-func/issues/1024)) ([096085d](https://github.com/knative-extensions/kn-plugin-func/commit/096085d751f105b5592a09c849fef364b84145b3))
|
||||
* enable Paketo builders for Python functions ([#979](https://github.com/knative-extensions/kn-plugin-func/issues/979)) ([5af934b](https://github.com/knative-extensions/kn-plugin-func/commit/5af934be8d97b0de676fb7d81e07f7b07a33a9e3))
|
||||
* expose default builder image logic for in-cluster builds ([#1021](https://github.com/knative-extensions/kn-plugin-func/issues/1021)) ([dc8abf1](https://github.com/knative-extensions/kn-plugin-func/commit/dc8abf179c63582d197e5a9add2006ad0c026ff6))
|
||||
* improved invoke verbosity ([#1007](https://github.com/knative-extensions/kn-plugin-func/issues/1007)) ([867d4c2](https://github.com/knative-extensions/kn-plugin-func/commit/867d4c26d6dd0b4d06cf6428dc932004e20ca981))
|
||||
* invoke verbose metadata ([#944](https://github.com/knative-extensions/kn-plugin-func/issues/944)) ([c3c1456](https://github.com/knative-extensions/kn-plugin-func/commit/c3c1456ede7b471a271d0680107657ac0e4f0568))
|
||||
* make templates consistent across runtimes ([#948](https://github.com/knative-extensions/kn-plugin-func/issues/948)) ([13d4222](https://github.com/knative-extensions/kn-plugin-func/commit/13d4222461c553d5da1c8448713cba9e4a3e828a))
|
||||
* s2i builder env var interpolation ([#991](https://github.com/knative-extensions/kn-plugin-func/issues/991)) ([1424831](https://github.com/knative-extensions/kn-plugin-func/commit/14248311b1254fe8601b394f064e2fdd92dd4ced))
|
||||
* s2i builder quarkus support ([#993](https://github.com/knative-extensions/kn-plugin-func/issues/993)) ([397ce65](https://github.com/knative-extensions/kn-plugin-func/commit/397ce65598c1f61d2312c62016ed78453e1299a3))
|
||||
* s2i builder typescript support ([#957](https://github.com/knative-extensions/kn-plugin-func/issues/957)) ([3be1a77](https://github.com/knative-extensions/kn-plugin-func/commit/3be1a77388647055dc67e3901da323c240dc77f4))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ignore `is forbidden` errors when deleting function and resources ([#988](https://github.com/knative-sandbox/kn-plugin-func/issues/988)) ([ce26a23](https://github.com/knative-sandbox/kn-plugin-func/commit/ce26a23352513747cad25b7668def43edff6f0fe))
|
||||
* ignore node_modules for s2i builds ([#1019](https://github.com/knative-sandbox/kn-plugin-func/issues/1019)) ([1d367c6](https://github.com/knative-sandbox/kn-plugin-func/commit/1d367c6be50d36e045b475c7ff173001b1eaa3d0))
|
||||
* read pwd from non-tty input ([#996](https://github.com/knative-sandbox/kn-plugin-func/issues/996)) ([e9932cd](https://github.com/knative-sandbox/kn-plugin-func/commit/e9932cdf43eb560ff496a98f83766d1c3e1fdc96))
|
||||
* update various doc links ([#980](https://github.com/knative-sandbox/kn-plugin-func/issues/980)) ([bc6383e](https://github.com/knative-sandbox/kn-plugin-func/commit/bc6383e55c89349e8e25a79e0f90be1760818e50))
|
||||
* ignore `is forbidden` errors when deleting function and resources ([#988](https://github.com/knative-extensions/kn-plugin-func/issues/988)) ([ce26a23](https://github.com/knative-extensions/kn-plugin-func/commit/ce26a23352513747cad25b7668def43edff6f0fe))
|
||||
* ignore node_modules for s2i builds ([#1019](https://github.com/knative-extensions/kn-plugin-func/issues/1019)) ([1d367c6](https://github.com/knative-extensions/kn-plugin-func/commit/1d367c6be50d36e045b475c7ff173001b1eaa3d0))
|
||||
* read pwd from non-tty input ([#996](https://github.com/knative-extensions/kn-plugin-func/issues/996)) ([e9932cd](https://github.com/knative-extensions/kn-plugin-func/commit/e9932cdf43eb560ff496a98f83766d1c3e1fdc96))
|
||||
* update various doc links ([#980](https://github.com/knative-extensions/kn-plugin-func/issues/980)) ([bc6383e](https://github.com/knative-extensions/kn-plugin-func/commit/bc6383e55c89349e8e25a79e0f90be1760818e50))
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
* add a language pack "contract" document ([#918](https://github.com/knative-sandbox/kn-plugin-func/issues/918)) ([76c647a](https://github.com/knative-sandbox/kn-plugin-func/commit/76c647a1c72f57efa8fad89c6802796d02254bd0))
|
||||
* add a language pack "contract" document ([#918](https://github.com/knative-extensions/kn-plugin-func/issues/918)) ([76c647a](https://github.com/knative-extensions/kn-plugin-func/commit/76c647a1c72f57efa8fad89c6802796d02254bd0))
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* add release process and func_darwin_arm64 to the release artifacts ([#945](https://github.com/knative-sandbox/kn-plugin-func/issues/945)) ([4e369a0](https://github.com/knative-sandbox/kn-plugin-func/commit/4e369a013ac3109bfea06dc730082b22f6d1cf36))
|
||||
* add version.txt to .gitattributes for style ([#966](https://github.com/knative-sandbox/kn-plugin-func/issues/966)) ([23d1188](https://github.com/knative-sandbox/kn-plugin-func/commit/23d118831923bf798c5d839c276382f48c048a32))
|
||||
* clean Repository and Runtimes structs ([#973](https://github.com/knative-sandbox/kn-plugin-func/issues/973)) ([e502d55](https://github.com/knative-sandbox/kn-plugin-func/commit/e502d554c8aafacc0f4d75bb7f6e1aef57e218fa))
|
||||
* **deps:** bump faas-js-runtime version ([#1000](https://github.com/knative-sandbox/kn-plugin-func/issues/1000)) ([83c081d](https://github.com/knative-sandbox/kn-plugin-func/commit/83c081d34a08b4775787c61eb00f9ca39cfcd33d))
|
||||
* templates ([#961](https://github.com/knative-sandbox/kn-plugin-func/issues/961)) ([34cb893](https://github.com/knative-sandbox/kn-plugin-func/commit/34cb893545a5f74a120783f66bb3a37d2b283d64))
|
||||
* update allocate script with latest knative ([#965](https://github.com/knative-sandbox/kn-plugin-func/issues/965)) ([4ffb1f9](https://github.com/knative-sandbox/kn-plugin-func/commit/4ffb1f9cba3ee1bac248a033ece6e8473965f7a7))
|
||||
* use paketo builders for all runtimes ([#1001](https://github.com/knative-sandbox/kn-plugin-func/issues/1001)) ([31c1d66](https://github.com/knative-sandbox/kn-plugin-func/commit/31c1d66eb3f0089541f8219f07722c75c8a82692))
|
||||
* add release process and func_darwin_arm64 to the release artifacts ([#945](https://github.com/knative-extensions/kn-plugin-func/issues/945)) ([4e369a0](https://github.com/knative-extensions/kn-plugin-func/commit/4e369a013ac3109bfea06dc730082b22f6d1cf36))
|
||||
* add version.txt to .gitattributes for style ([#966](https://github.com/knative-extensions/kn-plugin-func/issues/966)) ([23d1188](https://github.com/knative-extensions/kn-plugin-func/commit/23d118831923bf798c5d839c276382f48c048a32))
|
||||
* clean Repository and Runtimes structs ([#973](https://github.com/knative-extensions/kn-plugin-func/issues/973)) ([e502d55](https://github.com/knative-extensions/kn-plugin-func/commit/e502d554c8aafacc0f4d75bb7f6e1aef57e218fa))
|
||||
* **deps:** bump faas-js-runtime version ([#1000](https://github.com/knative-extensions/kn-plugin-func/issues/1000)) ([83c081d](https://github.com/knative-extensions/kn-plugin-func/commit/83c081d34a08b4775787c61eb00f9ca39cfcd33d))
|
||||
* templates ([#961](https://github.com/knative-extensions/kn-plugin-func/issues/961)) ([34cb893](https://github.com/knative-extensions/kn-plugin-func/commit/34cb893545a5f74a120783f66bb3a37d2b283d64))
|
||||
* update allocate script with latest knative ([#965](https://github.com/knative-extensions/kn-plugin-func/issues/965)) ([4ffb1f9](https://github.com/knative-extensions/kn-plugin-func/commit/4ffb1f9cba3ee1bac248a033ece6e8473965f7a7))
|
||||
* use paketo builders for all runtimes ([#1001](https://github.com/knative-extensions/kn-plugin-func/issues/1001)) ([31c1d66](https://github.com/knative-extensions/kn-plugin-func/commit/31c1d66eb3f0089541f8219f07722c75c8a82692))
|
||||
|
||||
<a name="unreleased"></a>
|
||||
|
||||
|
||||
---
|
||||
### [0.23.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.23.0...v0.22.0) (2022-04-06)
|
||||
### [0.23.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.23.0...v0.22.0) (2022-04-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* command help text template preprocessing ([#875](https://github.com/knative-sandbox/kn-plugin-func/issues/875)) ([2bd5254](https://github.com/knative-sandbox/kn-plugin-func/commit/2bd5254f19a14d6aae9bd4a4b59971ef36e96fad))
|
||||
* invoke verbose metadata ([#944](https://github.com/knative-sandbox/kn-plugin-func/issues/944)) ([c3c1456](https://github.com/knative-sandbox/kn-plugin-func/commit/c3c1456ede7b471a271d0680107657ac0e4f0568))
|
||||
* on cluster build doens't require privileged cluster permissions ([#934](https://github.com/knative-sandbox/kn-plugin-func/issues/934)) ([e9251f5](https://github.com/knative-sandbox/kn-plugin-func/commit/e9251f518cc806768f0221f11e39f04fa4619537))
|
||||
* s2i builder with preliminary node support ([#923](https://github.com/knative-sandbox/kn-plugin-func/issues/923)) ([a91bcc5](https://github.com/knative-sandbox/kn-plugin-func/commit/a91bcc5fcfe66948c86ce3e33cf0d28230536f1c)), closes [#921](https://github.com/knative-sandbox/kn-plugin-func/issues/921)
|
||||
* command help text template preprocessing ([#875](https://github.com/knative-extensions/kn-plugin-func/issues/875)) ([2bd5254](https://github.com/knative-extensions/kn-plugin-func/commit/2bd5254f19a14d6aae9bd4a4b59971ef36e96fad))
|
||||
* invoke verbose metadata ([#944](https://github.com/knative-extensions/kn-plugin-func/issues/944)) ([c3c1456](https://github.com/knative-extensions/kn-plugin-func/commit/c3c1456ede7b471a271d0680107657ac0e4f0568))
|
||||
* on cluster build doens't require privileged cluster permissions ([#934](https://github.com/knative-extensions/kn-plugin-func/issues/934)) ([e9251f5](https://github.com/knative-extensions/kn-plugin-func/commit/e9251f518cc806768f0221f11e39f04fa4619537))
|
||||
* s2i builder with preliminary node support ([#923](https://github.com/knative-extensions/kn-plugin-func/issues/923)) ([a91bcc5](https://github.com/knative-extensions/kn-plugin-func/commit/a91bcc5fcfe66948c86ce3e33cf0d28230536f1c)), closes [#921](https://github.com/knative-extensions/kn-plugin-func/issues/921)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* apply updated spring-boot-function dependency ([#936](https://github.com/knative-sandbox/kn-plugin-func/issues/936)) ([4a4cebb](https://github.com/knative-sandbox/kn-plugin-func/commit/4a4cebb1ea7226e7d7c1dbfb9e3fa8e5ec22c31d))
|
||||
* bind verbose flag to root ([#884](https://github.com/knative-sandbox/kn-plugin-func/issues/884)) ([25524a1](https://github.com/knative-sandbox/kn-plugin-func/commit/25524a1f8435cd310b45f283e987eee7a8736ceb))
|
||||
* full clone of template repos on add ([#904](https://github.com/knative-sandbox/kn-plugin-func/issues/904)) ([564a34b](https://github.com/knative-sandbox/kn-plugin-func/commit/564a34b3f53381bdd59262dcb78d2953f973c8bb))
|
||||
* minor typos in docs ([#862](https://github.com/knative-sandbox/kn-plugin-func/issues/862)) ([efc3b20](https://github.com/knative-sandbox/kn-plugin-func/commit/efc3b208cb5ab76f1eb73801501bcbfc23f16928))
|
||||
* use full root name for cmd help prefixes ([#873](https://github.com/knative-sandbox/kn-plugin-func/issues/873)) ([3f30c91](https://github.com/knative-sandbox/kn-plugin-func/commit/3f30c91116344b592bf392e92b63cb845b25428a))
|
||||
* apply updated spring-boot-function dependency ([#936](https://github.com/knative-extensions/kn-plugin-func/issues/936)) ([4a4cebb](https://github.com/knative-extensions/kn-plugin-func/commit/4a4cebb1ea7226e7d7c1dbfb9e3fa8e5ec22c31d))
|
||||
* bind verbose flag to root ([#884](https://github.com/knative-extensions/kn-plugin-func/issues/884)) ([25524a1](https://github.com/knative-extensions/kn-plugin-func/commit/25524a1f8435cd310b45f283e987eee7a8736ceb))
|
||||
* full clone of template repos on add ([#904](https://github.com/knative-extensions/kn-plugin-func/issues/904)) ([564a34b](https://github.com/knative-extensions/kn-plugin-func/commit/564a34b3f53381bdd59262dcb78d2953f973c8bb))
|
||||
* minor typos in docs ([#862](https://github.com/knative-extensions/kn-plugin-func/issues/862)) ([efc3b20](https://github.com/knative-extensions/kn-plugin-func/commit/efc3b208cb5ab76f1eb73801501bcbfc23f16928))
|
||||
* use full root name for cmd help prefixes ([#873](https://github.com/knative-extensions/kn-plugin-func/issues/873)) ([3f30c91](https://github.com/knative-extensions/kn-plugin-func/commit/3f30c91116344b592bf392e92b63cb845b25428a))
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* add Apple M1 build in cross-platform target ([#932](https://github.com/knative-sandbox/kn-plugin-func/issues/932)) ([00d5a82](https://github.com/knative-sandbox/kn-plugin-func/commit/00d5a8272284ea40ebeefa4f22f12c2d375aadae))
|
||||
* add Apple M1 build in cross-platform target ([#932](https://github.com/knative-extensions/kn-plugin-func/issues/932)) ([00d5a82](https://github.com/knative-extensions/kn-plugin-func/commit/00d5a8272284ea40ebeefa4f22f12c2d375aadae))
|
||||
---
|
||||
## [0.22.0](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.21.2...v0.22.0) (2022-02-22)
|
||||
## [0.22.0](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.21.2...v0.22.0) (2022-02-22)
|
||||
|
||||
### Chore
|
||||
|
||||
- Bump Node.js builder image to the latest paketo builder, removing a non-fatal warning that was issued at function startup. (#[8](https://github.com/knative-sandbox/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:8)26, @lance)
|
||||
- Update boson builder images to most recent versions (#8[10](https://github.com/knative-sandbox/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:10), @matejvasek)
|
||||
- Bump Node.js builder image to the latest paketo builder, removing a non-fatal warning that was issued at function startup. (#[8](https://github.com/knative-extensions/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:8)26, @lance)
|
||||
- Update boson builder images to most recent versions (#8[10](https://github.com/knative-extensions/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:10), @matejvasek)
|
||||
|
||||
### Enhancement
|
||||
|
||||
|
@ -139,48 +139,48 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
### Bug or Regression
|
||||
|
||||
- Fix a bug where interactive prompt defaults were not being used (#821, @lkingland)
|
||||
- Fixes a bug during func create when confirm option is used with the go language runtime (#8[15](https://github.com/knative-sandbox/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:15), @senthilnathan)
|
||||
- Fixes a bug where the invoke and describe commands could fail if Knative Eventing is not installed on the cluster. (#8[23](https://github.com/knative-sandbox/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:23), @lance)
|
||||
- Fixes a bug during func create when confirm option is used with the go language runtime (#8[15](https://github.com/knative-extensions/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:15), @senthilnathan)
|
||||
- Fixes a bug where the invoke and describe commands could fail if Knative Eventing is not installed on the cluster. (#8[23](https://github.com/knative-extensions/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:23), @lance)
|
||||
- Fixes missing `cloudevent` invocation format for Node.js, SpringBoot and Rust CloudEvent templates (#846, @lance)
|
||||
|
||||
### Uncategorized
|
||||
|
||||
- Detects when deploying to OpenShift and use internal registry (#8[25](https://github.com/knative-sandbox/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:25), @matejvasek)
|
||||
- Detects when deploying to OpenShift and use internal registry (#8[25](https://github.com/knative-extensions/kn-plugin-func/runs/5297690460?check_suite_focus=true#step:6:25), @matejvasek)
|
||||
|
||||
---
|
||||
## [0.21.2](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.21.1...v0.21.2) (2022-01-28)
|
||||
## [0.21.2](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.21.1...v0.21.2) (2022-01-28)
|
||||
|
||||
## What's Changed
|
||||
* backport: bug fixes for 0.21 by @lance in https://github.com/knative-sandbox/kn-plugin-func/pull/793
|
||||
* backport: bug fixes for 0.21 by @lance in https://github.com/knative-extensions/kn-plugin-func/pull/793
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.21.1...v0.21.2
|
||||
**Full Changelog**: https://github.com/knative-extensions/kn-plugin-func/compare/v0.21.1...v0.21.2
|
||||
|
||||
---
|
||||
## [0.21.1](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.21.0...v0.21.1) (2022-01-27)
|
||||
## [0.21.1](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.21.0...v0.21.1) (2022-01-27)
|
||||
|
||||
### Enhancement
|
||||
|
||||
- Adds a label `function.knative.dev/name: functionName` to every resouce created for a Function ([#757](https://github.com/knative-sandbox/kn-plugin-func/pull/757), [@zroubalik](https://github.com/zroubalik))
|
||||
- Adds the ability to build a Function on the cluster using Tekton Pipelines. The build on the cluster is enabled by fetching Function source code from a remote Git repository. ([#743](https://github.com/knative-sandbox/kn-plugin-func/pull/743), [@zroubalik](https://github.com/zroubalik))
|
||||
- Adds a label `function.knative.dev/name: functionName` to every resouce created for a Function ([#757](https://github.com/knative-extensions/kn-plugin-func/pull/757), [@zroubalik](https://github.com/zroubalik))
|
||||
- Adds the ability to build a Function on the cluster using Tekton Pipelines. The build on the cluster is enabled by fetching Function source code from a remote Git repository. ([#743](https://github.com/knative-extensions/kn-plugin-func/pull/743), [@zroubalik](https://github.com/zroubalik))
|
||||
|
||||
### Bug or Regression
|
||||
|
||||
- Changes the springboot function templates to use the base builder instead of the tiny builder. ([#792](https://github.com/knative-sandbox/kn-plugin-func/pull/792), [@lance](https://github.com/lance))
|
||||
- Changes the springboot function templates to use the base builder instead of the tiny builder. ([#792](https://github.com/knative-extensions/kn-plugin-func/pull/792), [@lance](https://github.com/lance))
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.21.0...v0.21.1
|
||||
**Full Changelog**: https://github.com/knative-extensions/kn-plugin-func/compare/v0.21.0...v0.21.1
|
||||
|
||||
---
|
||||
## [0.21.0](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.20.0...v0.21.0) (2022-01-12)
|
||||
## [0.21.0](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.20.0...v0.21.0) (2022-01-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add possibility to disable pushing of image in `deploy` command ([#736](https://www.github.com/knative-sandbox/kn-plugin-func/issues/736)) ([4e5a5e8](https://www.github.com/knative-sandbox/kn-plugin-func/commit/4e5a5e830799b73f65aba8ee248a52bf1c643acb))
|
||||
* add possibility to disable pushing of image in `deploy` command ([#739](https://www.github.com/knative-sandbox/kn-plugin-func/issues/739)) ([64ba17b](https://www.github.com/knative-sandbox/kn-plugin-func/commit/64ba17b4fbe9033e8279fa34aeebdb12edcee25d))
|
||||
* add possibility to disable pushing of image in `deploy` command ([#736](https://www.github.com/knative-extensions/kn-plugin-func/issues/736)) ([4e5a5e8](https://www.github.com/knative-extensions/kn-plugin-func/commit/4e5a5e830799b73f65aba8ee248a52bf1c643acb))
|
||||
* add possibility to disable pushing of image in `deploy` command ([#739](https://www.github.com/knative-extensions/kn-plugin-func/issues/739)) ([64ba17b](https://www.github.com/knative-extensions/kn-plugin-func/commit/64ba17b4fbe9033e8279fa34aeebdb12edcee25d))
|
||||
|
||||
## [0.20.0](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.19.0...v0.20.0) (2021-12-20)
|
||||
## [0.20.0](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.19.0...v0.20.0) (2021-12-20)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -189,33 +189,33 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* add flag to push image at the end of a successful build ([#681](https://www.github.com/knative-sandbox/kn-plugin-func/issues/681)) ([2f24182](https://www.github.com/knative-sandbox/kn-plugin-func/commit/2f241824ff3a2664a987fe742aed2f0b56aeb9ab))
|
||||
* add POD_NAME as an environment variable ([#660](https://www.github.com/knative-sandbox/kn-plugin-func/issues/660)) ([64473b7](https://www.github.com/knative-sandbox/kn-plugin-func/commit/64473b7197bb5a821b6724a8b914784891b1a828))
|
||||
* add telemetry to Node.js and TypeScript function templates ([#719](https://www.github.com/knative-sandbox/kn-plugin-func/issues/719)) ([d7cfe6e](https://www.github.com/knative-sandbox/kn-plugin-func/commit/d7cfe6ead76f15c4bcd34a132d0c17c02a149548))
|
||||
* allow build to be triggered from run when fn.Image is missing ([#644](https://www.github.com/knative-sandbox/kn-plugin-func/issues/644)) ([b190b52](https://www.github.com/knative-sandbox/kn-plugin-func/commit/b190b527542bf659f06bf931d94d09542d012c36))
|
||||
* allow push to cluster internal registries ([#718](https://www.github.com/knative-sandbox/kn-plugin-func/issues/718)) ([8d51393](https://www.github.com/knative-sandbox/kn-plugin-func/commit/8d51393181adca0c74a4b08cfb2dc2da390f983b))
|
||||
* automatically start podman service ([#648](https://www.github.com/knative-sandbox/kn-plugin-func/issues/648)) ([bfdfb76](https://www.github.com/knative-sandbox/kn-plugin-func/commit/bfdfb760cff575146764f9b841a0cafcb31bcd58))
|
||||
* custom default HTTP transport ([#711](https://www.github.com/knative-sandbox/kn-plugin-func/issues/711)) ([a13f897](https://www.github.com/knative-sandbox/kn-plugin-func/commit/a13f897fbb996dbfcb2120965745477321087a9c))
|
||||
* ensure config and repos path exists ([#683](https://www.github.com/knative-sandbox/kn-plugin-func/issues/683)) ([db9ad07](https://www.github.com/knative-sandbox/kn-plugin-func/commit/db9ad07c7048361946a8c7d45c549323eee44a58))
|
||||
* function creation timestamp ([#651](https://www.github.com/knative-sandbox/kn-plugin-func/issues/651)) ([1bf17ec](https://www.github.com/knative-sandbox/kn-plugin-func/commit/1bf17ec976130551da366e75b38f5169b3daed4e))
|
||||
* function version migrations ([#664](https://www.github.com/knative-sandbox/kn-plugin-func/issues/664)) ([ccf0015](https://www.github.com/knative-sandbox/kn-plugin-func/commit/ccf00152be0ceba1794267f8e03a09cb32fee514))
|
||||
* In cluster dialer to proxy TCP connections to unexposed services ([#688](https://www.github.com/knative-sandbox/kn-plugin-func/issues/688)) ([98ef5a0](https://www.github.com/knative-sandbox/kn-plugin-func/commit/98ef5a00356a5b93ef1a6c581ae8d5ba86ee09e4))
|
||||
* make SpringBoot template SpringNative by default ([#649](https://www.github.com/knative-sandbox/kn-plugin-func/issues/649)) ([c70a21e](https://www.github.com/knative-sandbox/kn-plugin-func/commit/c70a21e9a459d726a4118e177835082323698f83))
|
||||
* use `function.knative.dev` for Functions related labels ([#717](https://www.github.com/knative-sandbox/kn-plugin-func/issues/717)) ([feaf8f9](https://www.github.com/knative-sandbox/kn-plugin-func/commit/feaf8f91091afc21bcc3e99ed3098c9ff0679883))
|
||||
* add flag to push image at the end of a successful build ([#681](https://www.github.com/knative-extensions/kn-plugin-func/issues/681)) ([2f24182](https://www.github.com/knative-extensions/kn-plugin-func/commit/2f241824ff3a2664a987fe742aed2f0b56aeb9ab))
|
||||
* add POD_NAME as an environment variable ([#660](https://www.github.com/knative-extensions/kn-plugin-func/issues/660)) ([64473b7](https://www.github.com/knative-extensions/kn-plugin-func/commit/64473b7197bb5a821b6724a8b914784891b1a828))
|
||||
* add telemetry to Node.js and TypeScript function templates ([#719](https://www.github.com/knative-extensions/kn-plugin-func/issues/719)) ([d7cfe6e](https://www.github.com/knative-extensions/kn-plugin-func/commit/d7cfe6ead76f15c4bcd34a132d0c17c02a149548))
|
||||
* allow build to be triggered from run when fn.Image is missing ([#644](https://www.github.com/knative-extensions/kn-plugin-func/issues/644)) ([b190b52](https://www.github.com/knative-extensions/kn-plugin-func/commit/b190b527542bf659f06bf931d94d09542d012c36))
|
||||
* allow push to cluster internal registries ([#718](https://www.github.com/knative-extensions/kn-plugin-func/issues/718)) ([8d51393](https://www.github.com/knative-extensions/kn-plugin-func/commit/8d51393181adca0c74a4b08cfb2dc2da390f983b))
|
||||
* automatically start podman service ([#648](https://www.github.com/knative-extensions/kn-plugin-func/issues/648)) ([bfdfb76](https://www.github.com/knative-extensions/kn-plugin-func/commit/bfdfb760cff575146764f9b841a0cafcb31bcd58))
|
||||
* custom default HTTP transport ([#711](https://www.github.com/knative-extensions/kn-plugin-func/issues/711)) ([a13f897](https://www.github.com/knative-extensions/kn-plugin-func/commit/a13f897fbb996dbfcb2120965745477321087a9c))
|
||||
* ensure config and repos path exists ([#683](https://www.github.com/knative-extensions/kn-plugin-func/issues/683)) ([db9ad07](https://www.github.com/knative-extensions/kn-plugin-func/commit/db9ad07c7048361946a8c7d45c549323eee44a58))
|
||||
* function creation timestamp ([#651](https://www.github.com/knative-extensions/kn-plugin-func/issues/651)) ([1bf17ec](https://www.github.com/knative-extensions/kn-plugin-func/commit/1bf17ec976130551da366e75b38f5169b3daed4e))
|
||||
* function version migrations ([#664](https://www.github.com/knative-extensions/kn-plugin-func/issues/664)) ([ccf0015](https://www.github.com/knative-extensions/kn-plugin-func/commit/ccf00152be0ceba1794267f8e03a09cb32fee514))
|
||||
* In cluster dialer to proxy TCP connections to unexposed services ([#688](https://www.github.com/knative-extensions/kn-plugin-func/issues/688)) ([98ef5a0](https://www.github.com/knative-extensions/kn-plugin-func/commit/98ef5a00356a5b93ef1a6c581ae8d5ba86ee09e4))
|
||||
* make SpringBoot template SpringNative by default ([#649](https://www.github.com/knative-extensions/kn-plugin-func/issues/649)) ([c70a21e](https://www.github.com/knative-extensions/kn-plugin-func/commit/c70a21e9a459d726a4118e177835082323698f83))
|
||||
* use `function.knative.dev` for Functions related labels ([#717](https://www.github.com/knative-extensions/kn-plugin-func/issues/717)) ([feaf8f9](https://www.github.com/knative-extensions/kn-plugin-func/commit/feaf8f91091afc21bcc3e99ed3098c9ff0679883))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make registry validation work again ([#690](https://www.github.com/knative-sandbox/kn-plugin-func/issues/690)) ([10f2cf4](https://www.github.com/knative-sandbox/kn-plugin-func/commit/10f2cf44c74884b4585114affd3c05cfba4f7613))
|
||||
* move integration port to unregistered range ([#701](https://www.github.com/knative-sandbox/kn-plugin-func/issues/701)) ([f63af0d](https://www.github.com/knative-sandbox/kn-plugin-func/commit/f63af0d34e97a549df51c47f12e22a7558504278))
|
||||
* remove stray manifest.yaml files ([#628](https://www.github.com/knative-sandbox/kn-plugin-func/issues/628)) ([c810efc](https://www.github.com/knative-sandbox/kn-plugin-func/commit/c810efc7a4eb0d87f37f3acfafc46c1e4639fdc4))
|
||||
* remove template manifest from final Function ([#703](https://www.github.com/knative-sandbox/kn-plugin-func/issues/703)) ([79ad65d](https://www.github.com/knative-sandbox/kn-plugin-func/commit/79ad65ddf42b1bfffacd3f6fe4d606885b1a3766))
|
||||
* revert hostname alias ([#712](https://www.github.com/knative-sandbox/kn-plugin-func/issues/712)) ([07062c1](https://www.github.com/knative-sandbox/kn-plugin-func/commit/07062c144aa19e4eb4c4ef27d5c5cb1ebb8eb185))
|
||||
* schema-generate should point to `function.go` ([#677](https://www.github.com/knative-sandbox/kn-plugin-func/issues/677)) ([c7d18c8](https://www.github.com/knative-sandbox/kn-plugin-func/commit/c7d18c89edaf0a4fcb5c7b684e5e151c217430c2))
|
||||
* use default socket path for TCP connections ([#669](https://www.github.com/knative-sandbox/kn-plugin-func/issues/669)) ([ee96bef](https://www.github.com/knative-sandbox/kn-plugin-func/commit/ee96bef9aea34c9370cf1f871bc4c558ed449a13))
|
||||
* use specific version of paketo builder ([#670](https://www.github.com/knative-sandbox/kn-plugin-func/issues/670)) ([834e8ae](https://www.github.com/knative-sandbox/kn-plugin-func/commit/834e8ae46c833d2052171dc8dde23648a1da5112))
|
||||
* make registry validation work again ([#690](https://www.github.com/knative-extensions/kn-plugin-func/issues/690)) ([10f2cf4](https://www.github.com/knative-extensions/kn-plugin-func/commit/10f2cf44c74884b4585114affd3c05cfba4f7613))
|
||||
* move integration port to unregistered range ([#701](https://www.github.com/knative-extensions/kn-plugin-func/issues/701)) ([f63af0d](https://www.github.com/knative-extensions/kn-plugin-func/commit/f63af0d34e97a549df51c47f12e22a7558504278))
|
||||
* remove stray manifest.yaml files ([#628](https://www.github.com/knative-extensions/kn-plugin-func/issues/628)) ([c810efc](https://www.github.com/knative-extensions/kn-plugin-func/commit/c810efc7a4eb0d87f37f3acfafc46c1e4639fdc4))
|
||||
* remove template manifest from final Function ([#703](https://www.github.com/knative-extensions/kn-plugin-func/issues/703)) ([79ad65d](https://www.github.com/knative-extensions/kn-plugin-func/commit/79ad65ddf42b1bfffacd3f6fe4d606885b1a3766))
|
||||
* revert hostname alias ([#712](https://www.github.com/knative-extensions/kn-plugin-func/issues/712)) ([07062c1](https://www.github.com/knative-extensions/kn-plugin-func/commit/07062c144aa19e4eb4c4ef27d5c5cb1ebb8eb185))
|
||||
* schema-generate should point to `function.go` ([#677](https://www.github.com/knative-extensions/kn-plugin-func/issues/677)) ([c7d18c8](https://www.github.com/knative-extensions/kn-plugin-func/commit/c7d18c89edaf0a4fcb5c7b684e5e151c217430c2))
|
||||
* use default socket path for TCP connections ([#669](https://www.github.com/knative-extensions/kn-plugin-func/issues/669)) ([ee96bef](https://www.github.com/knative-extensions/kn-plugin-func/commit/ee96bef9aea34c9370cf1f871bc4c558ed449a13))
|
||||
* use specific version of paketo builder ([#670](https://www.github.com/knative-extensions/kn-plugin-func/issues/670)) ([834e8ae](https://www.github.com/knative-extensions/kn-plugin-func/commit/834e8ae46c833d2052171dc8dde23648a1da5112))
|
||||
|
||||
## [0.19.0](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.18.0...v0.19.0) (2021-11-03)
|
||||
## [0.19.0](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.18.0...v0.19.0) (2021-11-03)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -224,28 +224,28 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* add support for manifest.yaml at repo/language/template levels ([#558](https://www.github.com/knative-sandbox/kn-plugin-func/issues/558)) ([e319ea3](https://www.github.com/knative-sandbox/kn-plugin-func/commit/e319ea3b62150ea2939876cb078ce150b7580bdf))
|
||||
* allow developers to provide Build Envs to buildpacks in `func.yaml` ([#571](https://www.github.com/knative-sandbox/kn-plugin-func/issues/571)) ([114a5fa](https://www.github.com/knative-sandbox/kn-plugin-func/commit/114a5faee3ab9ae1ec37ae5c4375c6218405c3b7))
|
||||
* create cli ([#547](https://www.github.com/knative-sandbox/kn-plugin-func/issues/547)) ([4fe9fdc](https://www.github.com/knative-sandbox/kn-plugin-func/commit/4fe9fdcab08552814c86d85194c552b591f52cd7))
|
||||
* Improve build performance ([#569](https://www.github.com/knative-sandbox/kn-plugin-func/issues/569)) ([ef7b986](https://www.github.com/knative-sandbox/kn-plugin-func/commit/ef7b986900e1eb6afd4203067aeac3dc99a4ede5))
|
||||
* periodically update progress during build ([#537](https://www.github.com/knative-sandbox/kn-plugin-func/issues/537)) ([01689e7](https://www.github.com/knative-sandbox/kn-plugin-func/commit/01689e7c131dd79db1e469c3ce54bd011464a6ef))
|
||||
* rename event templates to 'cloudevents' ([#584](https://www.github.com/knative-sandbox/kn-plugin-func/issues/584)) ([68b0904](https://www.github.com/knative-sandbox/kn-plugin-func/commit/68b0904b17dee5bc6a5ec71132d35c45d52f4b71))
|
||||
* Save password after user input ([#560](https://www.github.com/knative-sandbox/kn-plugin-func/issues/560)) ([e85a4aa](https://www.github.com/knative-sandbox/kn-plugin-func/commit/e85a4aa7f38681eb7554cac818eab7b1ca3bded1))
|
||||
* ssh connection to remote docker daemon ([#594](https://www.github.com/knative-sandbox/kn-plugin-func/issues/594)) ([e1f164d](https://www.github.com/knative-sandbox/kn-plugin-func/commit/e1f164d2ca6b0e720ebcf881b8d5fd123dfd0d82))
|
||||
* validation for registry/namespace to not contain image name ([#601](https://www.github.com/knative-sandbox/kn-plugin-func/issues/601)) ([cf9596c](https://www.github.com/knative-sandbox/kn-plugin-func/commit/cf9596c83e6eae8229ca61a18fafb5ba4df31d6b))
|
||||
* add support for manifest.yaml at repo/language/template levels ([#558](https://www.github.com/knative-extensions/kn-plugin-func/issues/558)) ([e319ea3](https://www.github.com/knative-extensions/kn-plugin-func/commit/e319ea3b62150ea2939876cb078ce150b7580bdf))
|
||||
* allow developers to provide Build Envs to buildpacks in `func.yaml` ([#571](https://www.github.com/knative-extensions/kn-plugin-func/issues/571)) ([114a5fa](https://www.github.com/knative-extensions/kn-plugin-func/commit/114a5faee3ab9ae1ec37ae5c4375c6218405c3b7))
|
||||
* create cli ([#547](https://www.github.com/knative-extensions/kn-plugin-func/issues/547)) ([4fe9fdc](https://www.github.com/knative-extensions/kn-plugin-func/commit/4fe9fdcab08552814c86d85194c552b591f52cd7))
|
||||
* Improve build performance ([#569](https://www.github.com/knative-extensions/kn-plugin-func/issues/569)) ([ef7b986](https://www.github.com/knative-extensions/kn-plugin-func/commit/ef7b986900e1eb6afd4203067aeac3dc99a4ede5))
|
||||
* periodically update progress during build ([#537](https://www.github.com/knative-extensions/kn-plugin-func/issues/537)) ([01689e7](https://www.github.com/knative-extensions/kn-plugin-func/commit/01689e7c131dd79db1e469c3ce54bd011464a6ef))
|
||||
* rename event templates to 'cloudevents' ([#584](https://www.github.com/knative-extensions/kn-plugin-func/issues/584)) ([68b0904](https://www.github.com/knative-extensions/kn-plugin-func/commit/68b0904b17dee5bc6a5ec71132d35c45d52f4b71))
|
||||
* Save password after user input ([#560](https://www.github.com/knative-extensions/kn-plugin-func/issues/560)) ([e85a4aa](https://www.github.com/knative-extensions/kn-plugin-func/commit/e85a4aa7f38681eb7554cac818eab7b1ca3bded1))
|
||||
* ssh connection to remote docker daemon ([#594](https://www.github.com/knative-extensions/kn-plugin-func/issues/594)) ([e1f164d](https://www.github.com/knative-extensions/kn-plugin-func/commit/e1f164d2ca6b0e720ebcf881b8d5fd123dfd0d82))
|
||||
* validation for registry/namespace to not contain image name ([#601](https://www.github.com/knative-extensions/kn-plugin-func/issues/601)) ([cf9596c](https://www.github.com/knative-extensions/kn-plugin-func/commit/cf9596c83e6eae8229ca61a18fafb5ba4df31d6b))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ConfigMap/Secret key validation ([#623](https://www.github.com/knative-sandbox/kn-plugin-func/issues/623)) ([0ed1e81](https://www.github.com/knative-sandbox/kn-plugin-func/commit/0ed1e816920b3e750c0aa0ed25fd1e0308e80a2e))
|
||||
* Environment values -> Environment variables ([#622](https://www.github.com/knative-sandbox/kn-plugin-func/issues/622)) ([ac9de9d](https://www.github.com/knative-sandbox/kn-plugin-func/commit/ac9de9dfc68969ecb825c9ee2a92aa9918ae5ea7))
|
||||
* hide a fmt.Println behind verbose flag ([#538](https://www.github.com/knative-sandbox/kn-plugin-func/issues/538)) ([ad4607b](https://www.github.com/knative-sandbox/kn-plugin-func/commit/ad4607bd50ae0c41ba0792d46318757089239de4))
|
||||
* improve error message when invalid function name is used ([#567](https://www.github.com/knative-sandbox/kn-plugin-func/issues/567)) ([0e3c676](https://www.github.com/knative-sandbox/kn-plugin-func/commit/0e3c6764ef716cf24a3f60676e139d0c61161693))
|
||||
* registry URL comparison ([#549](https://www.github.com/knative-sandbox/kn-plugin-func/issues/549)) ([b10c484](https://www.github.com/knative-sandbox/kn-plugin-func/commit/b10c48453cc5817c4c28077be13fc03baee5d818))
|
||||
* stop the progress ticker after build completes ([#544](https://www.github.com/knative-sandbox/kn-plugin-func/issues/544)) ([4f3e5fd](https://www.github.com/knative-sandbox/kn-plugin-func/commit/4f3e5fdb7a40a3419d8d731d5a0c916b81af069b))
|
||||
* update-pkger.sh sed error on osX ([#541](https://www.github.com/knative-sandbox/kn-plugin-func/issues/541)) ([25f8b4d](https://www.github.com/knative-sandbox/kn-plugin-func/commit/25f8b4d6ead2f47c3ab6541e2bdb5016b4a423aa))
|
||||
* ConfigMap/Secret key validation ([#623](https://www.github.com/knative-extensions/kn-plugin-func/issues/623)) ([0ed1e81](https://www.github.com/knative-extensions/kn-plugin-func/commit/0ed1e816920b3e750c0aa0ed25fd1e0308e80a2e))
|
||||
* Environment values -> Environment variables ([#622](https://www.github.com/knative-extensions/kn-plugin-func/issues/622)) ([ac9de9d](https://www.github.com/knative-extensions/kn-plugin-func/commit/ac9de9dfc68969ecb825c9ee2a92aa9918ae5ea7))
|
||||
* hide a fmt.Println behind verbose flag ([#538](https://www.github.com/knative-extensions/kn-plugin-func/issues/538)) ([ad4607b](https://www.github.com/knative-extensions/kn-plugin-func/commit/ad4607bd50ae0c41ba0792d46318757089239de4))
|
||||
* improve error message when invalid function name is used ([#567](https://www.github.com/knative-extensions/kn-plugin-func/issues/567)) ([0e3c676](https://www.github.com/knative-extensions/kn-plugin-func/commit/0e3c6764ef716cf24a3f60676e139d0c61161693))
|
||||
* registry URL comparison ([#549](https://www.github.com/knative-extensions/kn-plugin-func/issues/549)) ([b10c484](https://www.github.com/knative-extensions/kn-plugin-func/commit/b10c48453cc5817c4c28077be13fc03baee5d818))
|
||||
* stop the progress ticker after build completes ([#544](https://www.github.com/knative-extensions/kn-plugin-func/issues/544)) ([4f3e5fd](https://www.github.com/knative-extensions/kn-plugin-func/commit/4f3e5fdb7a40a3419d8d731d5a0c916b81af069b))
|
||||
* update-pkger.sh sed error on osX ([#541](https://www.github.com/knative-extensions/kn-plugin-func/issues/541)) ([25f8b4d](https://www.github.com/knative-extensions/kn-plugin-func/commit/25f8b4d6ead2f47c3ab6541e2bdb5016b4a423aa))
|
||||
|
||||
## [0.18.0](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.17.1...v0.18.0) (2021-09-16)
|
||||
## [0.18.0](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.17.1...v0.18.0) (2021-09-16)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -255,61 +255,61 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* allow language packs to set function metadata ([#465](https://www.github.com/knative-sandbox/kn-plugin-func/issues/465)) ([48f40c3](https://www.github.com/knative-sandbox/kn-plugin-func/commit/48f40c35e3a239d09d6a87fc4603ad21db46bc37))
|
||||
* builders/buildpacks configured in client ([#495](https://www.github.com/knative-sandbox/kn-plugin-func/issues/495)) ([668804e](https://www.github.com/knative-sandbox/kn-plugin-func/commit/668804e53e76ce153a887289efb2b05f88203a1f))
|
||||
* change `describe` command to `info` ([#474](https://www.github.com/knative-sandbox/kn-plugin-func/issues/474)) ([10a0757](https://www.github.com/knative-sandbox/kn-plugin-func/commit/10a07578e9f6ab6bbbb8028633b37e3400fd22bb))
|
||||
* client effective runtimes list ([#490](https://www.github.com/knative-sandbox/kn-plugin-func/issues/490)) ([e0aad6f](https://www.github.com/knative-sandbox/kn-plugin-func/commit/e0aad6f936067892e04a463f85ca46689714716c))
|
||||
* generate json schema for func.yaml ([#460](https://www.github.com/knative-sandbox/kn-plugin-func/issues/460)) ([8939f89](https://www.github.com/knative-sandbox/kn-plugin-func/commit/8939f89beae7d5b2f66bc18b921ca3059f89e629))
|
||||
* make func schema if config updated ([#468](https://www.github.com/knative-sandbox/kn-plugin-func/issues/468)) ([6ae2157](https://www.github.com/knative-sandbox/kn-plugin-func/commit/6ae215754930c8a1e1dc4b5cd0b8ef3d99bb2893))
|
||||
* move go, typescript and nodejs to paketo builders ([#485](https://www.github.com/knative-sandbox/kn-plugin-func/issues/485)) ([a4b15ad](https://www.github.com/knative-sandbox/kn-plugin-func/commit/a4b15ad9926112910251a8d74747e2db368c86e9))
|
||||
* repository and templates client api ([#475](https://www.github.com/knative-sandbox/kn-plugin-func/issues/475)) ([3f56a8f](https://www.github.com/knative-sandbox/kn-plugin-func/commit/3f56a8fd7a66b923294043bcaa68ad59b1228831))
|
||||
* repository management cli ([#514](https://www.github.com/knative-sandbox/kn-plugin-func/issues/514)) ([ae638c3](https://www.github.com/knative-sandbox/kn-plugin-func/commit/ae638c349c46c035bad74645bfc612380c871a85))
|
||||
* repository management client api ([#467](https://www.github.com/knative-sandbox/kn-plugin-func/issues/467)) ([9fd2475](https://www.github.com/knative-sandbox/kn-plugin-func/commit/9fd247557ae8ee30cc7c5f0107d80fa72fbe8086))
|
||||
* use key&value for Labels ([#472](https://www.github.com/knative-sandbox/kn-plugin-func/issues/472)) ([5569681](https://www.github.com/knative-sandbox/kn-plugin-func/commit/55696811e317a51767e09acab3d4d4e2abc6e982))
|
||||
* allow language packs to set function metadata ([#465](https://www.github.com/knative-extensions/kn-plugin-func/issues/465)) ([48f40c3](https://www.github.com/knative-extensions/kn-plugin-func/commit/48f40c35e3a239d09d6a87fc4603ad21db46bc37))
|
||||
* builders/buildpacks configured in client ([#495](https://www.github.com/knative-extensions/kn-plugin-func/issues/495)) ([668804e](https://www.github.com/knative-extensions/kn-plugin-func/commit/668804e53e76ce153a887289efb2b05f88203a1f))
|
||||
* change `describe` command to `info` ([#474](https://www.github.com/knative-extensions/kn-plugin-func/issues/474)) ([10a0757](https://www.github.com/knative-extensions/kn-plugin-func/commit/10a07578e9f6ab6bbbb8028633b37e3400fd22bb))
|
||||
* client effective runtimes list ([#490](https://www.github.com/knative-extensions/kn-plugin-func/issues/490)) ([e0aad6f](https://www.github.com/knative-extensions/kn-plugin-func/commit/e0aad6f936067892e04a463f85ca46689714716c))
|
||||
* generate json schema for func.yaml ([#460](https://www.github.com/knative-extensions/kn-plugin-func/issues/460)) ([8939f89](https://www.github.com/knative-extensions/kn-plugin-func/commit/8939f89beae7d5b2f66bc18b921ca3059f89e629))
|
||||
* make func schema if config updated ([#468](https://www.github.com/knative-extensions/kn-plugin-func/issues/468)) ([6ae2157](https://www.github.com/knative-extensions/kn-plugin-func/commit/6ae215754930c8a1e1dc4b5cd0b8ef3d99bb2893))
|
||||
* move go, typescript and nodejs to paketo builders ([#485](https://www.github.com/knative-extensions/kn-plugin-func/issues/485)) ([a4b15ad](https://www.github.com/knative-extensions/kn-plugin-func/commit/a4b15ad9926112910251a8d74747e2db368c86e9))
|
||||
* repository and templates client api ([#475](https://www.github.com/knative-extensions/kn-plugin-func/issues/475)) ([3f56a8f](https://www.github.com/knative-extensions/kn-plugin-func/commit/3f56a8fd7a66b923294043bcaa68ad59b1228831))
|
||||
* repository management cli ([#514](https://www.github.com/knative-extensions/kn-plugin-func/issues/514)) ([ae638c3](https://www.github.com/knative-extensions/kn-plugin-func/commit/ae638c349c46c035bad74645bfc612380c871a85))
|
||||
* repository management client api ([#467](https://www.github.com/knative-extensions/kn-plugin-func/issues/467)) ([9fd2475](https://www.github.com/knative-extensions/kn-plugin-func/commit/9fd247557ae8ee30cc7c5f0107d80fa72fbe8086))
|
||||
* use key&value for Labels ([#472](https://www.github.com/knative-extensions/kn-plugin-func/issues/472)) ([5569681](https://www.github.com/knative-extensions/kn-plugin-func/commit/55696811e317a51767e09acab3d4d4e2abc6e982))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `build` should honor registry specified in `-r` ([#510](https://www.github.com/knative-sandbox/kn-plugin-func/issues/510)) ([8aba038](https://www.github.com/knative-sandbox/kn-plugin-func/commit/8aba038073f5584133eb3d08ba85289800e2e770))
|
||||
* `config labels` panic ([#493](https://www.github.com/knative-sandbox/kn-plugin-func/issues/493)) ([f2efbe5](https://www.github.com/knative-sandbox/kn-plugin-func/commit/f2efbe5b42a6e0af36ecc6be429a630312e0c6e5))
|
||||
* better cleanup before pkger run ([#479](https://www.github.com/knative-sandbox/kn-plugin-func/issues/479)) ([25b1d63](https://www.github.com/knative-sandbox/kn-plugin-func/commit/25b1d63b9c1b332e1d59e494af83bdc3a1f576e9))
|
||||
* control chars on progress listener for Windows OS ([#498](https://www.github.com/knative-sandbox/kn-plugin-func/issues/498)) ([1172a85](https://www.github.com/knative-sandbox/kn-plugin-func/commit/1172a85c80f834ff3958073bc36ff4a5173c9de6))
|
||||
* enable healt checks for Quarkus ([#477](https://www.github.com/knative-sandbox/kn-plugin-func/issues/477)) ([72a1cf8](https://www.github.com/knative-sandbox/kn-plugin-func/commit/72a1cf885e092340295cc6ace3580e7420640cda))
|
||||
* fast-fail on create if Function already exists ([#496](https://www.github.com/knative-sandbox/kn-plugin-func/issues/496)) ([25f7007](https://www.github.com/knative-sandbox/kn-plugin-func/commit/25f7007300c020b5a1d336740a2bbc2f546bf3da))
|
||||
* regenerate pkged.go ([#478](https://www.github.com/knative-sandbox/kn-plugin-func/issues/478)) ([c7b3af4](https://www.github.com/knative-sandbox/kn-plugin-func/commit/c7b3af41b8cac0b9edfb96d3a01230d2606e320a))
|
||||
* removal of repositories ([#524](https://www.github.com/knative-sandbox/kn-plugin-func/issues/524)) ([90c60b6](https://www.github.com/knative-sandbox/kn-plugin-func/commit/90c60b693d6b2dbb2c8edee27a7cf7b6e8d1c399))
|
||||
* support nested subdirs in remote templates ([#482](https://www.github.com/knative-sandbox/kn-plugin-func/issues/482)) ([fcf9e77](https://www.github.com/knative-sandbox/kn-plugin-func/commit/fcf9e77cb93808d28d0c60f3a0959fac605771fb))
|
||||
* use full image names ([#535](https://www.github.com/knative-sandbox/kn-plugin-func/issues/535)) ([16ee28c](https://www.github.com/knative-sandbox/kn-plugin-func/commit/16ee28c83debcc19092abb250ef20354eca09710))
|
||||
* `build` should honor registry specified in `-r` ([#510](https://www.github.com/knative-extensions/kn-plugin-func/issues/510)) ([8aba038](https://www.github.com/knative-extensions/kn-plugin-func/commit/8aba038073f5584133eb3d08ba85289800e2e770))
|
||||
* `config labels` panic ([#493](https://www.github.com/knative-extensions/kn-plugin-func/issues/493)) ([f2efbe5](https://www.github.com/knative-extensions/kn-plugin-func/commit/f2efbe5b42a6e0af36ecc6be429a630312e0c6e5))
|
||||
* better cleanup before pkger run ([#479](https://www.github.com/knative-extensions/kn-plugin-func/issues/479)) ([25b1d63](https://www.github.com/knative-extensions/kn-plugin-func/commit/25b1d63b9c1b332e1d59e494af83bdc3a1f576e9))
|
||||
* control chars on progress listener for Windows OS ([#498](https://www.github.com/knative-extensions/kn-plugin-func/issues/498)) ([1172a85](https://www.github.com/knative-extensions/kn-plugin-func/commit/1172a85c80f834ff3958073bc36ff4a5173c9de6))
|
||||
* enable healt checks for Quarkus ([#477](https://www.github.com/knative-extensions/kn-plugin-func/issues/477)) ([72a1cf8](https://www.github.com/knative-extensions/kn-plugin-func/commit/72a1cf885e092340295cc6ace3580e7420640cda))
|
||||
* fast-fail on create if Function already exists ([#496](https://www.github.com/knative-extensions/kn-plugin-func/issues/496)) ([25f7007](https://www.github.com/knative-extensions/kn-plugin-func/commit/25f7007300c020b5a1d336740a2bbc2f546bf3da))
|
||||
* regenerate pkged.go ([#478](https://www.github.com/knative-extensions/kn-plugin-func/issues/478)) ([c7b3af4](https://www.github.com/knative-extensions/kn-plugin-func/commit/c7b3af41b8cac0b9edfb96d3a01230d2606e320a))
|
||||
* removal of repositories ([#524](https://www.github.com/knative-extensions/kn-plugin-func/issues/524)) ([90c60b6](https://www.github.com/knative-extensions/kn-plugin-func/commit/90c60b693d6b2dbb2c8edee27a7cf7b6e8d1c399))
|
||||
* support nested subdirs in remote templates ([#482](https://www.github.com/knative-extensions/kn-plugin-func/issues/482)) ([fcf9e77](https://www.github.com/knative-extensions/kn-plugin-func/commit/fcf9e77cb93808d28d0c60f3a0959fac605771fb))
|
||||
* use full image names ([#535](https://www.github.com/knative-extensions/kn-plugin-func/issues/535)) ([16ee28c](https://www.github.com/knative-extensions/kn-plugin-func/commit/16ee28c83debcc19092abb250ef20354eca09710))
|
||||
|
||||
### [0.17.1](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.17.0...v0.17.1) (2021-08-05)
|
||||
### [0.17.1](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.17.0...v0.17.1) (2021-08-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* hide progress indicator if asking for creds ([#458](https://www.github.com/knative-sandbox/kn-plugin-func/issues/458)) ([79e2234](https://www.github.com/knative-sandbox/kn-plugin-func/commit/79e2234cbc62319f35b18a9b2a39ca4dffe89d4d))
|
||||
* use ascii chars in progress indicator on win ([#459](https://www.github.com/knative-sandbox/kn-plugin-func/issues/459)) ([6fd42a4](https://www.github.com/knative-sandbox/kn-plugin-func/commit/6fd42a421ea58a4e9e1b6b6bff3f97d1da99d349))
|
||||
* hide progress indicator if asking for creds ([#458](https://www.github.com/knative-extensions/kn-plugin-func/issues/458)) ([79e2234](https://www.github.com/knative-extensions/kn-plugin-func/commit/79e2234cbc62319f35b18a9b2a39ca4dffe89d4d))
|
||||
* use ascii chars in progress indicator on win ([#459](https://www.github.com/knative-extensions/kn-plugin-func/issues/459)) ([6fd42a4](https://www.github.com/knative-extensions/kn-plugin-func/commit/6fd42a421ea58a4e9e1b6b6bff3f97d1da99d349))
|
||||
|
||||
## [0.17.0](https://www.github.com/knative-sandbox/kn-plugin-func/compare/v0.16.0...v0.17.0) (2021-08-03)
|
||||
## [0.17.0](https://www.github.com/knative-extensions/kn-plugin-func/compare/v0.16.0...v0.17.0) (2021-08-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add proper example of configuring Rust functions. ([#436](https://www.github.com/knative-sandbox/kn-plugin-func/issues/436)) ([7656c40](https://www.github.com/knative-sandbox/kn-plugin-func/commit/7656c4097283ed54b9e5f0472947cff931973365))
|
||||
* add support for labels in func.yaml ([#373](https://www.github.com/knative-sandbox/kn-plugin-func/issues/373)) ([0dba677](https://www.github.com/knative-sandbox/kn-plugin-func/commit/0dba67751e5a4c594701d674b44b101a043e9a2c))
|
||||
* Configure Rust functions ([#430](https://www.github.com/knative-sandbox/kn-plugin-func/issues/430)) ([a08b843](https://www.github.com/knative-sandbox/kn-plugin-func/commit/a08b843a9c2639d6b237f4248341b35f3bd8b954))
|
||||
* print emit response output if it's a cloudevent ([#444](https://www.github.com/knative-sandbox/kn-plugin-func/issues/444)) ([a25b723](https://www.github.com/knative-sandbox/kn-plugin-func/commit/a25b723dbcd50d544566a385441cbdd883017947))
|
||||
* remote template repositories ([#437](https://www.github.com/knative-sandbox/kn-plugin-func/issues/437)) ([9db1a3d](https://www.github.com/knative-sandbox/kn-plugin-func/commit/9db1a3d902016d59e60b732de43bdf4be198334f))
|
||||
* Add proper example of configuring Rust functions. ([#436](https://www.github.com/knative-extensions/kn-plugin-func/issues/436)) ([7656c40](https://www.github.com/knative-extensions/kn-plugin-func/commit/7656c4097283ed54b9e5f0472947cff931973365))
|
||||
* add support for labels in func.yaml ([#373](https://www.github.com/knative-extensions/kn-plugin-func/issues/373)) ([0dba677](https://www.github.com/knative-extensions/kn-plugin-func/commit/0dba67751e5a4c594701d674b44b101a043e9a2c))
|
||||
* Configure Rust functions ([#430](https://www.github.com/knative-extensions/kn-plugin-func/issues/430)) ([a08b843](https://www.github.com/knative-extensions/kn-plugin-func/commit/a08b843a9c2639d6b237f4248341b35f3bd8b954))
|
||||
* print emit response output if it's a cloudevent ([#444](https://www.github.com/knative-extensions/kn-plugin-func/issues/444)) ([a25b723](https://www.github.com/knative-extensions/kn-plugin-func/commit/a25b723dbcd50d544566a385441cbdd883017947))
|
||||
* remote template repositories ([#437](https://www.github.com/knative-extensions/kn-plugin-func/issues/437)) ([9db1a3d](https://www.github.com/knative-extensions/kn-plugin-func/commit/9db1a3d902016d59e60b732de43bdf4be198334f))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* closing stdout ([6f40b29](https://www.github.com/knative-sandbox/kn-plugin-func/commit/6f40b29d3e02193c51317a29737c20dc11730c5a))
|
||||
* do not trust builder when using podman ([#420](https://www.github.com/knative-sandbox/kn-plugin-func/issues/420)) ([894f4fe](https://www.github.com/knative-sandbox/kn-plugin-func/commit/894f4febda1d7da5d3f47e1003b29b339b1f8cd4))
|
||||
* fix unit tests for Node.js event templates ([#438](https://www.github.com/knative-sandbox/kn-plugin-func/issues/438)) ([d71532a](https://www.github.com/knative-sandbox/kn-plugin-func/commit/d71532a070b24ec70dd5b77221e11b53bd300e8d))
|
||||
* unnecessary template repackaging ([#449](https://www.github.com/knative-sandbox/kn-plugin-func/issues/449)) ([435d1ac](https://www.github.com/knative-sandbox/kn-plugin-func/commit/435d1ac2a39c4e3abf1a6518b05be3151d132a57))
|
||||
* update builders version ([#421](https://www.github.com/knative-sandbox/kn-plugin-func/issues/421)) ([771a230](https://www.github.com/knative-sandbox/kn-plugin-func/commit/771a2307a13d105a188a0fd2c2fa843f3a535277))
|
||||
* closing stdout ([6f40b29](https://www.github.com/knative-extensions/kn-plugin-func/commit/6f40b29d3e02193c51317a29737c20dc11730c5a))
|
||||
* do not trust builder when using podman ([#420](https://www.github.com/knative-extensions/kn-plugin-func/issues/420)) ([894f4fe](https://www.github.com/knative-extensions/kn-plugin-func/commit/894f4febda1d7da5d3f47e1003b29b339b1f8cd4))
|
||||
* fix unit tests for Node.js event templates ([#438](https://www.github.com/knative-extensions/kn-plugin-func/issues/438)) ([d71532a](https://www.github.com/knative-extensions/kn-plugin-func/commit/d71532a070b24ec70dd5b77221e11b53bd300e8d))
|
||||
* unnecessary template repackaging ([#449](https://www.github.com/knative-extensions/kn-plugin-func/issues/449)) ([435d1ac](https://www.github.com/knative-extensions/kn-plugin-func/commit/435d1ac2a39c4e3abf1a6518b05be3151d132a57))
|
||||
* update builders version ([#421](https://www.github.com/knative-extensions/kn-plugin-func/issues/421)) ([771a230](https://www.github.com/knative-extensions/kn-plugin-func/commit/771a2307a13d105a188a0fd2c2fa843f3a535277))
|
||||
|
||||
## [0.16.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.15.1...v0.16.0) (2021-06-23)
|
||||
## [0.16.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.15.1...v0.16.0) (2021-06-23)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -319,37 +319,37 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* `func config envs` - interactive prompt ([#396](https://github.com/knative-sandbox/kn-plugin-func/issues/396)) ([83a9ca6](https://github.com/knative-sandbox/kn-plugin-func/commit/83a9ca684f1b74458b4804fe0e0efe5e95507077))
|
||||
* `func config volumes` - interactive prompt ([#391](https://github.com/knative-sandbox/kn-plugin-func/issues/391)) ([4ba95b6](https://github.com/knative-sandbox/kn-plugin-func/commit/4ba95b69a8926ef56773166951ab8fa577111d37))
|
||||
* add a URL output type for `func describe` ([#389](https://github.com/knative-sandbox/kn-plugin-func/issues/389)) ([947fcaa](https://github.com/knative-sandbox/kn-plugin-func/commit/947fcaa968a90efed4b6037cafa19e8fadda1fc7)), closes [#387](https://github.com/knative-sandbox/kn-plugin-func/issues/387)
|
||||
* allow setting autoscaling options to deployed KService ([#374](https://github.com/knative-sandbox/kn-plugin-func/issues/374)) ([a937c49](https://github.com/knative-sandbox/kn-plugin-func/commit/a937c490b7e1ad31c3596f91c310c3f4560329fd))
|
||||
* allow setting resource requests/limits ([#386](https://github.com/knative-sandbox/kn-plugin-func/issues/386)) ([12c5cda](https://github.com/knative-sandbox/kn-plugin-func/commit/12c5cda8e2157a775e9fc0bb14fc051c5119f86a))
|
||||
* reference ConfigMaps in `envs` and `volumes` sections in config ([#371](https://github.com/knative-sandbox/kn-plugin-func/issues/371)) ([1dbb5ae](https://github.com/knative-sandbox/kn-plugin-func/commit/1dbb5aecbf73cd77a648eaff5e52c1c3ce282a67))
|
||||
* reference Secrets in `envs` and `volumes` sections in config ([#369](https://github.com/knative-sandbox/kn-plugin-func/issues/369)) ([9d7fd34](https://github.com/knative-sandbox/kn-plugin-func/commit/9d7fd346495b119e895747d747c1c0a5bacb988e))
|
||||
* Rust templates ([#376](https://github.com/knative-sandbox/kn-plugin-func/issues/376)) ([4711638](https://github.com/knative-sandbox/kn-plugin-func/commit/4711638495692e5b8fc1ccca34000c44afa3832c))
|
||||
* typed errors for templates use cases ([40f1027](https://github.com/knative-sandbox/kn-plugin-func/commit/40f10277a4efc3239bbec7a35586c3eabf3337ee))
|
||||
* `func config envs` - interactive prompt ([#396](https://github.com/knative-extensions/kn-plugin-func/issues/396)) ([83a9ca6](https://github.com/knative-extensions/kn-plugin-func/commit/83a9ca684f1b74458b4804fe0e0efe5e95507077))
|
||||
* `func config volumes` - interactive prompt ([#391](https://github.com/knative-extensions/kn-plugin-func/issues/391)) ([4ba95b6](https://github.com/knative-extensions/kn-plugin-func/commit/4ba95b69a8926ef56773166951ab8fa577111d37))
|
||||
* add a URL output type for `func describe` ([#389](https://github.com/knative-extensions/kn-plugin-func/issues/389)) ([947fcaa](https://github.com/knative-extensions/kn-plugin-func/commit/947fcaa968a90efed4b6037cafa19e8fadda1fc7)), closes [#387](https://github.com/knative-extensions/kn-plugin-func/issues/387)
|
||||
* allow setting autoscaling options to deployed KService ([#374](https://github.com/knative-extensions/kn-plugin-func/issues/374)) ([a937c49](https://github.com/knative-extensions/kn-plugin-func/commit/a937c490b7e1ad31c3596f91c310c3f4560329fd))
|
||||
* allow setting resource requests/limits ([#386](https://github.com/knative-extensions/kn-plugin-func/issues/386)) ([12c5cda](https://github.com/knative-extensions/kn-plugin-func/commit/12c5cda8e2157a775e9fc0bb14fc051c5119f86a))
|
||||
* reference ConfigMaps in `envs` and `volumes` sections in config ([#371](https://github.com/knative-extensions/kn-plugin-func/issues/371)) ([1dbb5ae](https://github.com/knative-extensions/kn-plugin-func/commit/1dbb5aecbf73cd77a648eaff5e52c1c3ce282a67))
|
||||
* reference Secrets in `envs` and `volumes` sections in config ([#369](https://github.com/knative-extensions/kn-plugin-func/issues/369)) ([9d7fd34](https://github.com/knative-extensions/kn-plugin-func/commit/9d7fd346495b119e895747d747c1c0a5bacb988e))
|
||||
* Rust templates ([#376](https://github.com/knative-extensions/kn-plugin-func/issues/376)) ([4711638](https://github.com/knative-extensions/kn-plugin-func/commit/4711638495692e5b8fc1ccca34000c44afa3832c))
|
||||
* typed errors for templates use cases ([40f1027](https://github.com/knative-extensions/kn-plugin-func/commit/40f10277a4efc3239bbec7a35586c3eabf3337ee))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* disable selinux labeling ([6e8517c](https://github.com/knative-sandbox/kn-plugin-func/commit/6e8517c023fa815c616606640657344785dbe4ff))
|
||||
* password read on windows ([84f896b](https://github.com/knative-sandbox/kn-plugin-func/commit/84f896b3298fffe9c8aeec2706c83b6a0fb48141))
|
||||
* use credsStore ([88ea081](https://github.com/knative-sandbox/kn-plugin-func/commit/88ea081cc0addb644ca4a575735a6dd3393197a2))
|
||||
* disable selinux labeling ([6e8517c](https://github.com/knative-extensions/kn-plugin-func/commit/6e8517c023fa815c616606640657344785dbe4ff))
|
||||
* password read on windows ([84f896b](https://github.com/knative-extensions/kn-plugin-func/commit/84f896b3298fffe9c8aeec2706c83b6a0fb48141))
|
||||
* use credsStore ([88ea081](https://github.com/knative-extensions/kn-plugin-func/commit/88ea081cc0addb644ca4a575735a6dd3393197a2))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* change --trigger and --templates flags ([ce29ff6](https://github.com/knative-sandbox/kn-plugin-func/commit/ce29ff6285d68bc008fbf0cfbd956982044104bc))
|
||||
* function signatures implied from trigger ([b30e883](https://github.com/knative-sandbox/kn-plugin-func/commit/b30e883e671477ebfa217df03e6825778e84a3df))
|
||||
* change --trigger and --templates flags ([ce29ff6](https://github.com/knative-extensions/kn-plugin-func/commit/ce29ff6285d68bc008fbf0cfbd956982044104bc))
|
||||
* function signatures implied from trigger ([b30e883](https://github.com/knative-extensions/kn-plugin-func/commit/b30e883e671477ebfa217df03e6825778e84a3df))
|
||||
|
||||
### [0.15.1](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.15.0...v0.15.1) (2021-05-27)
|
||||
### [0.15.1](https://github.com/knative-extensions/kn-plugin-func/compare/v0.15.0...v0.15.1) (2021-05-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Revert "chore: bump Knative deps to 0.22.0 ([#358](https://github.com/knative-sandbox/kn-plugin-func/issues/358))" ([#366](https://github.com/knative-sandbox/kn-plugin-func/issues/366)) ([72584ce](https://github.com/knative-sandbox/kn-plugin-func/commit/72584ced0dc3af86852f56ce36171ba567481b41))
|
||||
* Revert "chore: bump Knative deps to 0.22.0 ([#358](https://github.com/knative-extensions/kn-plugin-func/issues/358))" ([#366](https://github.com/knative-extensions/kn-plugin-func/issues/366)) ([72584ce](https://github.com/knative-extensions/kn-plugin-func/commit/72584ced0dc3af86852f56ce36171ba567481b41))
|
||||
|
||||
## [0.15.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.14.0...v0.15.0) (2021-05-26)
|
||||
## [0.15.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.14.0...v0.15.0) (2021-05-26)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -358,20 +358,20 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* add 'kn func emit' command ([#332](https://github.com/knative-sandbox/kn-plugin-func/issues/332)) ([49594d9](https://github.com/knative-sandbox/kn-plugin-func/commit/49594d976627c593ff18e42086199225ddcf5130))
|
||||
* add typescript templates ([#355](https://github.com/knative-sandbox/kn-plugin-func/issues/355)) ([d3eafe2](https://github.com/knative-sandbox/kn-plugin-func/commit/d3eafe2a8451ebc28124b913f03c12e9359d5e30))
|
||||
* add 'kn func emit' command ([#332](https://github.com/knative-extensions/kn-plugin-func/issues/332)) ([49594d9](https://github.com/knative-extensions/kn-plugin-func/commit/49594d976627c593ff18e42086199225ddcf5130))
|
||||
* add typescript templates ([#355](https://github.com/knative-extensions/kn-plugin-func/issues/355)) ([d3eafe2](https://github.com/knative-extensions/kn-plugin-func/commit/d3eafe2a8451ebc28124b913f03c12e9359d5e30))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* minor typos in node template docs ([#351](https://github.com/knative-sandbox/kn-plugin-func/issues/351)) ([ea0a75a](https://github.com/knative-sandbox/kn-plugin-func/commit/ea0a75a7ccb6d00b8c859ff4cd311ad33fb8dbc3))
|
||||
* minor typos in node template docs ([#351](https://github.com/knative-extensions/kn-plugin-func/issues/351)) ([ea0a75a](https://github.com/knative-extensions/kn-plugin-func/commit/ea0a75a7ccb6d00b8c859ff4cd311ad33fb8dbc3))
|
||||
|
||||
|
||||
### src
|
||||
|
||||
* **templates:** modify the nodejs event template to accept a cloudevent ([#356](https://github.com/knative-sandbox/kn-plugin-func/issues/356)) ([caf0659](https://github.com/knative-sandbox/kn-plugin-func/commit/caf0659900a79650bb11877ffaeadbc30be9f922))
|
||||
* **templates:** modify the nodejs event template to accept a cloudevent ([#356](https://github.com/knative-extensions/kn-plugin-func/issues/356)) ([caf0659](https://github.com/knative-extensions/kn-plugin-func/commit/caf0659900a79650bb11877ffaeadbc30be9f922))
|
||||
|
||||
## [0.14.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.13.0...v0.14.0) (2021-05-12)
|
||||
## [0.14.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.13.0...v0.14.0) (2021-05-12)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -380,9 +380,9 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### src
|
||||
|
||||
* revert bump to go 1.16 and template changes ([#340](https://github.com/knative-sandbox/kn-plugin-func/issues/340)) ([2b025df](https://github.com/knative-sandbox/kn-plugin-func/commit/2b025df19942e990050ef344784662fe77fd7309))
|
||||
* revert bump to go 1.16 and template changes ([#340](https://github.com/knative-extensions/kn-plugin-func/issues/340)) ([2b025df](https://github.com/knative-extensions/kn-plugin-func/commit/2b025df19942e990050ef344784662fe77fd7309))
|
||||
|
||||
## [0.13.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.12.1...v0.13.0) (2021-05-12)
|
||||
## [0.13.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.12.1...v0.13.0) (2021-05-12)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -391,88 +391,88 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* add support for annotations in func.yaml ([#314](https://github.com/knative-sandbox/kn-plugin-func/issues/314)) ([5feb0e2](https://github.com/knative-sandbox/kn-plugin-func/commit/5feb0e20f366f8dc46f339257d87419bc852753c))
|
||||
* add/improve spinner for build and deploy ([#322](https://github.com/knative-sandbox/kn-plugin-func/issues/322)) ([857b0fd](https://github.com/knative-sandbox/kn-plugin-func/commit/857b0fd19d2a716c804426196e907a3ad31d559e))
|
||||
* create templates archive on go generate ([63b7f11](https://github.com/knative-sandbox/kn-plugin-func/commit/63b7f1147176ce5cfd21c3b74094fcc8154298df))
|
||||
* function name matches KService name ([#317](https://github.com/knative-sandbox/kn-plugin-func/issues/317)) ([541e858](https://github.com/knative-sandbox/kn-plugin-func/commit/541e8586f7348fa92ee83f246ef34730b1801b9f))
|
||||
* positive error when runtimme or template unrecognized ([acc56b0](https://github.com/knative-sandbox/kn-plugin-func/commit/acc56b0900113ca68270bd3ac68310864e42b5a7))
|
||||
* preserve file modes using in-memory tar FS ([7dc772e](https://github.com/knative-sandbox/kn-plugin-func/commit/7dc772ec62536fc77b84b16550bf7d2a1f0b6a09))
|
||||
* support windows paths in embedded templates FS ([c2b2168](https://github.com/knative-sandbox/kn-plugin-func/commit/c2b216857bcc1e18555a2e41fa3ad675e75cf1c3))
|
||||
* usage of local evnvvar in func cfg file ([7f8e595](https://github.com/knative-sandbox/kn-plugin-func/commit/7f8e5954a939563486661a98198b22f41eebc195))
|
||||
* add support for annotations in func.yaml ([#314](https://github.com/knative-extensions/kn-plugin-func/issues/314)) ([5feb0e2](https://github.com/knative-extensions/kn-plugin-func/commit/5feb0e20f366f8dc46f339257d87419bc852753c))
|
||||
* add/improve spinner for build and deploy ([#322](https://github.com/knative-extensions/kn-plugin-func/issues/322)) ([857b0fd](https://github.com/knative-extensions/kn-plugin-func/commit/857b0fd19d2a716c804426196e907a3ad31d559e))
|
||||
* create templates archive on go generate ([63b7f11](https://github.com/knative-extensions/kn-plugin-func/commit/63b7f1147176ce5cfd21c3b74094fcc8154298df))
|
||||
* function name matches KService name ([#317](https://github.com/knative-extensions/kn-plugin-func/issues/317)) ([541e858](https://github.com/knative-extensions/kn-plugin-func/commit/541e8586f7348fa92ee83f246ef34730b1801b9f))
|
||||
* positive error when runtimme or template unrecognized ([acc56b0](https://github.com/knative-extensions/kn-plugin-func/commit/acc56b0900113ca68270bd3ac68310864e42b5a7))
|
||||
* preserve file modes using in-memory tar FS ([7dc772e](https://github.com/knative-extensions/kn-plugin-func/commit/7dc772ec62536fc77b84b16550bf7d2a1f0b6a09))
|
||||
* support windows paths in embedded templates FS ([c2b2168](https://github.com/knative-extensions/kn-plugin-func/commit/c2b216857bcc1e18555a2e41fa3ad675e75cf1c3))
|
||||
* usage of local evnvvar in func cfg file ([7f8e595](https://github.com/knative-extensions/kn-plugin-func/commit/7f8e5954a939563486661a98198b22f41eebc195))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* added checks on delete command test for lint ([94e387c](https://github.com/knative-sandbox/kn-plugin-func/commit/94e387c9326aed79ede95f36b97da4de97c42dec))
|
||||
* default for `--builder` flag ([06455f4](https://github.com/knative-sandbox/kn-plugin-func/commit/06455f4bac02e8581ae4471e72909ba9fe7dbd4d))
|
||||
* func delete with explicity name as argument ([#323](https://github.com/knative-sandbox/kn-plugin-func/issues/323)) with strict validation ([8ab0ba2](https://github.com/knative-sandbox/kn-plugin-func/commit/8ab0ba243ae4c40867a2426b2ca965559a03cd53))
|
||||
* lint issues ([895872a](https://github.com/knative-sandbox/kn-plugin-func/commit/895872aee76b44be739bd0eafb9f2cdcdc137494))
|
||||
* added checks on delete command test for lint ([94e387c](https://github.com/knative-extensions/kn-plugin-func/commit/94e387c9326aed79ede95f36b97da4de97c42dec))
|
||||
* default for `--builder` flag ([06455f4](https://github.com/knative-extensions/kn-plugin-func/commit/06455f4bac02e8581ae4471e72909ba9fe7dbd4d))
|
||||
* func delete with explicit name as argument ([#323](https://github.com/knative-extensions/kn-plugin-func/issues/323)) with strict validation ([8ab0ba2](https://github.com/knative-extensions/kn-plugin-func/commit/8ab0ba243ae4c40867a2426b2ca965559a03cd53))
|
||||
* lint issues ([895872a](https://github.com/knative-extensions/kn-plugin-func/commit/895872aee76b44be739bd0eafb9f2cdcdc137494))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* change envVars to env in func.yaml ([#316](https://github.com/knative-sandbox/kn-plugin-func/issues/316)) ([89ff286](https://github.com/knative-sandbox/kn-plugin-func/commit/89ff286a1f3afae655a2c724a05cb3bc3c281786))
|
||||
* change envVars to env in func.yaml ([#316](https://github.com/knative-extensions/kn-plugin-func/issues/316)) ([89ff286](https://github.com/knative-extensions/kn-plugin-func/commit/89ff286a1f3afae655a2c724a05cb3bc3c281786))
|
||||
|
||||
### [0.12.1](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.12.0...v0.12.1) (2021-04-14)
|
||||
### [0.12.1](https://github.com/knative-extensions/kn-plugin-func/compare/v0.12.0...v0.12.1) (2021-04-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* build needs to use legacy jar ([129dc5a](https://github.com/knative-sandbox/kn-plugin-func/commit/129dc5a8348dc8e4e14f5891871cf6b50ae35ccc))
|
||||
* build needs to use legacy jar ([129dc5a](https://github.com/knative-extensions/kn-plugin-func/commit/129dc5a8348dc8e4e14f5891871cf6b50ae35ccc))
|
||||
|
||||
## [0.12.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.11.0...v0.12.0) (2021-03-30)
|
||||
## [0.12.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.11.0...v0.12.0) (2021-03-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add --build (default: true) flag to func deploy ([8a91cac](https://github.com/knative-sandbox/kn-plugin-func/commit/8a91cac6cc78b5cf56d5158f3eb03a4076a34ffe))
|
||||
* basic lifecycle integraiton tests ([8edd0df](https://github.com/knative-sandbox/kn-plugin-func/commit/8edd0df836055b33473f9a7774e8ae755f46ac2e))
|
||||
* integration tests target ([ddf4ab8](https://github.com/knative-sandbox/kn-plugin-func/commit/ddf4ab86c46912f78e56a52a14efcf89fd187103))
|
||||
* local cluster allocation, configuration and teardown ([9c499b6](https://github.com/knative-sandbox/kn-plugin-func/commit/9c499b69c4991b86e51127081cee7fb0fc34d554))
|
||||
* using custom docker daemon (e.g podman) ([6d2d8c6](https://github.com/knative-sandbox/kn-plugin-func/commit/6d2d8c63b01e12f6cf277c2cd18c3f7298ce86ab))
|
||||
* add --build (default: true) flag to func deploy ([8a91cac](https://github.com/knative-extensions/kn-plugin-func/commit/8a91cac6cc78b5cf56d5158f3eb03a4076a34ffe))
|
||||
* basic lifecycle integraiton tests ([8edd0df](https://github.com/knative-extensions/kn-plugin-func/commit/8edd0df836055b33473f9a7774e8ae755f46ac2e))
|
||||
* integration tests target ([ddf4ab8](https://github.com/knative-extensions/kn-plugin-func/commit/ddf4ab86c46912f78e56a52a14efcf89fd187103))
|
||||
* local cluster allocation, configuration and teardown ([9c499b6](https://github.com/knative-extensions/kn-plugin-func/commit/9c499b69c4991b86e51127081cee7fb0fc34d554))
|
||||
* using custom docker daemon (e.g podman) ([6d2d8c6](https://github.com/knative-extensions/kn-plugin-func/commit/6d2d8c63b01e12f6cf277c2cd18c3f7298ce86ab))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `func deploy` uses Docker API, not binary ([dc2fbee](https://github.com/knative-sandbox/kn-plugin-func/commit/dc2fbee67f7f2304bece83a9b4d4f051ed19cd61))
|
||||
* `func run` now uses Docker API, not binary ([db0945e](https://github.com/knative-sandbox/kn-plugin-func/commit/db0945ed3ecb9e6e4283a0cb478d39657c6803dc))
|
||||
* compare service names in integraiton tests ([1551d69](https://github.com/knative-sandbox/kn-plugin-func/commit/1551d69b5d287becaafdf3d5b99a6ba8da926fa6))
|
||||
* exposed port ([7ed2e86](https://github.com/knative-sandbox/kn-plugin-func/commit/7ed2e86d9672f285c1def490a3d325ceb9e8471f))
|
||||
* increase remove timeout to 120s ([80e366b](https://github.com/knative-sandbox/kn-plugin-func/commit/80e366b14234c184932d91db4188bdabb0742e7a))
|
||||
* sprint-boot template ([38fd673](https://github.com/knative-sandbox/kn-plugin-func/commit/38fd673fdbef1094558b32910a42fcdff2d8bb0c))
|
||||
* update pack dependency ([c3c2165](https://github.com/knative-sandbox/kn-plugin-func/commit/c3c21657b2bc3cba9e4ba87864d8fe0c5d4e43af))
|
||||
* `func deploy` uses Docker API, not binary ([dc2fbee](https://github.com/knative-extensions/kn-plugin-func/commit/dc2fbee67f7f2304bece83a9b4d4f051ed19cd61))
|
||||
* `func run` now uses Docker API, not binary ([db0945e](https://github.com/knative-extensions/kn-plugin-func/commit/db0945ed3ecb9e6e4283a0cb478d39657c6803dc))
|
||||
* compare service names in integraiton tests ([1551d69](https://github.com/knative-extensions/kn-plugin-func/commit/1551d69b5d287becaafdf3d5b99a6ba8da926fa6))
|
||||
* exposed port ([7ed2e86](https://github.com/knative-extensions/kn-plugin-func/commit/7ed2e86d9672f285c1def490a3d325ceb9e8471f))
|
||||
* increase remove timeout to 120s ([80e366b](https://github.com/knative-extensions/kn-plugin-func/commit/80e366b14234c184932d91db4188bdabb0742e7a))
|
||||
* sprint-boot template ([38fd673](https://github.com/knative-extensions/kn-plugin-func/commit/38fd673fdbef1094558b32910a42fcdff2d8bb0c))
|
||||
* update pack dependency ([c3c2165](https://github.com/knative-extensions/kn-plugin-func/commit/c3c21657b2bc3cba9e4ba87864d8fe0c5d4e43af))
|
||||
|
||||
## [0.11.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.10.0...v0.11.0) (2021-01-21)
|
||||
## [0.11.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.10.0...v0.11.0) (2021-01-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add --all-namespaces flag to `func list` ([#242](https://github.com/knative-sandbox/kn-plugin-func/issues/242)) ([8e72fd2](https://github.com/knative-sandbox/kn-plugin-func/commit/8e72fd2eba9f4e6e5d3a0bd366215025ba1d1004))
|
||||
* add --all-namespaces flag to `func list` ([#242](https://github.com/knative-extensions/kn-plugin-func/issues/242)) ([8e72fd2](https://github.com/knative-extensions/kn-plugin-func/commit/8e72fd2eba9f4e6e5d3a0bd366215025ba1d1004))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* change --format flag to --output for list and describe commands ([#248](https://github.com/knative-sandbox/kn-plugin-func/issues/248)) ([6470d9e](https://github.com/knative-sandbox/kn-plugin-func/commit/6470d9e57462bc8d3a30583cf146d4f466e2d5f7))
|
||||
* correct fn signatures in Go Events template ([#246](https://github.com/knative-sandbox/kn-plugin-func/issues/246)) ([5502492](https://github.com/knative-sandbox/kn-plugin-func/commit/55024921c26e044f83187cbd5510375d8702c6d9))
|
||||
* correcting broken merge ([#252](https://github.com/knative-sandbox/kn-plugin-func/issues/252)) ([8d1f5b8](https://github.com/knative-sandbox/kn-plugin-func/commit/8d1f5b833d86fa959e3386db73f7e1b07bdd6dfd))
|
||||
* fix the help text for the describe function ([#243](https://github.com/knative-sandbox/kn-plugin-func/issues/243)) ([5a3a0d6](https://github.com/knative-sandbox/kn-plugin-func/commit/5a3a0d6bdab4d01292c4c8f6011a3b67cadb8ef6))
|
||||
* print "No functions found in [ns] namespace" for kn func list ([#240](https://github.com/knative-sandbox/kn-plugin-func/issues/240)) ([61ea8d4](https://github.com/knative-sandbox/kn-plugin-func/commit/61ea8d4fc6e841f0f10151244f10131862bf181c))
|
||||
* set envVars when creating a function ([#250](https://github.com/knative-sandbox/kn-plugin-func/issues/250)) ([f0be048](https://github.com/knative-sandbox/kn-plugin-func/commit/f0be048c841be22fcd0d448fdecc0da33b8c77be))
|
||||
* change --format flag to --output for list and describe commands ([#248](https://github.com/knative-extensions/kn-plugin-func/issues/248)) ([6470d9e](https://github.com/knative-extensions/kn-plugin-func/commit/6470d9e57462bc8d3a30583cf146d4f466e2d5f7))
|
||||
* correct fn signatures in Go Events template ([#246](https://github.com/knative-extensions/kn-plugin-func/issues/246)) ([5502492](https://github.com/knative-extensions/kn-plugin-func/commit/55024921c26e044f83187cbd5510375d8702c6d9))
|
||||
* correcting broken merge ([#252](https://github.com/knative-extensions/kn-plugin-func/issues/252)) ([8d1f5b8](https://github.com/knative-extensions/kn-plugin-func/commit/8d1f5b833d86fa959e3386db73f7e1b07bdd6dfd))
|
||||
* fix the help text for the describe function ([#243](https://github.com/knative-extensions/kn-plugin-func/issues/243)) ([5a3a0d6](https://github.com/knative-extensions/kn-plugin-func/commit/5a3a0d6bdab4d01292c4c8f6011a3b67cadb8ef6))
|
||||
* print "No functions found in [ns] namespace" for kn func list ([#240](https://github.com/knative-extensions/kn-plugin-func/issues/240)) ([61ea8d4](https://github.com/knative-extensions/kn-plugin-func/commit/61ea8d4fc6e841f0f10151244f10131862bf181c))
|
||||
* set envVars when creating a function ([#250](https://github.com/knative-extensions/kn-plugin-func/issues/250)) ([f0be048](https://github.com/knative-extensions/kn-plugin-func/commit/f0be048c841be22fcd0d448fdecc0da33b8c77be))
|
||||
|
||||
## [0.10.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.9.0...v0.10.0) (2020-12-08)
|
||||
## [0.10.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.9.0...v0.10.0) (2020-12-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add spring cloud function runtime and templates ([#231](https://github.com/knative-sandbox/kn-plugin-func/issues/231)) ([557361a](https://github.com/knative-sandbox/kn-plugin-func/commit/557361a37446953dc613ae30f59913f1924dedd3))
|
||||
* add spring cloud function runtime and templates ([#231](https://github.com/knative-extensions/kn-plugin-func/issues/231)) ([557361a](https://github.com/knative-extensions/kn-plugin-func/commit/557361a37446953dc613ae30f59913f1924dedd3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix plugin version output ([#233](https://github.com/knative-sandbox/kn-plugin-func/issues/233)) ([8a30ba1](https://github.com/knative-sandbox/kn-plugin-func/commit/8a30ba193da6097a141332212cbd64e5a1a708e8))
|
||||
* use image name for run command ([#238](https://github.com/knative-sandbox/kn-plugin-func/issues/238)) ([985906b](https://github.com/knative-sandbox/kn-plugin-func/commit/985906b0e1f692f94fc84e3e796893192d17bd4c))
|
||||
* Fix plugin version output ([#233](https://github.com/knative-extensions/kn-plugin-func/issues/233)) ([8a30ba1](https://github.com/knative-extensions/kn-plugin-func/commit/8a30ba193da6097a141332212cbd64e5a1a708e8))
|
||||
* use image name for run command ([#238](https://github.com/knative-extensions/kn-plugin-func/issues/238)) ([985906b](https://github.com/knative-extensions/kn-plugin-func/commit/985906b0e1f692f94fc84e3e796893192d17bd4c))
|
||||
|
||||
## [0.9.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.8.0...v0.9.0) (2020-11-06)
|
||||
## [0.9.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.8.0...v0.9.0) (2020-11-06)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -482,19 +482,19 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* Better output of build/deploy/delete commands ([#206](https://github.com/knative-sandbox/kn-plugin-func/issues/206)) ([ddbb95b](https://github.com/knative-sandbox/kn-plugin-func/commit/ddbb95b075a383fb1847be2c75fd2c216870c7f8))
|
||||
* change default runtime to Node.js HTTP ([#198](https://github.com/knative-sandbox/kn-plugin-func/issues/198)) ([61cb56a](https://github.com/knative-sandbox/kn-plugin-func/commit/61cb56aec3461e9f9b35282435dbc884999be2b3))
|
||||
* list command - improved output ([#205](https://github.com/knative-sandbox/kn-plugin-func/issues/205)) ([29ca077](https://github.com/knative-sandbox/kn-plugin-func/commit/29ca07768ca455debb7992ebbf09b2db2058f56d))
|
||||
* remove create cli subcommand ([#180](https://github.com/knative-sandbox/kn-plugin-func/issues/180)) ([57e1236](https://github.com/knative-sandbox/kn-plugin-func/commit/57e12362af18f48624a9c303c070846e1645e08d))
|
||||
* rename faas to function ([#210](https://github.com/knative-sandbox/kn-plugin-func/issues/210)) ([cd57692](https://github.com/knative-sandbox/kn-plugin-func/commit/cd57692c9d04fecb918abf4f15cd37d45592cf82))
|
||||
* Better output of build/deploy/delete commands ([#206](https://github.com/knative-extensions/kn-plugin-func/issues/206)) ([ddbb95b](https://github.com/knative-extensions/kn-plugin-func/commit/ddbb95b075a383fb1847be2c75fd2c216870c7f8))
|
||||
* change default runtime to Node.js HTTP ([#198](https://github.com/knative-extensions/kn-plugin-func/issues/198)) ([61cb56a](https://github.com/knative-extensions/kn-plugin-func/commit/61cb56aec3461e9f9b35282435dbc884999be2b3))
|
||||
* list command - improved output ([#205](https://github.com/knative-extensions/kn-plugin-func/issues/205)) ([29ca077](https://github.com/knative-extensions/kn-plugin-func/commit/29ca07768ca455debb7992ebbf09b2db2058f56d))
|
||||
* remove create cli subcommand ([#180](https://github.com/knative-extensions/kn-plugin-func/issues/180)) ([57e1236](https://github.com/knative-extensions/kn-plugin-func/commit/57e12362af18f48624a9c303c070846e1645e08d))
|
||||
* rename faas to function ([#210](https://github.com/knative-extensions/kn-plugin-func/issues/210)) ([cd57692](https://github.com/knative-extensions/kn-plugin-func/commit/cd57692c9d04fecb918abf4f15cd37d45592cf82))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `delete` and `deploy sub-commands respects func.yaml conf ([d562498](https://github.com/knative-sandbox/kn-plugin-func/commit/d5624980d5f31f98bc27e803ae94311491d4d078))
|
||||
* return JSON in Node.js event template ([#211](https://github.com/knative-sandbox/kn-plugin-func/issues/211)) ([beb838f](https://github.com/knative-sandbox/kn-plugin-func/commit/beb838ff43d04c7ccec63a26fbe2af9fb167ae1a))
|
||||
* `delete` and `deploy sub-commands respects func.yaml conf ([d562498](https://github.com/knative-extensions/kn-plugin-func/commit/d5624980d5f31f98bc27e803ae94311491d4d078))
|
||||
* return JSON in Node.js event template ([#211](https://github.com/knative-extensions/kn-plugin-func/issues/211)) ([beb838f](https://github.com/knative-extensions/kn-plugin-func/commit/beb838ff43d04c7ccec63a26fbe2af9fb167ae1a))
|
||||
|
||||
## [0.8.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.7.0...v0.8.0) (2020-10-20)
|
||||
## [0.8.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.7.0...v0.8.0) (2020-10-20)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
@ -504,48 +504,48 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
|
||||
### Features
|
||||
|
||||
* add health probes to node & go services ([#174](https://github.com/knative-sandbox/kn-plugin-func/issues/174)) ([95c1eb5](https://github.com/knative-sandbox/kn-plugin-func/commit/95c1eb5e59335cfee84ce536d086bd394268c81c))
|
||||
* introduce CloudEvent data as first parameter for event functions ([#172](https://github.com/knative-sandbox/kn-plugin-func/issues/172)) ([7451194](https://github.com/knative-sandbox/kn-plugin-func/commit/74511948cefc368d898ad05b911fded74d44b759))
|
||||
* user can set envvars ([5182487](https://github.com/knative-sandbox/kn-plugin-func/commit/5182487df218685867fda10c3d1983b4c035c08a))
|
||||
* **kn:** Enable faas to be integrated as plugin to kn ([#155](https://github.com/knative-sandbox/kn-plugin-func/issues/155)) ([85a5f47](https://github.com/knative-sandbox/kn-plugin-func/commit/85a5f475eb32269b9cced05fe36dc90f8befd000))
|
||||
* ability for users to specify custom builders ([#147](https://github.com/knative-sandbox/kn-plugin-func/issues/147)) ([c2b4a30](https://github.com/knative-sandbox/kn-plugin-func/commit/c2b4a304bd3fa7d020c71db9f4d79c80c98d86d3))
|
||||
* combine deploy and update commands ([#152](https://github.com/knative-sandbox/kn-plugin-func/issues/152)) ([d5839ea](https://github.com/knative-sandbox/kn-plugin-func/commit/d5839ea6c1e84e843ad643cc0611a82e2e6d2399))
|
||||
* fish completion ([d822303](https://github.com/knative-sandbox/kn-plugin-func/commit/d82230353d3d437e8f35e7f9ce3569988d765b42))
|
||||
* add health probes to node & go services ([#174](https://github.com/knative-extensions/kn-plugin-func/issues/174)) ([95c1eb5](https://github.com/knative-extensions/kn-plugin-func/commit/95c1eb5e59335cfee84ce536d086bd394268c81c))
|
||||
* introduce CloudEvent data as first parameter for event functions ([#172](https://github.com/knative-extensions/kn-plugin-func/issues/172)) ([7451194](https://github.com/knative-extensions/kn-plugin-func/commit/74511948cefc368d898ad05b911fded74d44b759))
|
||||
* user can set envvars ([5182487](https://github.com/knative-extensions/kn-plugin-func/commit/5182487df218685867fda10c3d1983b4c035c08a))
|
||||
* **kn:** Enable faas to be integrated as plugin to kn ([#155](https://github.com/knative-extensions/kn-plugin-func/issues/155)) ([85a5f47](https://github.com/knative-extensions/kn-plugin-func/commit/85a5f475eb32269b9cced05fe36dc90f8befd000))
|
||||
* ability for users to specify custom builders ([#147](https://github.com/knative-extensions/kn-plugin-func/issues/147)) ([c2b4a30](https://github.com/knative-extensions/kn-plugin-func/commit/c2b4a304bd3fa7d020c71db9f4d79c80c98d86d3))
|
||||
* combine deploy and update commands ([#152](https://github.com/knative-extensions/kn-plugin-func/issues/152)) ([d5839ea](https://github.com/knative-extensions/kn-plugin-func/commit/d5839ea6c1e84e843ad643cc0611a82e2e6d2399))
|
||||
* fish completion ([d822303](https://github.com/knative-extensions/kn-plugin-func/commit/d82230353d3d437e8f35e7f9ce3569988d765b42))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* examples in readme ([5591e7f](https://github.com/knative-sandbox/kn-plugin-func/commit/5591e7fa2ca9584f03bf8d065778cd120ea9054f))
|
||||
* image parsing ([6a621a5](https://github.com/knative-sandbox/kn-plugin-func/commit/6a621a5186ffffec79e6f34c34681cc37eeaa0bd))
|
||||
* regenerate pkger files ([#183](https://github.com/knative-sandbox/kn-plugin-func/issues/183)) ([1d14a8c](https://github.com/knative-sandbox/kn-plugin-func/commit/1d14a8c10156098d66ef691f84ecce1bd25a6d88))
|
||||
* root cmd init ([ec5327d](https://github.com/knative-sandbox/kn-plugin-func/commit/ec5327d5201b57d6a33bcc7314332686582b676f))
|
||||
* stop using manually edited completion ([bf9b048](https://github.com/knative-sandbox/kn-plugin-func/commit/bf9b04881333fed6038251fa4de92368771840d9))
|
||||
* update quarkus templates ([ffc6a12](https://github.com/knative-sandbox/kn-plugin-func/commit/ffc6a123e469968865fef1ccb5f8d84a443baccb))
|
||||
* update to Knative 0.17 ([#145](https://github.com/knative-sandbox/kn-plugin-func/issues/145)) ([5fe7052](https://github.com/knative-sandbox/kn-plugin-func/commit/5fe70526e531e283c6704d9526e3cdd7ef64f9e1))
|
||||
* examples in readme ([5591e7f](https://github.com/knative-extensions/kn-plugin-func/commit/5591e7fa2ca9584f03bf8d065778cd120ea9054f))
|
||||
* image parsing ([6a621a5](https://github.com/knative-extensions/kn-plugin-func/commit/6a621a5186ffffec79e6f34c34681cc37eeaa0bd))
|
||||
* regenerate pkger files ([#183](https://github.com/knative-extensions/kn-plugin-func/issues/183)) ([1d14a8c](https://github.com/knative-extensions/kn-plugin-func/commit/1d14a8c10156098d66ef691f84ecce1bd25a6d88))
|
||||
* root cmd init ([ec5327d](https://github.com/knative-extensions/kn-plugin-func/commit/ec5327d5201b57d6a33bcc7314332686582b676f))
|
||||
* stop using manually edited completion ([bf9b048](https://github.com/knative-extensions/kn-plugin-func/commit/bf9b04881333fed6038251fa4de92368771840d9))
|
||||
* update quarkus templates ([ffc6a12](https://github.com/knative-extensions/kn-plugin-func/commit/ffc6a123e469968865fef1ccb5f8d84a443baccb))
|
||||
* update to Knative 0.17 ([#145](https://github.com/knative-extensions/kn-plugin-func/issues/145)) ([5fe7052](https://github.com/knative-extensions/kn-plugin-func/commit/5fe70526e531e283c6704d9526e3cdd7ef64f9e1))
|
||||
|
||||
|
||||
### src
|
||||
|
||||
* change all references of "repository" to "registry" for images ([#156](https://github.com/knative-sandbox/kn-plugin-func/issues/156)) ([e425c8f](https://github.com/knative-sandbox/kn-plugin-func/commit/e425c8f08183b333e56d5d3cfe74fc9e85a6c903))
|
||||
* change all references of "repository" to "registry" for images ([#156](https://github.com/knative-extensions/kn-plugin-func/issues/156)) ([e425c8f](https://github.com/knative-extensions/kn-plugin-func/commit/e425c8f08183b333e56d5d3cfe74fc9e85a6c903))
|
||||
|
||||
## [0.7.0](https://github.com/knative-sandbox/kn-plugin-func/compare/v0.6.2...v0.7.0) (2020-09-24)
|
||||
## [0.7.0](https://github.com/knative-extensions/kn-plugin-func/compare/v0.6.2...v0.7.0) (2020-09-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add local debugging to node.js templates ([#132](https://github.com/knative-sandbox/kn-plugin-func/issues/132)) ([1b0bb15](https://github.com/knative-sandbox/kn-plugin-func/commit/1b0bb15147889bb55ff33de1dc132cb0370d1da6))
|
||||
* decouple function name from function domain ([#127](https://github.com/knative-sandbox/kn-plugin-func/issues/127)) ([0258626](https://github.com/knative-sandbox/kn-plugin-func/commit/025862689ec8dc460a1ef6f4402151c18a072ba3))
|
||||
* default to no confirmation prompts for CLI commands ([566d8f9](https://github.com/knative-sandbox/kn-plugin-func/commit/566d8f9255d532e88e72d5bce122bebaee88bc81))
|
||||
* set builder images in templates and .faas.yaml ([#136](https://github.com/knative-sandbox/kn-plugin-func/issues/136)) ([d6e131f](https://github.com/knative-sandbox/kn-plugin-func/commit/d6e131f9153c20bd3edbf1441060610987fa5693))
|
||||
* **ci/cd:** add release-please for automated release management ([8a60c5e](https://github.com/knative-sandbox/kn-plugin-func/commit/8a60c5e0c44d28d2ff085e56299217e05e408df8))
|
||||
* add local debugging to node.js templates ([#132](https://github.com/knative-extensions/kn-plugin-func/issues/132)) ([1b0bb15](https://github.com/knative-extensions/kn-plugin-func/commit/1b0bb15147889bb55ff33de1dc132cb0370d1da6))
|
||||
* decouple function name from function domain ([#127](https://github.com/knative-extensions/kn-plugin-func/issues/127)) ([0258626](https://github.com/knative-extensions/kn-plugin-func/commit/025862689ec8dc460a1ef6f4402151c18a072ba3))
|
||||
* default to no confirmation prompts for CLI commands ([566d8f9](https://github.com/knative-extensions/kn-plugin-func/commit/566d8f9255d532e88e72d5bce122bebaee88bc81))
|
||||
* set builder images in templates and .faas.yaml ([#136](https://github.com/knative-extensions/kn-plugin-func/issues/136)) ([d6e131f](https://github.com/knative-extensions/kn-plugin-func/commit/d6e131f9153c20bd3edbf1441060610987fa5693))
|
||||
* **ci/cd:** add release-please for automated release management ([8a60c5e](https://github.com/knative-extensions/kn-plugin-func/commit/8a60c5e0c44d28d2ff085e56299217e05e408df8))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correct value for config path and robustify ([#130](https://github.com/knative-sandbox/kn-plugin-func/issues/130)) ([fae27da](https://github.com/knative-sandbox/kn-plugin-func/commit/fae27dabc97c78cd98be400d296da6fc2fbeba65))
|
||||
* delete command ([284b77f](https://github.com/knative-sandbox/kn-plugin-func/commit/284b77f7ef6524195da958850131190399470375))
|
||||
* describe works without Eventing ([6c16e65](https://github.com/knative-sandbox/kn-plugin-func/commit/6c16e65d60543458f0b70c010d672cb4d45f6279))
|
||||
* sync package-lock.json ([#137](https://github.com/knative-sandbox/kn-plugin-func/issues/137)) ([02309a2](https://github.com/knative-sandbox/kn-plugin-func/commit/02309a24a1d8779fb69e4f67fa4f7faea705b2ba))
|
||||
* correct value for config path and robustify ([#130](https://github.com/knative-extensions/kn-plugin-func/issues/130)) ([fae27da](https://github.com/knative-extensions/kn-plugin-func/commit/fae27dabc97c78cd98be400d296da6fc2fbeba65))
|
||||
* delete command ([284b77f](https://github.com/knative-extensions/kn-plugin-func/commit/284b77f7ef6524195da958850131190399470375))
|
||||
* describe works without Eventing ([6c16e65](https://github.com/knative-extensions/kn-plugin-func/commit/6c16e65d60543458f0b70c010d672cb4d45f6279))
|
||||
* sync package-lock.json ([#137](https://github.com/knative-extensions/kn-plugin-func/issues/137)) ([02309a2](https://github.com/knative-extensions/kn-plugin-func/commit/02309a24a1d8779fb69e4f67fa4f7faea705b2ba))
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
|
@ -565,7 +565,7 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
### Chore
|
||||
- update quarkus version to 1.7.2.Final
|
||||
- use organization-level secrets for image deployment
|
||||
- **actions:** add binary uploads to develop branch CI ([#104](https://github.com/knative-sandbox/kn-plugin-func/issues/104))
|
||||
- **actions:** add binary uploads to develop branch CI ([#104](https://github.com/knative-extensions/kn-plugin-func/issues/104))
|
||||
|
||||
### Docs
|
||||
- initial Go template READMEs
|
||||
|
@ -573,13 +573,13 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
### Fix
|
||||
- build releases from main branch only
|
||||
- remove references to unused binaries appsody, kn, kubectl
|
||||
- image override ([#88](https://github.com/knative-sandbox/kn-plugin-func/issues/88))
|
||||
- image override ([#88](https://github.com/knative-extensions/kn-plugin-func/issues/88))
|
||||
|
||||
### Release
|
||||
- v0.6.1
|
||||
|
||||
### Templates
|
||||
- **node:** make node templates use npx [@redhat](https://github.com/redhat)/faas-js-runtime ([#99](https://github.com/knative-sandbox/kn-plugin-func/issues/99))
|
||||
- **node:** make node templates use npx [@redhat](https://github.com/redhat)/faas-js-runtime ([#99](https://github.com/knative-extensions/kn-plugin-func/issues/99))
|
||||
|
||||
|
||||
<a name="v0.6.0"></a>
|
||||
|
@ -590,7 +590,7 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
### Docs
|
||||
- fix function typos
|
||||
- setting up remote access to kind clusters
|
||||
- wireguard configuraiton for OS X
|
||||
- wireguard configuration for OS X
|
||||
- Kind cluster provisioning and TLS
|
||||
- separate repository and system docs
|
||||
- getting started with kubernetes, reorganization.
|
||||
|
@ -602,8 +602,8 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
- consolidate knative client config construction
|
||||
- cli usability enhancements and API simplification
|
||||
- the `list` sub-command uses namespace
|
||||
- version command respects verbose flag ([#61](https://github.com/knative-sandbox/kn-plugin-func/issues/61))
|
||||
- add init/build/deploy commands and customizable namespace ([#65](https://github.com/knative-sandbox/kn-plugin-func/issues/65))
|
||||
- version command respects verbose flag ([#61](https://github.com/knative-extensions/kn-plugin-func/issues/61))
|
||||
- add init/build/deploy commands and customizable namespace ([#65](https://github.com/knative-extensions/kn-plugin-func/issues/65))
|
||||
- JSON output for the `list` sub-command
|
||||
|
||||
### Fix
|
||||
|
@ -618,13 +618,13 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
- v0.6.0
|
||||
|
||||
### Test
|
||||
- add test targets for go and quarkus templates ([#72](https://github.com/knative-sandbox/kn-plugin-func/issues/72))
|
||||
- add test targets for go and quarkus templates ([#72](https://github.com/knative-extensions/kn-plugin-func/issues/72))
|
||||
|
||||
|
||||
<a name="v0.5.0"></a>
|
||||
## [v0.5.0] - 2020-07-31
|
||||
### Actions
|
||||
- add CHANGELOG.md and a release target to Makefile ([#45](https://github.com/knative-sandbox/kn-plugin-func/issues/45))
|
||||
- add CHANGELOG.md and a release target to Makefile ([#45](https://github.com/knative-extensions/kn-plugin-func/issues/45))
|
||||
|
||||
### Build
|
||||
- reduce build verbosity for cross-platform compilations
|
||||
|
@ -727,17 +727,17 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
- add kn-based implementation
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.6.2...HEAD
|
||||
[v0.6.2]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.6.1...v0.6.2
|
||||
[v0.6.1]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.6.0...v0.6.1
|
||||
[v0.6.0]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.5.0...v0.6.0
|
||||
[v0.5.0]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.4.0...v0.5.0
|
||||
[v0.4.0]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.3.0...v0.4.0
|
||||
[v0.3.0]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.2.2...v0.3.0
|
||||
[v0.2.2]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.2.1...v0.2.2
|
||||
[v0.2.1]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.2.0...v0.2.1
|
||||
[v0.2.0]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.1.0...v0.2.0
|
||||
[v0.1.0]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.0.19...v0.1.0
|
||||
[v0.0.19]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.0.18...v0.0.19
|
||||
[v0.0.18]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.0.17...v0.0.18
|
||||
[v0.0.17]: https://github.com/knative-sandbox/kn-plugin-func/compare/v0.0.16...v0.0.17
|
||||
[Unreleased]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.6.2...HEAD
|
||||
[v0.6.2]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.6.1...v0.6.2
|
||||
[v0.6.1]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.6.0...v0.6.1
|
||||
[v0.6.0]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.5.0...v0.6.0
|
||||
[v0.5.0]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.4.0...v0.5.0
|
||||
[v0.4.0]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.3.0...v0.4.0
|
||||
[v0.3.0]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.2.2...v0.3.0
|
||||
[v0.2.2]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.2.1...v0.2.2
|
||||
[v0.2.1]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.2.0...v0.2.1
|
||||
[v0.2.0]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.1.0...v0.2.0
|
||||
[v0.1.0]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.0.19...v0.1.0
|
||||
[v0.0.19]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.0.18...v0.0.19
|
||||
[v0.0.18]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.0.17...v0.0.18
|
||||
[v0.0.17]: https://github.com/knative-extensions/kn-plugin-func/compare/v0.0.16...v0.0.17
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
FROM scratch
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG FUNC_UTIL_BINARY=func-util-$TARGETARCH
|
||||
|
||||
ENV PATH=/
|
||||
|
||||
COPY $FUNC_UTIL_BINARY /func-util
|
||||
|
||||
ADD func-util-symlinks.tgz /
|
||||
|
||||
LABEL \
|
||||
org.opencontainers.image.description="Knative Func Utils Image" \
|
||||
org.opencontainers.image.source="https://github.com/knative/func" \
|
||||
org.opencontainers.image.vendor="https://github.com/knative/func" \
|
||||
org.opencontainers.image.url="https://github.com/knative/func/pkgs/container/func-utils"
|
||||
|
||||
USER 0:0
|
156
Makefile
156
Makefile
|
@ -27,24 +27,28 @@ VTAG := $(shell git tag --points-at HEAD | head -1)
|
|||
VTAG := $(shell [ -z $(VTAG) ] && echo $(ETAG) || echo $(VTAG))
|
||||
VERS ?= $(shell git describe --tags --match 'v*')
|
||||
KVER ?= $(shell git describe --tags --match 'knative-*')
|
||||
LDFLAGS := "-X main.date=$(DATE) -X main.vers=$(VERS) -X main.kver=$(KVER) -X main.hash=$(HASH)"
|
||||
|
||||
LDFLAGS := -X knative.dev/func/pkg/version.Vers=$(VERS) -X knative.dev/func/pkg/version.Kver=$(KVER) -X knative.dev/func/pkg/version.Hash=$(HASH)
|
||||
|
||||
FUNC_UTILS_IMG ?= ghcr.io/knative/func-utils:v2
|
||||
LDFLAGS += -X knative.dev/func/pkg/k8s.SocatImage=$(FUNC_UTILS_IMG)
|
||||
LDFLAGS += -X knative.dev/func/pkg/k8s.TarImage=$(FUNC_UTILS_IMG)
|
||||
LDFLAGS += -X knative.dev/func/pkg/pipelines/tekton.FuncUtilImage=$(FUNC_UTILS_IMG)
|
||||
|
||||
GOFLAGS := "-ldflags=$(LDFLAGS)"
|
||||
export GOFLAGS
|
||||
|
||||
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
# All Code prerequisites, including generated files, etc.
|
||||
CODE := $(shell find . -name '*.go') \
|
||||
generate/zz_filesystem_generated.go \
|
||||
schema/func_yaml-schema.json \
|
||||
templates/certs/ca-certificates.crt \
|
||||
go.mod
|
||||
|
||||
.PHONY: test docs
|
||||
|
||||
# Default Targets
|
||||
.PHONY: all
|
||||
all: build docs
|
||||
@echo '🎉 Build process completed!'
|
||||
|
||||
# Help Text
|
||||
# Headings: lines with `##$` comment prefix
|
||||
# Targets: printed if their line includes a `##` comment
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage: make <OPTIONS> ... <TARGETS>'
|
||||
@echo ''
|
||||
|
@ -56,12 +60,15 @@ help:
|
|||
##@ Development
|
||||
###############
|
||||
|
||||
.PHONY: build
|
||||
build: $(BIN) ## (default) Build binary for current OS
|
||||
|
||||
$(BIN): $(CODE)
|
||||
env CGO_ENABLED=0 go build -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
.PHONY: $(BIN)
|
||||
$(BIN): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 go build ./cmd/$(BIN)
|
||||
|
||||
test: $(CODE) ## Run core unit tests
|
||||
.PHONY: test
|
||||
test: generate/zz_filesystem_generated.go ## Run core unit tests
|
||||
go test -race -cover -coverprofile=coverage.txt ./...
|
||||
|
||||
.PHONY: check
|
||||
|
@ -70,7 +77,7 @@ check: $(BIN_GOLANGCI_LINT) ## Check code quality (lint)
|
|||
cd test && $(BIN_GOLANGCI_LINT) run --timeout 300s
|
||||
|
||||
$(BIN_GOLANGCI_LINT):
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./bin v1.53.2
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./bin v2.0.2
|
||||
|
||||
.PHONY: generate/zz_filesystem_generated.go
|
||||
generate/zz_filesystem_generated.go: clean_templates
|
||||
|
@ -79,23 +86,27 @@ generate/zz_filesystem_generated.go: clean_templates
|
|||
.PHONY: clean_templates
|
||||
clean_templates:
|
||||
# Removing temporary template files
|
||||
@rm -f templates/go/cloudevents/go.sum
|
||||
@rm -f templates/go/http/go.sum
|
||||
@rm -rf templates/**/.DS_Store
|
||||
@rm -rf templates/node/cloudevents/node_modules
|
||||
@rm -rf templates/node/http/node_modules
|
||||
@rm -rf templates/python/cloudevents/__pycache__
|
||||
@rm -rf templates/python/http/__pycache__
|
||||
@rm -rf templates/typescript/cloudevents/node_modules
|
||||
@rm -rf templates/typescript/http/node_modules
|
||||
@rm -rf templates/typescript/cloudevents/build
|
||||
@rm -rf templates/typescript/http/build
|
||||
@rm -rf templates/rust/cloudevents/target
|
||||
@rm -rf templates/rust/http/target
|
||||
@rm -rf templates/python/cloudevents/.venv
|
||||
@rm -rf templates/python/cloudevents/.pytest_cache
|
||||
@rm -rf templates/python/cloudevents/function/__pycache__
|
||||
@rm -rf templates/python/cloudevents/tests/__pycache__
|
||||
@rm -rf templates/python/http/.venv
|
||||
@rm -rf templates/python/http/.pytest_cache
|
||||
@rm -rf templates/python/http/function/__pycache__
|
||||
@rm -rf templates/python/http/tests/__pycache__
|
||||
@rm -rf templates/quarkus/cloudevents/target
|
||||
@rm -rf templates/quarkus/http/target
|
||||
@rm -rf templates/rust/cloudevents/target
|
||||
@rm -rf templates/rust/http/target
|
||||
@rm -rf templates/springboot/cloudevents/target
|
||||
@rm -rf templates/springboot/http/target
|
||||
@rm -f templates/**/.DS_Store
|
||||
@rm -rf templates/typescript/cloudevents/build
|
||||
@rm -rf templates/typescript/cloudevents/node_modules
|
||||
@rm -rf templates/typescript/http/build
|
||||
@rm -rf templates/typescript/http/node_modules
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean_templates ## Remove generated artifacts such as binaries and schemas
|
||||
|
@ -107,12 +118,13 @@ clean: clean_templates ## Remove generated artifacts such as binaries and schema
|
|||
.PHONY: docs
|
||||
docs:
|
||||
# Generating command reference doc
|
||||
go run docs/generator/main.go
|
||||
KUBECONFIG="$(shell mktemp)" go run docs/generator/main.go
|
||||
|
||||
#############
|
||||
##@ Prow Integration
|
||||
#############
|
||||
|
||||
.PHONY: presubmit-unit-tests
|
||||
presubmit-unit-tests: ## Run prow presubmit unit tests locally
|
||||
docker run --platform linux/amd64 -it --rm -v$(MAKEFILE_DIR):/src/ us-docker.pkg.dev/knative-tests/images/prow-tests:v20230616-086ddd644 sh -c 'cd /src && runner.sh ./test/presubmit-tests.sh --unit-tests'
|
||||
|
||||
|
@ -121,6 +133,10 @@ presubmit-unit-tests: ## Run prow presubmit unit tests locally
|
|||
##@ Templates
|
||||
#############
|
||||
|
||||
.PHONY: check-embedded-fs
|
||||
check-embedded-fs: ## Check the embedded templates FS
|
||||
go test -run "^\QTestFileSystems\E$$/^\Qembedded\E$$" ./pkg/filesystem
|
||||
|
||||
# TODO: add linters for other templates
|
||||
.PHONY: check-templates
|
||||
check-templates: check-go check-rust ## Run template source code checks
|
||||
|
@ -137,32 +153,39 @@ check-rust: ## Check Rust templates' source
|
|||
cd templates/rust/cloudevents && cargo clippy && cargo clean
|
||||
cd templates/rust/http && cargo clippy && cargo clean
|
||||
|
||||
.PHONY: test-templates
|
||||
test-templates: test-go test-node test-python test-quarkus test-springboot test-rust test-typescript ## Run all template tests
|
||||
|
||||
.PHONY: test-go
|
||||
test-go: ## Test Go templates
|
||||
cd templates/go/cloudevents && go mod tidy && go test
|
||||
cd templates/go/http && go mod tidy && go test
|
||||
|
||||
.PHONY: test-node
|
||||
test-node: ## Test Node templates
|
||||
cd templates/node/cloudevents && npm ci && npm test && rm -rf node_modules
|
||||
cd templates/node/http && npm ci && npm test && rm -rf node_modules
|
||||
|
||||
test-python: ## Test Python templates
|
||||
cd templates/python/cloudevents && pip3 install -r requirements.txt && python3 test_func.py && rm -rf __pycache__
|
||||
cd templates/python/http && python3 test_func.py && rm -rf __pycache__
|
||||
.PHONY: test-python
|
||||
test-python: ## Test Python templates and Scaffolding
|
||||
test/test_python.sh
|
||||
|
||||
.PHONY: test-quarkus
|
||||
test-quarkus: ## Test Quarkus templates
|
||||
cd templates/quarkus/cloudevents && mvn -q test && mvn clean
|
||||
cd templates/quarkus/http && mvn -q test && mvn clean
|
||||
cd templates/quarkus/cloudevents && ./mvnw -q test && ./mvnw clean && rm .mvn/wrapper/maven-wrapper.jar
|
||||
cd templates/quarkus/http && ./mvnw -q test && ./mvnw clean && rm .mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
.PHONY: test-springboot
|
||||
test-springboot: ## Test Spring Boot templates
|
||||
cd templates/springboot/cloudevents && mvn -q test && mvn clean
|
||||
cd templates/springboot/http && mvn -q test && mvn clean
|
||||
cd templates/springboot/cloudevents && ./mvnw -q test && ./mvnw clean && rm .mvn/wrapper/maven-wrapper.jar
|
||||
cd templates/springboot/http && ./mvnw -q test && ./mvnw clean && rm .mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
.PHONY: test-rust
|
||||
test-rust: ## Test Rust templates
|
||||
cd templates/rust/cloudevents && cargo -q test && cargo clean
|
||||
cd templates/rust/http && cargo -q test && cargo clean
|
||||
|
||||
.PHONY: test-typescript
|
||||
test-typescript: ## Test Typescript templates
|
||||
cd templates/typescript/cloudevents && npm ci && npm test && rm -rf node_modules build
|
||||
cd templates/typescript/http && npm ci && npm test && rm -rf node_modules build
|
||||
|
@ -172,15 +195,18 @@ test-typescript: ## Test Typescript templates
|
|||
###############
|
||||
|
||||
# Pulls runtimes then rebuilds the embedded filesystem
|
||||
update-runtimes: pull-runtimes generate/zz_filesystem_generated.go ## Update Scaffolding Runtimes
|
||||
.PHONY: update-runtimes
|
||||
update-runtimes: update-runtime-go generate/zz_filesystem_generated.go ## Update Scaffolding Runtimes
|
||||
|
||||
pull-runtimes:
|
||||
cd templates/go/scaffolding/instanced-http && go get -u github.com/knative-sandbox/func-go/http
|
||||
cd templates/go/scaffolding/static-http && go get -u github.com/knative-sandbox/func-go/http
|
||||
cd templates/go/scaffolding/instanced-cloudevents && go get -u github.com/knative-sandbox/func-go/cloudevents
|
||||
cd templates/go/scaffolding/static-cloudevents && go get -u github.com/knative-sandbox/func-go/cloudevents
|
||||
.PHONY: update-runtime-go
|
||||
update-runtime-go:
|
||||
cd templates/go/scaffolding/instanced-http && go get -u knative.dev/func-go/http
|
||||
cd templates/go/scaffolding/static-http && go get -u knative.dev/func-go/http
|
||||
cd templates/go/scaffolding/instanced-cloudevents && go get -u knative.dev/func-go/cloudevents
|
||||
cd templates/go/scaffolding/static-cloudevents && go get -u knative.dev/func-go/cloudevents
|
||||
|
||||
.PHONY: cert
|
||||
|
||||
.PHONY: certs
|
||||
certs: templates/certs/ca-certificates.crt ## Update root certificates
|
||||
|
||||
.PHONY: templates/certs/ca-certificates.crt
|
||||
|
@ -192,20 +218,23 @@ templates/certs/ca-certificates.crt:
|
|||
##@ Extended Testing (cluster required)
|
||||
###################
|
||||
|
||||
.PHONY: test-integration
|
||||
test-integration: ## Run integration tests using an available cluster.
|
||||
go test -tags integration -timeout 30m --coverprofile=coverage.txt ./... -v
|
||||
|
||||
.PHONY: func-instrumented
|
||||
func-instrumented: # func binary instrumented with coverage reporting
|
||||
env CGO_ENABLED=1 go build -cover -o func ./cmd/$(BIN)
|
||||
|
||||
func-instrumented: ## Func binary that is instrumented for e2e tests
|
||||
env CGO_ENABLED=1 go build -ldflags $(LDFLAGS) -cover -o func ./cmd/func
|
||||
|
||||
.PHONY: test-e2e
|
||||
test-e2e: func-instrumented ## Run end-to-end tests using an available cluster.
|
||||
./test/e2e_extended_tests.sh
|
||||
|
||||
.PHONY: test-e2e-runtime
|
||||
test-e2e-runtime: func-instrumented ## Run end-to-end lifecycle tests using an available cluster for a single runtime.
|
||||
./test/e2e_lifecycle_tests.sh $(runtime)
|
||||
|
||||
.PHONY: test-e2e-on-cluster
|
||||
test-e2e-on-cluster: func-instrumented ## Run end-to-end on-cluster build tests using an available cluster.
|
||||
./test/e2e_oncluster_tests.sh
|
||||
|
||||
|
@ -213,51 +242,61 @@ test-e2e-on-cluster: func-instrumented ## Run end-to-end on-cluster build tests
|
|||
##@ Release Artifacts
|
||||
######################
|
||||
|
||||
.PHONY: cross-platform
|
||||
cross-platform: darwin-arm64 darwin-amd64 linux-amd64 linux-arm64 linux-ppc64le linux-s390x windows ## Build all distributable (cross-platform) binaries
|
||||
|
||||
.PHONY: darwin-arm64
|
||||
darwin-arm64: $(BIN_DARWIN_ARM64) ## Build for mac M1
|
||||
|
||||
$(BIN_DARWIN_ARM64): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o $(BIN_DARWIN_ARM64) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o $(BIN_DARWIN_ARM64) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
.PHONY: darwn-amd64
|
||||
darwin-amd64: $(BIN_DARWIN_AMD64) ## Build for Darwin (macOS)
|
||||
|
||||
$(BIN_DARWIN_AMD64): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o $(BIN_DARWIN_AMD64) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o $(BIN_DARWIN_AMD64) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
.PHONY: linux-amd64
|
||||
linux-amd64: $(BIN_LINUX_AMD64) ## Build for Linux amd64
|
||||
|
||||
$(BIN_LINUX_AMD64): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(BIN_LINUX_AMD64) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(BIN_LINUX_AMD64) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
.PHONY: linux-arm64
|
||||
linux-arm64: $(BIN_LINUX_ARM64) ## Build for Linux arm64
|
||||
|
||||
$(BIN_LINUX_ARM64): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(BIN_LINUX_ARM64) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(BIN_LINUX_ARM64) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
.PHONY: linux-ppc64le
|
||||
linux-ppc64le: $(BIN_LINUX_PPC64LE) ## Build for Linux ppc64le
|
||||
|
||||
$(BIN_LINUX_PPC64LE): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le go build -o $(BIN_LINUX_PPC64LE) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le go build -o $(BIN_LINUX_PPC64LE) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
.PHONY: linux-s390x
|
||||
linux-s390x: $(BIN_LINUX_S390X) ## Build for Linux s390x
|
||||
|
||||
$(BIN_LINUX_S390X): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o $(BIN_LINUX_S390X) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o $(BIN_LINUX_S390X) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
.PHONY: windows
|
||||
windows: $(BIN_WINDOWS) ## Build for Windows
|
||||
|
||||
$(BIN_WINDOWS): generate/zz_filesystem_generated.go
|
||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o $(BIN_WINDOWS) -ldflags $(LDFLAGS) ./cmd/$(BIN)
|
||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o $(BIN_WINDOWS) -trimpath -ldflags "$(LDFLAGS) -w -s" ./cmd/$(BIN)
|
||||
|
||||
######################
|
||||
##@ Schemas
|
||||
######################
|
||||
|
||||
.PHONY: schema-generate
|
||||
schema-generate: schema/func_yaml-schema.json ## Generate func.yaml schema
|
||||
schema/func_yaml-schema.json: pkg/functions/function.go pkg/functions/function_*.go
|
||||
go run schema/generator/main.go
|
||||
|
||||
.PHONY: schema-check
|
||||
schema-check: ## Check that func.yaml schema is up-to-date
|
||||
mv schema/func_yaml-schema.json schema/func_yaml-schema-previous.json
|
||||
make schema-generate
|
||||
|
@ -265,3 +304,20 @@ schema-check: ## Check that func.yaml schema is up-to-date
|
|||
(echo "\n\nFunction config schema 'schema/func_yaml-schema.json' is obsolete, please run 'make schema-generate'.\n\n"; rm -rf schema/func_yaml-schema-previous.json; exit 1)
|
||||
rm -rf schema/func_yaml-schema-previous.json
|
||||
|
||||
######################
|
||||
##@ Hack scripting
|
||||
######################
|
||||
|
||||
.PHONY: hack-generate-components
|
||||
hack-generate-components: ## Regenerate components in hack/ dir
|
||||
cd hack && go run ./cmd/components
|
||||
|
||||
.PHONY: test-hack
|
||||
test-hack:
|
||||
cd hack && go test ./... -v
|
||||
|
||||
## This is used by workflows
|
||||
|
||||
.PHONY: update-builder
|
||||
__update-builder: # Used in automation
|
||||
cd hack && go run ./cmd/update-builder
|
||||
|
|
117
OWNERS_ALIASES
117
OWNERS_ALIASES
|
@ -2,95 +2,64 @@
|
|||
# Do not modify this file, instead modify peribolos/knative.yaml
|
||||
|
||||
aliases:
|
||||
client-reviewers:
|
||||
- itsmurugappan
|
||||
client-reviewers: []
|
||||
client-wg-leads:
|
||||
- dsimansk
|
||||
- navidshaikh
|
||||
- rhuss
|
||||
client-writers:
|
||||
- dsimansk
|
||||
- maximilien
|
||||
- navidshaikh
|
||||
- rhuss
|
||||
- vyasgun
|
||||
conformance-task-force-leads:
|
||||
- salaboy
|
||||
conformance-writers:
|
||||
- salaboy
|
||||
docs-reviewers:
|
||||
- nainaz
|
||||
- nak3
|
||||
- pmbanugo
|
||||
- retocode
|
||||
- skonto
|
||||
- snneji
|
||||
docs-wg-leads:
|
||||
- snneji
|
||||
docs-writers:
|
||||
- csantanapr
|
||||
- nak3
|
||||
- psschwei
|
||||
- retocode
|
||||
- skonto
|
||||
- snneji
|
||||
eventing-reviewers:
|
||||
- Leo6Leo
|
||||
- aslom
|
||||
- cali0707
|
||||
- creydr
|
||||
eventing-triage:
|
||||
- lberk
|
||||
eventing-wg-leads:
|
||||
- creydr
|
||||
- pierDipi
|
||||
eventing-writers:
|
||||
- Leo6Leo
|
||||
- aliok
|
||||
- lberk
|
||||
- lionelvillard
|
||||
- cali0707
|
||||
- creydr
|
||||
- matzew
|
||||
- odacremolbap
|
||||
- pierDipi
|
||||
func-reviewers:
|
||||
- gauron99
|
||||
- jrangelramos
|
||||
- nainaz
|
||||
func-writers:
|
||||
- gauron99
|
||||
- jrangelramos
|
||||
- lance
|
||||
- lkingland
|
||||
- matejvasek
|
||||
- matzew
|
||||
- salaboy
|
||||
- zroubalik
|
||||
functions-wg-leads:
|
||||
- lance
|
||||
- lkingland
|
||||
- salaboy
|
||||
knative-admin:
|
||||
- Vishal-Chdhry
|
||||
- creydr
|
||||
- csantanapr
|
||||
- aliok
|
||||
- arsenetar
|
||||
- cardil
|
||||
- dprotaso
|
||||
- dsimansk
|
||||
- evankanderson
|
||||
- gauron99
|
||||
- knative-automation
|
||||
- knative-prow-releaser-robot
|
||||
- knative-prow-robot
|
||||
- knative-prow-updater-robot
|
||||
- knative-test-reporter-robot
|
||||
- kvmware
|
||||
- lance
|
||||
- mchmarny
|
||||
- nainaz
|
||||
- pierDipi
|
||||
- psschwei
|
||||
- puerco
|
||||
- salaboy
|
||||
- matzew
|
||||
- skonto
|
||||
- smoser-ibm
|
||||
- upodroid
|
||||
- xtreme-sameer-vohra
|
||||
- zroubalik
|
||||
knative-release-leads:
|
||||
- Vishal-Chdhry
|
||||
- creydr
|
||||
- dprotaso
|
||||
- dsimansk
|
||||
- pierDipi
|
||||
- gauron99
|
||||
- skonto
|
||||
knative-robots:
|
||||
- knative-automation
|
||||
|
@ -102,27 +71,23 @@ aliases:
|
|||
- aliok
|
||||
- houshengbo
|
||||
- matzew
|
||||
- maximilien
|
||||
operations-wg-leads:
|
||||
- houshengbo
|
||||
operations-writers:
|
||||
- aliok
|
||||
- houshengbo
|
||||
- matzew
|
||||
- maximilien
|
||||
productivity-leads:
|
||||
- kvmware
|
||||
- cardil
|
||||
- upodroid
|
||||
productivity-reviewers:
|
||||
- evankanderson
|
||||
- mgencur
|
||||
productivity-wg-leads:
|
||||
- kvmware
|
||||
- cardil
|
||||
- upodroid
|
||||
productivity-writers:
|
||||
- cardil
|
||||
- kvmware
|
||||
- psschwei
|
||||
- upodroid
|
||||
security-wg-leads:
|
||||
- davidhadas
|
||||
|
@ -131,45 +96,31 @@ aliases:
|
|||
- davidhadas
|
||||
- evankanderson
|
||||
serving-approvers:
|
||||
- nak3
|
||||
- psschwei
|
||||
- dsimansk
|
||||
- skonto
|
||||
serving-reviewers:
|
||||
- KauzClay
|
||||
- jsanin-vmw
|
||||
- kauana
|
||||
- kvmware
|
||||
- retocode
|
||||
- skonto
|
||||
- xtreme-vikram-yadav
|
||||
serving-triage:
|
||||
- KauzClay
|
||||
- retocode
|
||||
- skonto
|
||||
serving-wg-leads:
|
||||
- dprotaso
|
||||
serving-writers:
|
||||
- dprotaso
|
||||
- nak3
|
||||
- psschwei
|
||||
- dsimansk
|
||||
- skonto
|
||||
steering-committee:
|
||||
- csantanapr
|
||||
- lance
|
||||
- nainaz
|
||||
- puerco
|
||||
- salaboy
|
||||
technical-oversight-committee:
|
||||
- aliok
|
||||
- arsenetar
|
||||
- dprotaso
|
||||
- dsimansk
|
||||
- kvmware
|
||||
- psschwei
|
||||
- zroubalik
|
||||
trademark-committee:
|
||||
- mchmarny
|
||||
- smoser-ibm
|
||||
- xtreme-sameer-vohra
|
||||
- evankanderson
|
||||
- matzew
|
||||
ux-wg-leads:
|
||||
- snneji
|
||||
- Leo6Leo
|
||||
- cali0707
|
||||
- mmejia02
|
||||
- zainabhusain227
|
||||
ux-writers:
|
||||
- snneji
|
||||
- Leo6Leo
|
||||
- cali0707
|
||||
- mmejia02
|
||||
- zainabhusain227
|
||||
|
|
|
@ -21,6 +21,11 @@ We use GitHub issues and project to track our roadmap. Please see our roadmap [h
|
|||
|
||||
## Contributing
|
||||
|
||||
We are always looking for contributions from the Function Developer community. For more information on how to participate, see the [Contribuiting Guide](docs/CONTRIBUTING.md)
|
||||
We are always looking for contributions from the Function Developer community. For more information on how to participate, see the [Contribuiting Guide](docs/CONTRIBUTING.md).
|
||||
For a list of all help wanted issues in Knative, take a look at [CLOTRIBUTOR](https://clotributor.dev/search?project=knative&page=1).
|
||||
|
||||
The `func` Working Group meets @ 10:00 US Eastern every Tuesday, we'd love to have you! For more information, see the invitation on the [Knative Team Calendar](https://calendar.google.com/calendar/u/0/embed?src=knative.team_9q83bg07qs5b9rrslp5jor4l6s@group.calendar.google.com).
|
||||
|
||||
## Roadmap
|
||||
|
||||
Our project roadmap can be found: https://github.com/orgs/knative/projects/49
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Knative Security Policy
|
||||
|
||||
We're extremely grateful for security researchers and users that report vulnerabilities to the Knative Open Source Community. All reports are thoroughly investigated by a set of community volunteers.
|
||||
|
||||
To make a report, please email the private security@knative.team list with the security details and the details expected for all Knative bug reports.
|
||||
|
||||
See [Knative Security and Disclosure Information](https://knative.dev/docs/reference/security/) for more details.
|
129
cmd/build.go
129
cmd/build.go
|
@ -1,6 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
@ -23,12 +24,13 @@ func NewBuildCmd(newClient ClientFactory) *cobra.Command {
|
|||
Short: "Build a function container",
|
||||
Long: `
|
||||
NAME
|
||||
{{rootCmdUse}} build - Build a function container locally withoud deploying
|
||||
{{rootCmdUse}} build - Build a function container locally without deploying
|
||||
|
||||
SYNOPSIS
|
||||
{{rootCmdUse}} build [-r|--registry] [--builder] [--builder-image] [--push]
|
||||
{{rootCmdUse}} build [-r|--registry] [--builder] [--builder-image]
|
||||
[--push] [--username] [--password] [--token]
|
||||
[--platform] [-p|--path] [-c|--confirm] [-v|--verbose]
|
||||
[--build-timestamp]
|
||||
[--build-timestamp] [--registry-insecure]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
@ -66,7 +68,9 @@ EXAMPLES
|
|||
|
||||
`,
|
||||
SuggestFor: []string{"biuld", "buidl", "built"},
|
||||
PreRunE: bindEnv("image", "path", "builder", "registry", "confirm", "push", "builder-image", "platform", "verbose", "build-timestamp"),
|
||||
PreRunE: bindEnv("image", "path", "builder", "registry", "confirm",
|
||||
"push", "builder-image", "base-image", "platform", "verbose",
|
||||
"build-timestamp", "registry-insecure", "username", "password", "token"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runBuild(cmd, args, newClient)
|
||||
},
|
||||
|
@ -98,6 +102,7 @@ EXAMPLES
|
|||
fmt.Sprintf("Builder to use when creating the function's container. Currently supported builders are %s. ($FUNC_BUILDER)", KnownBuilders()))
|
||||
cmd.Flags().StringP("registry", "r", cfg.Registry,
|
||||
"Container registry + registry namespace. (ex 'ghcr.io/myuser'). The full image name is automatically determined using this along with function name. ($FUNC_REGISTRY)")
|
||||
cmd.Flags().Bool("registry-insecure", cfg.RegistryInsecure, "Skip TLS certificate verification when communicating in HTTPS with the registry ($FUNC_REGISTRY_INSECURE)")
|
||||
|
||||
// Function-Context Flags:
|
||||
// Options whose value is available on the function with context only
|
||||
|
@ -105,17 +110,32 @@ EXAMPLES
|
|||
builderImage := f.Build.BuilderImages[f.Build.Builder]
|
||||
cmd.Flags().StringP("builder-image", "", builderImage,
|
||||
"Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE)")
|
||||
cmd.Flags().StringP("base-image", "", f.Build.BaseImage,
|
||||
"Override the base image for your function (host builder only)")
|
||||
cmd.Flags().StringP("image", "i", f.Image,
|
||||
"Full image name in the form [registry]/[namespace]/[name]:[tag] (optional). This option takes precedence over --registry ($FUNC_IMAGE)")
|
||||
cmd.Flags().BoolP("build-timestamp", "", false, "Use the actual time as the created time for the docker image. This is only useful for buildpacks builder.")
|
||||
|
||||
// Static Flags:
|
||||
// Options which have static defaults only (not globally configurable nor
|
||||
// persisted with the function)
|
||||
// Options which are either empty or have static defaults only (not
|
||||
// globally configurable nor persisted with the function)
|
||||
cmd.Flags().BoolP("push", "u", false,
|
||||
"Attempt to push the function image to the configured registry after being successfully built")
|
||||
cmd.Flags().StringP("platform", "", "",
|
||||
"Optionally specify a target platform, for example \"linux/amd64\" when using the s2i build strategy")
|
||||
cmd.Flags().StringP("username", "", "",
|
||||
"Username to use when pushing to the registry.")
|
||||
cmd.Flags().StringP("password", "", "",
|
||||
"Password to use when pushing to the registry.")
|
||||
cmd.Flags().StringP("token", "", "",
|
||||
"Token to use when pushing to the registry.")
|
||||
cmd.Flags().BoolP("build-timestamp", "", false, "Use the actual time as the created time for the docker image. This is only useful for buildpacks builder.")
|
||||
|
||||
// Temporarily Hidden Basic Auth Flags
|
||||
// Username, Password and Token flags, which plumb through basic auth, are
|
||||
// currently only available on the "host" builder.
|
||||
_ = cmd.Flags().MarkHidden("username")
|
||||
_ = cmd.Flags().MarkHidden("password")
|
||||
_ = cmd.Flags().MarkHidden("token")
|
||||
|
||||
// Oft-shared flags:
|
||||
addConfirmFlag(cmd, cfg.Confirm)
|
||||
|
@ -138,39 +158,21 @@ func runBuild(cmd *cobra.Command, _ []string, newClient ClientFactory) (err erro
|
|||
cfg buildConfig
|
||||
f fn.Function
|
||||
)
|
||||
if err = config.CreatePaths(); err != nil { // for possible auth.json usage
|
||||
if cfg, err = newBuildConfig().Prompt(); err != nil { // gather values into a single instruction set
|
||||
return
|
||||
}
|
||||
if cfg, err = newBuildConfig().Prompt(); err != nil {
|
||||
if err = cfg.Validate(); err != nil { // Perform any pre-validation
|
||||
return
|
||||
}
|
||||
if err = cfg.Validate(); err != nil {
|
||||
return
|
||||
}
|
||||
if f, err = fn.NewFunction(cfg.Path); err != nil {
|
||||
if f, err = fn.NewFunction(cfg.Path); err != nil { // Read in the Function
|
||||
return
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
}
|
||||
f = cfg.Configure(f) // Updates f at path to include build request values
|
||||
f = cfg.Configure(f) // Returns an f updated with values from the config (flags, envs, etc)
|
||||
|
||||
// TODO: this logic is duplicated with runDeploy. Shouild be in buildConfig
|
||||
// constructor.
|
||||
// Checks if there is a difference between defined registry and its value
|
||||
// used as a prefix in the image tag In case of a mismatch a new image tag is
|
||||
// created and used for build.
|
||||
// Do not react if image tag has been changed outside configuration
|
||||
if f.Registry != "" && !cmd.Flags().Changed("image") && strings.Index(f.Image, "/") > 0 && !strings.HasPrefix(f.Image, f.Registry) {
|
||||
prfx := f.Registry
|
||||
if prfx[len(prfx)-1:] != "/" {
|
||||
prfx = prfx + "/"
|
||||
}
|
||||
sps := strings.Split(f.Image, "/")
|
||||
updImg := prfx + sps[len(sps)-1]
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Warning: function has current image '%s' which has a different registry than the currently configured registry '%s'. The new image tag will be '%s'. To use an explicit image, use --image.\n", f.Image, f.Registry, updImg)
|
||||
f.Image = updImg
|
||||
}
|
||||
cmd.SetContext(cfg.WithValues(cmd.Context())) // Some optional settings are passed via context
|
||||
|
||||
// Client
|
||||
clientOptions, err := cfg.clientOptions()
|
||||
|
@ -181,7 +183,7 @@ func runBuild(cmd *cobra.Command, _ []string, newClient ClientFactory) (err erro
|
|||
defer done()
|
||||
|
||||
// Build
|
||||
buildOptions, err := cfg.buildOptions()
|
||||
buildOptions, err := cfg.buildOptions() // build-specific options from the finalized cfg
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -189,11 +191,10 @@ func runBuild(cmd *cobra.Command, _ []string, newClient ClientFactory) (err erro
|
|||
return
|
||||
}
|
||||
if cfg.Push {
|
||||
if f, err = client.Push(cmd.Context(), f); err != nil {
|
||||
if f, _, err = client.Push(cmd.Context(), f); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = f.Write(); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -202,6 +203,16 @@ func runBuild(cmd *cobra.Command, _ []string, newClient ClientFactory) (err erro
|
|||
return f.Stamp()
|
||||
}
|
||||
|
||||
// WithValues returns a context populated with values from the build config
|
||||
// which are provided to the system via the context.
|
||||
func (c buildConfig) WithValues(ctx context.Context) context.Context {
|
||||
// Push
|
||||
ctx = context.WithValue(ctx, fn.PushUsernameKey{}, c.Username)
|
||||
ctx = context.WithValue(ctx, fn.PushPasswordKey{}, c.Password)
|
||||
ctx = context.WithValue(ctx, fn.PushTokenKey{}, c.Token)
|
||||
return ctx
|
||||
}
|
||||
|
||||
type buildConfig struct {
|
||||
// Globals (builder, confirm, registry, verbose)
|
||||
config.Global
|
||||
|
@ -214,6 +225,10 @@ type buildConfig struct {
|
|||
// image name derivation based on registry and function name)
|
||||
Image string
|
||||
|
||||
// BaseImage is an image to build a function upon (host builder only)
|
||||
// TODO: gauron99 -- make option to add a path to dockerfile ?
|
||||
BaseImage string
|
||||
|
||||
// Path of the function implementation on local disk. Defaults to current
|
||||
// working directory of the process.
|
||||
Path string
|
||||
|
@ -224,6 +239,17 @@ type buildConfig struct {
|
|||
// Push the resulting image to the registry after building.
|
||||
Push bool
|
||||
|
||||
// Username when specifying optional basic auth.
|
||||
Username string
|
||||
|
||||
// Password when using optional basic auth. Should be provided along
|
||||
// with Username.
|
||||
Password string
|
||||
|
||||
// Token when performing basic auth using a bearer token. Should be
|
||||
// exclusive with Username and Password.
|
||||
Token string
|
||||
|
||||
// Build with the current timestamp as the created time for docker image.
|
||||
// This is only useful for buildpacks builder.
|
||||
WithTimestamp bool
|
||||
|
@ -233,16 +259,21 @@ type buildConfig struct {
|
|||
func newBuildConfig() buildConfig {
|
||||
return buildConfig{
|
||||
Global: config.Global{
|
||||
Builder: viper.GetString("builder"),
|
||||
Confirm: viper.GetBool("confirm"),
|
||||
Registry: registry(), // deferred defaulting
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
Builder: viper.GetString("builder"),
|
||||
Confirm: viper.GetBool("confirm"),
|
||||
Registry: registry(), // deferred defaulting
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
RegistryInsecure: viper.GetBool("registry-insecure"),
|
||||
},
|
||||
BuilderImage: viper.GetString("builder-image"),
|
||||
BaseImage: viper.GetString("base-image"),
|
||||
Image: viper.GetString("image"),
|
||||
Path: viper.GetString("path"),
|
||||
Platform: viper.GetString("platform"),
|
||||
Push: viper.GetBool("push"),
|
||||
Username: viper.GetString("username"),
|
||||
Password: viper.GetString("password"),
|
||||
Token: viper.GetString("token"),
|
||||
WithTimestamp: viper.GetBool("build-timestamp"),
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +288,7 @@ func (c buildConfig) Configure(f fn.Function) fn.Function {
|
|||
f.Build.BuilderImages[f.Build.Builder] = c.BuilderImage
|
||||
}
|
||||
f.Image = c.Image
|
||||
f.Build.BaseImage = c.BaseImage
|
||||
// Path, Platform and Push are not part of a function's state.
|
||||
return f
|
||||
}
|
||||
|
@ -300,16 +332,12 @@ func (c buildConfig) Prompt() (buildConfig, error) {
|
|||
// Image Name Override
|
||||
// Calculate a better image name message which shows the value of the final
|
||||
// image name as it will be calculated if an explicit image name is not used.
|
||||
var imagePromptMessageSuffix string
|
||||
if name := deriveImage(c.Image, c.Registry, c.Path); name != "" {
|
||||
imagePromptMessageSuffix = fmt.Sprintf(". if not specified, the default '%v' will be used')", name)
|
||||
}
|
||||
|
||||
qs := []*survey.Question{
|
||||
{
|
||||
Name: "image",
|
||||
Prompt: &survey.Input{
|
||||
Message: fmt.Sprintf("Image name to use (e.g. quay.io/boson/node-sample)%v:", imagePromptMessageSuffix),
|
||||
Message: "Optionally specify an exact image name to use (e.g. quay.io/boson/node-sample:latest)",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -336,10 +364,14 @@ func (c buildConfig) Validate() (err error) {
|
|||
|
||||
// Platform is only supported with the S2I builder at this time
|
||||
if c.Platform != "" && c.Builder != builders.S2I {
|
||||
err = errors.New("Only S2I builds currently support specifying platform")
|
||||
err = errors.New("only S2I builds currently support specifying platform")
|
||||
return
|
||||
}
|
||||
|
||||
// BaseImage is only supported with the host builder
|
||||
if c.BaseImage != "" && c.Builder != "host" {
|
||||
err = errors.New("only host builds support specifying the base image")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -360,22 +392,23 @@ func (c buildConfig) Validate() (err error) {
|
|||
// deployment is not the contiainer, but rather the running service.
|
||||
func (c buildConfig) clientOptions() ([]fn.Option, error) {
|
||||
o := []fn.Option{fn.WithRegistry(c.Registry)}
|
||||
if c.Builder == builders.Host {
|
||||
switch c.Builder {
|
||||
case builders.Host:
|
||||
o = append(o,
|
||||
fn.WithBuilder(oci.NewBuilder(builders.Host, c.Verbose)),
|
||||
fn.WithPusher(oci.NewPusher(false, c.Verbose)))
|
||||
} else if c.Builder == builders.Pack {
|
||||
fn.WithPusher(oci.NewPusher(c.RegistryInsecure, false, c.Verbose)))
|
||||
case builders.Pack:
|
||||
o = append(o,
|
||||
fn.WithBuilder(pack.NewBuilder(
|
||||
pack.WithName(builders.Pack),
|
||||
pack.WithTimestamp(c.WithTimestamp),
|
||||
pack.WithVerbose(c.Verbose))))
|
||||
} else if c.Builder == builders.S2I {
|
||||
case builders.S2I:
|
||||
o = append(o,
|
||||
fn.WithBuilder(s2i.NewBuilder(
|
||||
s2i.WithName(builders.S2I),
|
||||
s2i.WithVerbose(c.Verbose))))
|
||||
} else {
|
||||
default:
|
||||
return o, builders.ErrUnknownBuilder{Name: c.Builder, Known: KnownBuilders()}
|
||||
}
|
||||
return o, nil
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/mock"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestBuild_BuilderPersists ensures that the builder chosen is read from
|
||||
|
@ -88,13 +89,25 @@ func TestBuild_RegistryOrImageRequired(t *testing.T) {
|
|||
testRegistryOrImageRequired(NewBuildCmd, t)
|
||||
}
|
||||
|
||||
// TestBuild_Authentication ensures that Token and Username/Password auth
|
||||
// propagate to pushers which support them.
|
||||
func TestBuild_Authentication(t *testing.T) {
|
||||
testAuthentication(NewBuildCmd, t)
|
||||
}
|
||||
|
||||
// TestBuild_BaseImage ensures that base image is used only with the right
|
||||
// builders and propagates into f.Build.BaseImage
|
||||
func TestBuild_BaseImage(t *testing.T) {
|
||||
testBaseImage(NewBuildCmd, t)
|
||||
}
|
||||
|
||||
// TestBuild_Push ensures that the build command properly pushes and respects
|
||||
// the --push flag.
|
||||
// - Push triggered after a successful build
|
||||
// - Push not triggered after an unsuccessful build
|
||||
// - Push can be disabled
|
||||
func TestBuild_Push(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
f := fn.Function{
|
||||
Root: root,
|
||||
|
|
|
@ -15,18 +15,12 @@ import (
|
|||
"knative.dev/func/pkg/k8s"
|
||||
"knative.dev/func/pkg/knative"
|
||||
"knative.dev/func/pkg/pipelines/tekton"
|
||||
"knative.dev/func/pkg/progress"
|
||||
)
|
||||
|
||||
// ClientConfig settings for use with NewClient
|
||||
// These are the minimum settings necessary to create the default client
|
||||
// instance which has most subsystems initialized.
|
||||
type ClientConfig struct {
|
||||
// Namespace in the remote cluster to use for any client commands which
|
||||
// touch the remote. Optional. Empty namespace indicates the namespace
|
||||
// currently configured in the client's connection should be used.
|
||||
Namespace string
|
||||
|
||||
// Verbose logging. By default, logging output is kept to the bare minimum.
|
||||
// Use this flag to configure verbose logging throughout.
|
||||
Verbose bool
|
||||
|
@ -61,25 +55,22 @@ func NewTestClient(options ...fn.Option) ClientFactory {
|
|||
// 'Verbose' indicates the system should write out a higher amount of logging.
|
||||
func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
var (
|
||||
p = progress.New(cfg.Verbose) // updates the CLI
|
||||
t = newTransport(cfg.InsecureSkipVerify) // may provide a custom impl which proxies
|
||||
c = newCredentialsProvider(config.Dir(), t) // for accessing registries
|
||||
d = newKnativeDeployer(cfg.Namespace, cfg.Verbose)
|
||||
pp = newTektonPipelinesProvider(cfg.Namespace, p, c, cfg.Verbose)
|
||||
d = newKnativeDeployer(cfg.Verbose)
|
||||
pp = newTektonPipelinesProvider(c, cfg.Verbose)
|
||||
o = []fn.Option{ // standard (shared) options for all commands
|
||||
fn.WithVerbose(cfg.Verbose),
|
||||
fn.WithProgressListener(p),
|
||||
fn.WithTransport(t),
|
||||
fn.WithRepositoriesPath(config.RepositoriesPath()),
|
||||
fn.WithBuilder(buildpacks.NewBuilder(buildpacks.WithVerbose(cfg.Verbose))),
|
||||
fn.WithRemover(knative.NewRemover(cfg.Namespace, cfg.Verbose)),
|
||||
fn.WithDescriber(knative.NewDescriber(cfg.Namespace, cfg.Verbose)),
|
||||
fn.WithLister(knative.NewLister(cfg.Namespace, cfg.Verbose)),
|
||||
fn.WithRemover(knative.NewRemover(cfg.Verbose)),
|
||||
fn.WithDescriber(knative.NewDescriber(cfg.Verbose)),
|
||||
fn.WithLister(knative.NewLister(cfg.Verbose)),
|
||||
fn.WithDeployer(d),
|
||||
fn.WithPipelinesProvider(pp),
|
||||
fn.WithPusher(docker.NewPusher(
|
||||
docker.WithCredentialsProvider(c),
|
||||
docker.WithProgressListener(p),
|
||||
docker.WithTransport(t),
|
||||
docker.WithVerbose(cfg.Verbose))),
|
||||
}
|
||||
|
@ -121,10 +112,8 @@ func newCredentialsProvider(configPath string, t http.RoundTripper) docker.Crede
|
|||
return creds.NewCredentialsProvider(configPath, options...)
|
||||
}
|
||||
|
||||
func newTektonPipelinesProvider(namespace string, progress *progress.Bar, creds docker.CredentialsProvider, verbose bool) *tekton.PipelinesProvider {
|
||||
func newTektonPipelinesProvider(creds docker.CredentialsProvider, verbose bool) *tekton.PipelinesProvider {
|
||||
options := []tekton.Opt{
|
||||
tekton.WithNamespace(namespace),
|
||||
tekton.WithProgressListener(progress),
|
||||
tekton.WithCredentialsProvider(creds),
|
||||
tekton.WithVerbose(verbose),
|
||||
tekton.WithPipelineDecorator(deployDecorator{}),
|
||||
|
@ -133,9 +122,8 @@ func newTektonPipelinesProvider(namespace string, progress *progress.Bar, creds
|
|||
return tekton.NewPipelinesProvider(options...)
|
||||
}
|
||||
|
||||
func newKnativeDeployer(namespace string, verbose bool) fn.Deployer {
|
||||
func newKnativeDeployer(verbose bool) fn.Deployer {
|
||||
options := []knative.DeployerOpt{
|
||||
knative.WithDeployerNamespace(namespace),
|
||||
knative.WithDeployerVerbose(verbose),
|
||||
knative.WithDeployerDecorator(deployDecorator{}),
|
||||
}
|
||||
|
|
|
@ -22,30 +22,34 @@ func Test_NewTestClient(t *testing.T) {
|
|||
|
||||
// Factory constructor options which should be used when invoking later
|
||||
clientFn := NewTestClient(fn.WithRemover(remover))
|
||||
|
||||
// Factory should ignore options provided when invoking
|
||||
client, _ := clientFn(ClientConfig{}, fn.WithDescriber(describer))
|
||||
|
||||
// Trigger an invocation of the mocks
|
||||
err := client.Remove(context.Background(), fn.Function{Name: "test"}, true)
|
||||
// Trigger an invocation of the mocks by running the associated client
|
||||
// methods which depend on them
|
||||
err := client.Remove(context.Background(), "myfunc", "myns", fn.Function{}, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f, err := fn.NewFunction("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = client.Describe(context.Background(), "test", f)
|
||||
_, err = client.Describe(context.Background(), "myfunc", "myns", fn.Function{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure the first set of options, held on the factory, were used
|
||||
// Ensure the first set of options, held on the factory (the mock remover)
|
||||
// is invoked.
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatalf("factory (outer) options not carried through to final client instance")
|
||||
}
|
||||
// Ensure the second set of options, provided when constructing the
|
||||
// client using the factory, were ignored
|
||||
// Ensure the second set of options, provided when constructing the client
|
||||
// using the factory, are ignored.
|
||||
if describer.DescribeInvoked {
|
||||
t.Fatalf("test client factory should ignore options when invoked.")
|
||||
}
|
||||
|
||||
// This ensures that the NewTestClient function, when provided a set
|
||||
// of optional implementations (mocks) will override any which are set
|
||||
// by commands, allowing tests to "force" a command to use the mocked
|
||||
// implementations.
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ import (
|
|||
)
|
||||
|
||||
func CompleteFunctionList(cmd *cobra.Command, args []string, toComplete string) (strings []string, directive cobra.ShellCompDirective) {
|
||||
lister := knative.NewLister("", false)
|
||||
lister := knative.NewLister(false)
|
||||
|
||||
list, err := lister.List(cmd.Context())
|
||||
list, err := lister.List(cmd.Context(), "")
|
||||
if err != nil {
|
||||
directive = cobra.ShellCompDirectiveError
|
||||
return
|
||||
|
|
|
@ -111,33 +111,36 @@ func runConfigCmd(cmd *cobra.Command, args []string) (err error) {
|
|||
|
||||
switch answers.SelectedOperation {
|
||||
case "Add":
|
||||
if answers.SelectedConfig == "Volumes" {
|
||||
switch answers.SelectedConfig {
|
||||
case "Volumes":
|
||||
err = runAddVolumesPrompt(cmd.Context(), function)
|
||||
} else if answers.SelectedConfig == "Environment variables" {
|
||||
case "Environment variables":
|
||||
err = runAddEnvsPrompt(cmd.Context(), function)
|
||||
} else if answers.SelectedConfig == "Labels" {
|
||||
case "Labels":
|
||||
err = runAddLabelsPrompt(cmd.Context(), function, defaultLoaderSaver)
|
||||
} else if answers.SelectedConfig == "Git" {
|
||||
case "Git":
|
||||
err = runConfigGitSetCmd(cmd, NewClient)
|
||||
}
|
||||
case "Remove":
|
||||
if answers.SelectedConfig == "Volumes" {
|
||||
switch answers.SelectedConfig {
|
||||
case "Volumes":
|
||||
err = runRemoveVolumesPrompt(function)
|
||||
} else if answers.SelectedConfig == "Environment variables" {
|
||||
case "Environment variables":
|
||||
err = runRemoveEnvsPrompt(function)
|
||||
} else if answers.SelectedConfig == "Labels" {
|
||||
case "Labels":
|
||||
err = runRemoveLabelsPrompt(function, defaultLoaderSaver)
|
||||
} else if answers.SelectedConfig == "Git" {
|
||||
case "Git":
|
||||
err = runConfigGitRemoveCmd(cmd, NewClient)
|
||||
}
|
||||
case "List":
|
||||
if answers.SelectedConfig == "Volumes" {
|
||||
switch answers.SelectedConfig {
|
||||
case "Volumes":
|
||||
listVolumes(function)
|
||||
} else if answers.SelectedConfig == "Environment variables" {
|
||||
case "Environment variables":
|
||||
err = listEnvs(function, cmd.OutOrStdout(), Human)
|
||||
} else if answers.SelectedConfig == "Labels" {
|
||||
listLabels(function)
|
||||
} else if answers.SelectedConfig == "Git" {
|
||||
case "Labels":
|
||||
err = listLabels(function, cmd.OutOrStdout(), Human)
|
||||
case "Git":
|
||||
err = runConfigGitCmd(cmd, NewClient)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ the current directory or from the directory specified with --path.
|
|||
cmd.Flags().StringP("output", "o", "human", "Output format (human|json) ($FUNC_OUTPUT)")
|
||||
|
||||
configEnvsAddCmd := NewConfigEnvsAddCmd(loadSaver)
|
||||
configEnvsRemoveCmd := NewConfigEnvsRemoveCmd()
|
||||
configEnvsRemoveCmd := NewConfigEnvsRemoveCmd(loadSaver)
|
||||
|
||||
addPathFlag(cmd)
|
||||
addPathFlag(configEnvsAddCmd)
|
||||
|
@ -139,8 +139,8 @@ set environment variable from a secret
|
|||
return cmd
|
||||
}
|
||||
|
||||
func NewConfigEnvsRemoveCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
func NewConfigEnvsRemoveCmd(loadSaver functionLoaderSaver) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "Remove environment variable from the function configuration",
|
||||
Long: `Remove environment variable from the function configuration
|
||||
|
@ -150,17 +150,40 @@ in the current directory or from the directory specified with --path.
|
|||
`,
|
||||
Aliases: []string{"rm"},
|
||||
SuggestFor: []string{"del", "delete", "rmeove"},
|
||||
PreRunE: bindEnv("path", "verbose"),
|
||||
PreRunE: bindEnv("path", "name", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
function, err := initConfigCommand(defaultLoaderSaver)
|
||||
function, err := initConfigCommand(loadSaver)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var name string
|
||||
if cmd.Flags().Changed("name") {
|
||||
s, e := cmd.Flags().GetString("name")
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
name = s
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
envs := []fn.Env{}
|
||||
for _, v := range function.Run.Envs {
|
||||
if *v.Name != name {
|
||||
envs = append(envs, v)
|
||||
}
|
||||
}
|
||||
function.Run.Envs = envs
|
||||
return loadSaver.Save(function)
|
||||
}
|
||||
|
||||
return runRemoveEnvsPrompt(function)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("name", "", "", "Name of the environment variable.")
|
||||
return cmd
|
||||
|
||||
}
|
||||
|
||||
func listEnvs(f fn.Function, w io.Writer, outputFormat Format) error {
|
||||
|
|
|
@ -48,7 +48,7 @@ the current directory or from the directory specified with --path.
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runConfigGitCmd(cmd *cobra.Command, newClient ClientFactory) (err error) {
|
||||
func runConfigGitCmd(_ *cobra.Command, _ ClientFactory) (err error) {
|
||||
fmt.Printf("--------------------------- Function Git config ---------------------------\n")
|
||||
fmt.Printf("Not implemented yet.\n")
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ func NewConfigGitRemoveCmd(newClient ClientFactory) *cobra.Command {
|
|||
such as local generated Pipelines resources and any resources generated on the cluster.
|
||||
`,
|
||||
SuggestFor: []string{"rem", "rmeove", "del", "dle"},
|
||||
PreRunE: bindEnv("path", "namespace", "delete-local", "delete-cluster"),
|
||||
PreRunE: bindEnv("path", "delete-local", "delete-cluster"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
return runConfigGitRemoveCmd(cmd, newClient)
|
||||
},
|
||||
|
@ -37,20 +37,6 @@ func NewConfigGitRemoveCmd(newClient ClientFactory) *cobra.Command {
|
|||
fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err)
|
||||
}
|
||||
|
||||
// Function Context
|
||||
f, _ := fn.NewFunction(effectivePath())
|
||||
if f.Initialized() {
|
||||
cfg = cfg.Apply(f)
|
||||
}
|
||||
|
||||
// Flags
|
||||
//
|
||||
// Globally-Configurable Flags:
|
||||
// Options whose value may be defined globally may also exist on the
|
||||
// contextually relevant function; but sets are flattened via cfg.Apply(f)
|
||||
cmd.Flags().StringP("namespace", "n", cfg.Namespace,
|
||||
"Deploy into a specific namespace. Will use function's current namespace by default if already deployed, and the currently active namespace if it can be determined. ($FUNC_NAMESPACE)")
|
||||
|
||||
// Resources generated related Flags:
|
||||
cmd.Flags().Bool("delete-local", false, "Delete local resources (pipeline templates).")
|
||||
cmd.Flags().Bool("delete-cluster", false, "Delete cluster resources (credentials and config on the cluster).")
|
||||
|
@ -69,8 +55,6 @@ type configGitRemoveConfig struct {
|
|||
// working directory of the process.
|
||||
Path string
|
||||
|
||||
Namespace string
|
||||
|
||||
// informs whether any specific flag for deleting only a subset of resources has been set
|
||||
flagSet bool
|
||||
|
||||
|
@ -78,7 +62,7 @@ type configGitRemoveConfig struct {
|
|||
}
|
||||
|
||||
// newConfigGitRemoveConfig creates a configGitRemoveConfig populated from command flags
|
||||
func newConfigGitRemoveConfig(cmd *cobra.Command) (c configGitRemoveConfig) {
|
||||
func newConfigGitRemoveConfig(_ *cobra.Command) (c configGitRemoveConfig) {
|
||||
flagSet := false
|
||||
|
||||
// decide what resources we should delete:
|
||||
|
@ -93,8 +77,6 @@ func newConfigGitRemoveConfig(cmd *cobra.Command) (c configGitRemoveConfig) {
|
|||
}
|
||||
|
||||
c = configGitRemoveConfig{
|
||||
Namespace: viper.GetString("namespace"),
|
||||
|
||||
flagSet: flagSet,
|
||||
|
||||
metadata: pipelines.PacMetadata{
|
||||
|
@ -181,7 +163,7 @@ func runConfigGitRemoveCmd(cmd *cobra.Command, newClient ClientFactory) (err err
|
|||
return
|
||||
}
|
||||
|
||||
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
return client.RemovePAC(cmd.Context(), f, cfg.metadata)
|
||||
|
|
|
@ -25,7 +25,7 @@ func NewConfigGitSetCmd(newClient ClientFactory) *cobra.Command {
|
|||
directory or from the directory specified with --path.
|
||||
`,
|
||||
SuggestFor: []string{"add", "ad", "update", "create", "insert", "append"},
|
||||
PreRunE: bindEnv("path", "builder", "builder-image", "image", "registry", "namespace", "git-provider", "git-url", "git-branch", "git-dir", "gh-access-token", "config-local", "config-cluster", "config-remote"),
|
||||
PreRunE: bindEnv("path", "builder", "builder-image", "image", "registry", "git-provider", "git-url", "git-branch", "git-dir", "gh-access-token", "config-local", "config-cluster", "config-remote"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
return runConfigGitSetCmd(cmd, newClient)
|
||||
},
|
||||
|
@ -93,8 +93,6 @@ func NewConfigGitSetCmd(newClient ClientFactory) *cobra.Command {
|
|||
type configGitSetConfig struct {
|
||||
buildConfig // further embeds config.Global
|
||||
|
||||
Namespace string
|
||||
|
||||
GitProvider string
|
||||
GitURL string
|
||||
GitRevision string
|
||||
|
@ -107,7 +105,7 @@ type configGitSetConfig struct {
|
|||
|
||||
// newConfigGitSetConfig creates a buildConfig populated from command flags and
|
||||
// environment variables; in that precedence.
|
||||
func newConfigGitSetConfig(cmd *cobra.Command) (c configGitSetConfig) {
|
||||
func newConfigGitSetConfig(_ *cobra.Command) (c configGitSetConfig) {
|
||||
// decide what resources we should configure:
|
||||
// - by default all resources
|
||||
// - if any parameter is explicitly specified then get value from parameters
|
||||
|
@ -127,7 +125,6 @@ func newConfigGitSetConfig(cmd *cobra.Command) (c configGitSetConfig) {
|
|||
|
||||
c = configGitSetConfig{
|
||||
buildConfig: newBuildConfig(),
|
||||
Namespace: viper.GetString("namespace"),
|
||||
|
||||
GitURL: viper.GetString("git-url"),
|
||||
GitRevision: viper.GetString("git-branch"),
|
||||
|
@ -307,7 +304,7 @@ func runConfigGitSetCmd(cmd *cobra.Command, newClient ClientFactory) (err error)
|
|||
return
|
||||
}
|
||||
|
||||
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose}, fn.WithRegistry(cfg.Registry))
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose}, fn.WithRegistry(cfg.Registry))
|
||||
defer done()
|
||||
|
||||
return client.ConfigurePAC(cmd.Context(), f, cfg.metadata)
|
||||
|
|
|
@ -2,10 +2,13 @@ package cmd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"knative.dev/func/pkg/config"
|
||||
|
@ -24,16 +27,14 @@ the current directory or from the directory specified with --path.
|
|||
`,
|
||||
Aliases: []string{"label"},
|
||||
SuggestFor: []string{"albels", "abels"},
|
||||
PreRunE: bindEnv("path", "verbose"),
|
||||
PreRunE: bindEnv("path", "output", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
function, err := initConfigCommand(loaderSaver)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
listLabels(function)
|
||||
|
||||
return
|
||||
return listLabels(function, cmd.OutOrStdout(), Format(viper.GetString("output")))
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -42,20 +43,54 @@ the current directory or from the directory specified with --path.
|
|||
Short: "Add labels to the function configuration",
|
||||
Long: `Add labels to the function configuration
|
||||
|
||||
Interactive prompt to add labels to the function project in the current
|
||||
directory or from the directory specified with --path.
|
||||
If label is not set explicitly by flag, interactive prompt is used.
|
||||
|
||||
The label can be set directly from a value or from an environment variable on
|
||||
the local machine.
|
||||
`,
|
||||
Example: `# set label directly
|
||||
{{rootCmdUse}} config labels add --name=Foo --value=Bar
|
||||
|
||||
# set label from local env $FOO
|
||||
{{rootCmdUse}} config labels add --name=Foo --value='{{"{{"}} env:FOO {{"}}"}}'`,
|
||||
SuggestFor: []string{"ad", "create", "insert", "append"},
|
||||
PreRunE: bindEnv("path", "verbose"),
|
||||
PreRunE: bindEnv("path", "name", "value", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
function, err := initConfigCommand(loaderSaver)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var np *string
|
||||
var vp *string
|
||||
|
||||
if cmd.Flags().Changed("name") {
|
||||
s, e := cmd.Flags().GetString("name")
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
np = &s
|
||||
}
|
||||
if cmd.Flags().Changed("value") {
|
||||
s, e := cmd.Flags().GetString("value")
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
vp = &s
|
||||
}
|
||||
|
||||
if np != nil && vp != nil {
|
||||
if err := utils.ValidateLabelKey(*np); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := utils.ValidateLabelValue(*vp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
function.Deploy.Labels = append(function.Deploy.Labels, fn.Label{Key: np, Value: vp})
|
||||
return loaderSaver.Save(function)
|
||||
}
|
||||
|
||||
return runAddLabelsPrompt(cmd.Context(), function, loaderSaver)
|
||||
},
|
||||
}
|
||||
|
@ -70,13 +105,33 @@ directory or from the directory specified with --path.
|
|||
`,
|
||||
Aliases: []string{"rm"},
|
||||
SuggestFor: []string{"del", "delete", "rmeove"},
|
||||
PreRunE: bindEnv("path", "verbose"),
|
||||
PreRunE: bindEnv("path", "name", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
function, err := initConfigCommand(loaderSaver)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var name string
|
||||
if cmd.Flags().Changed("name") {
|
||||
s, e := cmd.Flags().GetString("name")
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
name = s
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
labels := []fn.Label{}
|
||||
for _, v := range function.Deploy.Labels {
|
||||
if v.Key == nil || *v.Key != name {
|
||||
labels = append(labels, v)
|
||||
}
|
||||
}
|
||||
function.Deploy.Labels = labels
|
||||
return loaderSaver.Save(function)
|
||||
}
|
||||
|
||||
return runRemoveLabelsPrompt(function, loaderSaver)
|
||||
},
|
||||
}
|
||||
|
@ -86,6 +141,12 @@ directory or from the directory specified with --path.
|
|||
fmt.Fprintf(configLabelsCmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err)
|
||||
}
|
||||
|
||||
// Add flags
|
||||
configLabelsCmd.Flags().StringP("output", "o", "human", "Output format (human|json)")
|
||||
configLabelsAddCmd.Flags().StringP("name", "", "", "Name of the label.")
|
||||
configLabelsAddCmd.Flags().StringP("value", "", "", "Value of the label.")
|
||||
configLabelsRemoveCmd.Flags().StringP("name", "", "", "Name of the label.")
|
||||
|
||||
addPathFlag(configLabelsCmd)
|
||||
addPathFlag(configLabelsAddCmd)
|
||||
addPathFlag(configLabelsRemoveCmd)
|
||||
|
@ -99,19 +160,31 @@ directory or from the directory specified with --path.
|
|||
return configLabelsCmd
|
||||
}
|
||||
|
||||
func listLabels(f fn.Function) {
|
||||
if len(f.Deploy.Labels) == 0 {
|
||||
fmt.Println("There aren't any configured labels")
|
||||
return
|
||||
}
|
||||
func listLabels(f fn.Function, w io.Writer, outputFormat Format) error {
|
||||
switch outputFormat {
|
||||
case Human:
|
||||
if len(f.Deploy.Labels) == 0 {
|
||||
_, err := fmt.Fprintln(w, "No labels defined")
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Configured labels:")
|
||||
for _, e := range f.Deploy.Labels {
|
||||
fmt.Println(" - ", e.String())
|
||||
fmt.Fprintln(w, "Labels:")
|
||||
for _, e := range f.Deploy.Labels {
|
||||
_, err := fmt.Fprintln(w, " - ", e.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case JSON:
|
||||
enc := json.NewEncoder(w)
|
||||
return enc.Encode(f.Deploy.Labels)
|
||||
default:
|
||||
return fmt.Errorf("invalid format: %v", outputFormat)
|
||||
}
|
||||
}
|
||||
|
||||
func runAddLabelsPrompt(ctx context.Context, f fn.Function, saver functionSaver) (err error) {
|
||||
func runAddLabelsPrompt(_ context.Context, f fn.Function, saver functionSaver) (err error) {
|
||||
|
||||
insertToIndex := 0
|
||||
|
||||
|
|
|
@ -12,8 +12,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Netflix/go-expect"
|
||||
"github.com/creack/pty"
|
||||
"github.com/hinshun/vt10x"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
)
|
||||
|
||||
|
@ -41,11 +43,17 @@ func createRunFunc(cmd *cobra.Command, t *testing.T) func(subcmd string, input .
|
|||
return func(subcmd string, input ...string) {
|
||||
|
||||
ctx := context.Background()
|
||||
c, _, err := vt10x.NewVT10XConsole()
|
||||
|
||||
ptm, pts, err := pty.Open()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
term := vt10x.New(vt10x.WithWriter(pts))
|
||||
c, err := expect.NewConsole(expect.WithStdin(ptm), expect.WithStdout(term), expect.WithCloser(ptm, pts))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { c.Close() })
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
@ -147,7 +155,7 @@ func TestListLabels(t *testing.T) {
|
|||
cmd.SetArgs([]string{})
|
||||
|
||||
ctx := context.Background()
|
||||
c, _, err := vt10x.NewVT10XConsole()
|
||||
c, err := expect.NewConsole()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -164,9 +172,9 @@ func TestListLabels(t *testing.T) {
|
|||
}()
|
||||
|
||||
expected := []string{
|
||||
`Configured labels:`,
|
||||
`- Label with key "a" and value "b"`,
|
||||
`- Label with key "c" and value "d"`,
|
||||
`Labels:`,
|
||||
` - Label with key "a" and value "b"`,
|
||||
` - Label with key "c" and value "d"`,
|
||||
}
|
||||
|
||||
// prevents the ExpectString() function from waiting indefinitely
|
||||
|
|
|
@ -66,19 +66,49 @@ func NewConfigVolumesAddCmd() *cobra.Command {
|
|||
|
||||
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
|
||||
in the current directory or from the directory specified with --path.
|
||||
|
||||
For non-interactive usage, use flags to specify the volume type and configuration.
|
||||
`,
|
||||
Example: `# Add a ConfigMap volume
|
||||
{{rootCmdUse}} config volumes add --type=configmap --source=my-config --path=/etc/config
|
||||
|
||||
# Add a Secret volume
|
||||
{{rootCmdUse}} config volumes add --type=secret --source=my-secret --path=/etc/secret
|
||||
|
||||
# Add a PersistentVolumeClaim volume
|
||||
{{rootCmdUse}} config volumes add --type=pvc --source=my-pvc --path=/data
|
||||
{{rootCmdUse}} config volumes add --type=pvc --source=my-pvc --path=/data --read-only
|
||||
|
||||
# Add an EmptyDir volume
|
||||
{{rootCmdUse}} config volumes add --type=emptydir --path=/tmp/cache
|
||||
{{rootCmdUse}} config volumes add --type=emptydir --path=/tmp/cache --size=1Gi --medium=Memory`,
|
||||
SuggestFor: []string{"ad", "create", "insert", "append"},
|
||||
PreRunE: bindEnv("path", "verbose"),
|
||||
PreRunE: bindEnv("path", "verbose", "type", "source", "mount-path", "read-only", "size", "medium"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
function, err := initConfigCommand(defaultLoaderSaver)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if flags are provided for non-interactive mode
|
||||
volumeType, _ := cmd.Flags().GetString("type")
|
||||
if volumeType != "" {
|
||||
return runAddVolume(cmd, function)
|
||||
}
|
||||
|
||||
// Fall back to interactive mode
|
||||
return runAddVolumesPrompt(cmd.Context(), function)
|
||||
},
|
||||
}
|
||||
|
||||
// Add flags for non-interactive mode
|
||||
cmd.Flags().StringP("type", "t", "", "Volume type: configmap, secret, pvc, or emptydir")
|
||||
cmd.Flags().StringP("source", "s", "", "Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)")
|
||||
cmd.Flags().StringP("mount-path", "m", "", "Path where the volume should be mounted in the container")
|
||||
cmd.Flags().BoolP("read-only", "r", false, "Mount volume as read-only (only for PVC)")
|
||||
cmd.Flags().StringP("size", "", "", "Maximum size limit for EmptyDir volume (e.g., 1Gi)")
|
||||
cmd.Flags().StringP("medium", "", "", "Storage medium for EmptyDir volume: 'Memory' or '' (default)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
@ -90,20 +120,34 @@ func NewConfigVolumesRemoveCmd() *cobra.Command {
|
|||
|
||||
Interactive prompt to remove Volume mounts from the function project
|
||||
in the current directory or from the directory specified with --path.
|
||||
|
||||
For non-interactive usage, use the --mount-path flag to specify which volume to remove.
|
||||
`,
|
||||
Example: `# Remove a volume by its mount path
|
||||
{{rootCmdUse}} config volumes remove --mount-path=/etc/config`,
|
||||
Aliases: []string{"rm"},
|
||||
SuggestFor: []string{"del", "delete", "rmeove"},
|
||||
PreRunE: bindEnv("path", "verbose"),
|
||||
PreRunE: bindEnv("path", "verbose", "mount-path"),
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
function, err := initConfigCommand(defaultLoaderSaver)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if mount-path flag is provided for non-interactive mode
|
||||
mountPath, _ := cmd.Flags().GetString("mount-path")
|
||||
if mountPath != "" {
|
||||
return runRemoveVolume(cmd, function, mountPath)
|
||||
}
|
||||
|
||||
// Fall back to interactive mode
|
||||
return runRemoveVolumesPrompt(function)
|
||||
},
|
||||
}
|
||||
|
||||
// Add flag for non-interactive mode
|
||||
cmd.Flags().StringP("mount-path", "m", "", "Path of the volume mount to remove")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
@ -227,7 +271,7 @@ func runAddVolumesPrompt(ctx context.Context, f fn.Function) (err error) {
|
|||
case optionSecret:
|
||||
newVolume.Secret = &selectedResource
|
||||
case optionPersistentVolumeClaim:
|
||||
newVolume.PresistentVolumeClaim = &fn.PersistentVolumeClaim{
|
||||
newVolume.PersistentVolumeClaim = &fn.PersistentVolumeClaim{
|
||||
ClaimName: &selectedResource,
|
||||
ReadOnly: readOnly,
|
||||
}
|
||||
|
@ -286,3 +330,104 @@ func runRemoveVolumesPrompt(f fn.Function) (err error) {
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// runAddVolume handles adding volumes using command line flags
|
||||
func runAddVolume(cmd *cobra.Command, f fn.Function) error {
|
||||
var (
|
||||
volumeType, _ = cmd.Flags().GetString("type")
|
||||
source, _ = cmd.Flags().GetString("source")
|
||||
mountPath, _ = cmd.Flags().GetString("mount-path")
|
||||
readOnly, _ = cmd.Flags().GetBool("read-only")
|
||||
sizeLimit, _ = cmd.Flags().GetString("size")
|
||||
medium, _ = cmd.Flags().GetString("medium")
|
||||
)
|
||||
|
||||
// Validate mount path
|
||||
if mountPath == "" {
|
||||
return fmt.Errorf("--mount-path is required")
|
||||
}
|
||||
if !strings.HasPrefix(mountPath, "/") {
|
||||
return fmt.Errorf("mount path must be an absolute path (start with /)")
|
||||
}
|
||||
|
||||
// Create the volume based on type
|
||||
newVolume := fn.Volume{Path: &mountPath}
|
||||
|
||||
// All volumeTypes except emptydir require a source
|
||||
if volumeType != "emptydir" && source == "" {
|
||||
return fmt.Errorf("--source is required for %s volumes", volumeType)
|
||||
}
|
||||
|
||||
switch volumeType {
|
||||
case "configmap":
|
||||
newVolume.ConfigMap = &source
|
||||
case "secret":
|
||||
newVolume.Secret = &source
|
||||
case "pvc":
|
||||
newVolume.PersistentVolumeClaim = &fn.PersistentVolumeClaim{
|
||||
ClaimName: &source,
|
||||
ReadOnly: readOnly,
|
||||
}
|
||||
if readOnly {
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "PersistentVolumeClaim will be mounted as read-only")
|
||||
}
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Please ensure the PersistentVolumeClaim extension flag is enabled:\nhttps://knative.dev/docs/serving/configuration/feature-flags/\n")
|
||||
case "emptydir":
|
||||
emptyDir := &fn.EmptyDir{}
|
||||
if sizeLimit != "" {
|
||||
emptyDir.SizeLimit = &sizeLimit
|
||||
}
|
||||
if medium != "" {
|
||||
if medium != fn.StorageMediumMemory && medium != fn.StorageMediumDefault {
|
||||
return fmt.Errorf("invalid medium: must be 'Memory' or empty")
|
||||
}
|
||||
emptyDir.Medium = medium
|
||||
}
|
||||
newVolume.EmptyDir = emptyDir
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Please make sure to enable the EmptyDir extension flag:\nhttps://knative.dev/docs/serving/configuration/feature-flags/\n")
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid volume type: %s (must be one of: configmap, secret, pvc, emptydir)", volumeType)
|
||||
}
|
||||
|
||||
// Add the volume to the function
|
||||
f.Run.Volumes = append(f.Run.Volumes, newVolume)
|
||||
|
||||
// Save the function
|
||||
err := f.Write()
|
||||
if err == nil {
|
||||
fmt.Printf("Volume entry was added to the function configuration\n")
|
||||
fmt.Printf("Added: %s\n", newVolume.String())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// runRemoveVolume handles removing volumes by mount path
|
||||
func runRemoveVolume(cmd *cobra.Command, f fn.Function, mountPath string) error {
|
||||
if !strings.HasPrefix(mountPath, "/") {
|
||||
return fmt.Errorf("mount path must be an absolute path (start with /)")
|
||||
}
|
||||
|
||||
// Find and remove the volume with the specified path
|
||||
var newVolumes []fn.Volume
|
||||
removed := false
|
||||
for _, v := range f.Run.Volumes {
|
||||
if v.Path != nil && *v.Path == mountPath {
|
||||
removed = true
|
||||
} else {
|
||||
newVolumes = append(newVolumes, v)
|
||||
}
|
||||
}
|
||||
|
||||
if !removed {
|
||||
return fmt.Errorf("no volume found with mount path: %s", mountPath)
|
||||
}
|
||||
|
||||
f.Run.Volumes = newVolumes
|
||||
err := f.Write()
|
||||
if err == nil {
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Volume entry was removed from the function configuration\n")
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Removed volume at path: %s\n", mountPath)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -141,7 +141,6 @@ func runCreate(cmd *cobra.Command, args []string, newClient ClientFactory) (err
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Confirm
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Created %v function in %v\n", cfg.Runtime, cfg.Path)
|
||||
return nil
|
||||
|
@ -535,7 +534,7 @@ func newHelpTemplate(cmd *cobra.Command) *template.Template {
|
|||
fm := template.FuncMap{
|
||||
"indent": func(i int, c string, v string) string {
|
||||
indentation := strings.Repeat(c, i)
|
||||
return indentation + strings.Replace(v, "\n", "\n"+indentation, -1)
|
||||
return indentation + strings.ReplaceAll(v, "\n", "\n"+indentation)
|
||||
},
|
||||
}
|
||||
t.Funcs(fm)
|
||||
|
|
|
@ -4,13 +4,14 @@ import (
|
|||
"errors"
|
||||
"testing"
|
||||
|
||||
. "knative.dev/func/pkg/testing"
|
||||
"knative.dev/func/pkg/utils"
|
||||
)
|
||||
|
||||
// TestCreate_Execute ensures that an invocation of create with minimal settings
|
||||
// and valid input completes without error; degenerate case.
|
||||
func TestCreate_Execute(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewCreateCmd(NewClient)
|
||||
cmd.SetArgs([]string{"--language", "go", "myfunc"})
|
||||
|
@ -23,7 +24,7 @@ func TestCreate_Execute(t *testing.T) {
|
|||
// TestCreate_NoRuntime ensures that an invocation of create must be
|
||||
// done with a runtime.
|
||||
func TestCreate_NoRuntime(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewCreateCmd(NewClient)
|
||||
cmd.SetArgs([]string{"myfunc"}) // Do not use test command args
|
||||
|
@ -38,7 +39,7 @@ func TestCreate_NoRuntime(t *testing.T) {
|
|||
// TestCreate_WithNoRuntime ensures that an invocation of create must be
|
||||
// done with one of the valid runtimes only.
|
||||
func TestCreate_WithInvalidRuntime(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewCreateCmd(NewClient)
|
||||
cmd.SetArgs([]string{"--language", "invalid", "myfunc"})
|
||||
|
@ -53,7 +54,7 @@ func TestCreate_WithInvalidRuntime(t *testing.T) {
|
|||
// TestCreate_InvalidTemplate ensures that an invocation of create must be
|
||||
// done with one of the valid templates only.
|
||||
func TestCreate_InvalidTemplate(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewCreateCmd(NewClient)
|
||||
cmd.SetArgs([]string{"--language", "go", "--template", "invalid", "myfunc"})
|
||||
|
@ -68,7 +69,7 @@ func TestCreate_InvalidTemplate(t *testing.T) {
|
|||
// TestCreate_ValidatesName ensures that the create command only accepts
|
||||
// DNS-1123 labels for function name.
|
||||
func TestCreate_ValidatesName(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
// Execute the command with a function name containing invalid characters and
|
||||
// confirm the expected error is returned
|
||||
|
@ -84,7 +85,7 @@ func TestCreate_ValidatesName(t *testing.T) {
|
|||
// TestCreate_ConfigOptional ensures that the system can be used without
|
||||
// any additional configuration being required.
|
||||
func TestCreate_ConfigOptional(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ No local files are deleted.
|
|||
{{rootCmdUse}} delete
|
||||
|
||||
# Undeploy the function 'myfunc' in namespace 'apps'
|
||||
{{rootCmdUse}} delete -n apps myfunc
|
||||
{{rootCmdUse}} delete myfunc --namespace apps
|
||||
`,
|
||||
SuggestFor: []string{"remove", "del"},
|
||||
Aliases: []string{"rm"},
|
||||
|
@ -47,7 +47,7 @@ No local files are deleted.
|
|||
}
|
||||
|
||||
// Flags
|
||||
cmd.Flags().StringP("namespace", "n", cfg.Namespace, "The namespace in which to delete. ($FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("namespace", "n", defaultNamespace(fn.Function{}, false), "The namespace when deleting by name. ($FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("all", "a", "true", "Delete all resources created for a function, eg. Pipelines, Secrets, etc. ($FUNC_ALL) (allowed values: \"true\", \"false\")")
|
||||
addConfirmFlag(cmd, cfg.Confirm)
|
||||
addPathFlag(cmd)
|
||||
|
@ -57,70 +57,63 @@ No local files are deleted.
|
|||
}
|
||||
|
||||
func runDelete(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg, err := newDeleteConfig(args).Prompt()
|
||||
cfg, err := newDeleteConfig(cmd, args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var function fn.Function
|
||||
|
||||
// Initialize func with explicit name (when provided)
|
||||
if len(args) > 0 && args[0] != "" {
|
||||
pathChanged := cmd.Flags().Changed("path")
|
||||
if pathChanged {
|
||||
return fmt.Errorf("only one of --path and [NAME] should be provided")
|
||||
}
|
||||
function = fn.Function{
|
||||
Name: args[0],
|
||||
}
|
||||
} else {
|
||||
function, err = fn.NewFunction(cfg.Path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the function has been initialized
|
||||
if !function.Initialized() {
|
||||
return fn.NewErrNotInitialized(function.Root)
|
||||
}
|
||||
|
||||
// If not provided, use the function's extant namespace
|
||||
if !cmd.Flags().Changed("namespace") {
|
||||
cfg.Namespace = function.Deploy.Namespace
|
||||
}
|
||||
|
||||
if cfg, err = cfg.Prompt(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Create a client instance from the now-final config
|
||||
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
// Invoke remove using the concrete client impl
|
||||
return client.Remove(cmd.Context(), function, cfg.DeleteAll)
|
||||
if cfg.Name != "" { // Delete by name if provided
|
||||
return client.Remove(cmd.Context(), cfg.Name, cfg.Namespace, fn.Function{}, cfg.All)
|
||||
} else { // Otherwise; delete the function at path (cwd by default)
|
||||
f, err := fn.NewFunction(cfg.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.Remove(cmd.Context(), "", "", f, cfg.All)
|
||||
}
|
||||
}
|
||||
|
||||
type deleteConfig struct {
|
||||
Name string
|
||||
Namespace string
|
||||
Path string
|
||||
DeleteAll bool
|
||||
All bool
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
// newDeleteConfig returns a config populated from the current execution context
|
||||
// (args, flags and environment variables)
|
||||
func newDeleteConfig(args []string) deleteConfig {
|
||||
func newDeleteConfig(cmd *cobra.Command, args []string) (cfg deleteConfig, err error) {
|
||||
var name string
|
||||
if len(args) > 0 {
|
||||
name = args[0]
|
||||
}
|
||||
return deleteConfig{
|
||||
Path: viper.GetString("path"),
|
||||
cfg = deleteConfig{
|
||||
All: viper.GetBool("all"),
|
||||
Name: name, // args[0] or derived
|
||||
Namespace: viper.GetString("namespace"),
|
||||
DeleteAll: viper.GetBool("all"),
|
||||
Name: deriveName(name, viper.GetString("path")), // args[0] or derived
|
||||
Verbose: viper.GetBool("verbose"), // defined on root
|
||||
Path: viper.GetString("path"),
|
||||
Verbose: viper.GetBool("verbose"), // defined on root
|
||||
}
|
||||
if cfg.Name == "" && cmd.Flags().Changed("namespace") {
|
||||
// logicially inconsistent to supply only a namespace.
|
||||
// Either use the function's local state in its entirety, or specify
|
||||
// both a name and a namespace to ignore any local function source.
|
||||
err = fmt.Errorf("must also specify a name when specifying namespace")
|
||||
}
|
||||
if cfg.Name != "" && cmd.Flags().Changed("path") {
|
||||
// logically inconsistent to provide both a name and a path to source.
|
||||
// Either use the function's local state on disk (--path), or specify
|
||||
// a name and a namespace to ignore any local function source.
|
||||
err = fmt.Errorf("only one of --path and [NAME] should be provided")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Prompt the user with value of config members, allowing for interaractive changes.
|
||||
|
@ -144,7 +137,7 @@ func (c deleteConfig) Prompt() (deleteConfig, error) {
|
|||
Name: "all",
|
||||
Prompt: &survey.Confirm{
|
||||
Message: "Do you want to delete all resources?",
|
||||
Default: c.DeleteAll,
|
||||
Default: c.All,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -159,7 +152,7 @@ func (c deleteConfig) Prompt() (deleteConfig, error) {
|
|||
}
|
||||
|
||||
dc.Name = answers.Name
|
||||
dc.DeleteAll = answers.All
|
||||
dc.All = answers.All
|
||||
|
||||
return dc, err
|
||||
}
|
||||
|
|
|
@ -1,94 +1,58 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/mock"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestDelete_Namespace ensures that the namespace provided to the client
|
||||
// for use when deleting a function is set
|
||||
// 1. The flag /env variable if provided
|
||||
// 2. The namespace of the function at path if provided
|
||||
// 3. The user's current active namespace
|
||||
func TestDelete_Namespace(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
|
||||
// Ensure that the default is "default" when no context can be identified
|
||||
t.Setenv("KUBECONFIG", filepath.Join(cwd(), "nonexistent"))
|
||||
t.Setenv("KUBERNETES_SERVICE_HOST", "")
|
||||
cmd := NewDeleteCmd(func(cc ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != "" {
|
||||
t.Fatalf("expected '', got '%v'", cc.Namespace)
|
||||
}
|
||||
return fn.New(), func() {}
|
||||
})
|
||||
cmd.SetArgs([]string{"somefunc"}) // delete by name such that no f need be created
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure the extant function's namespace is used
|
||||
f := fn.Function{
|
||||
Root: root,
|
||||
Runtime: "go",
|
||||
Deploy: fn.DeploySpec{
|
||||
Namespace: "deployed",
|
||||
},
|
||||
}
|
||||
if _, err := fn.New().Init(f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cmd = NewDeleteCmd(func(cc ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != "deployed" {
|
||||
t.Fatalf("expected 'deployed', got '%v'", cc.Namespace)
|
||||
}
|
||||
return fn.New(), func() {}
|
||||
})
|
||||
cmd.SetArgs([]string{})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure an explicit namespace is plumbed through
|
||||
cmd = NewDeleteCmd(func(cc ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != "ns" {
|
||||
t.Fatalf("expected 'ns', got '%v'", cc.Namespace)
|
||||
}
|
||||
return fn.New(), func() {}
|
||||
})
|
||||
cmd.SetArgs([]string{"--namespace", "ns"})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestDelete_ByName ensures that running delete specifying the name of the
|
||||
// function explicitly as an argument invokes the remover appropriately.
|
||||
func TestDelete_ByName(t *testing.T) {
|
||||
// TestDelete_Default ensures that the deployed function is deleted correctly
|
||||
// with default options and the default situation: running "delete" from
|
||||
// within the same directory of the function which is to be deleted.
|
||||
func TestDelete_Default(t *testing.T) {
|
||||
var (
|
||||
testname = "testname" // explicit name for the function
|
||||
remover = mock.NewRemover() // with a mock remover
|
||||
err error
|
||||
root = FromTempDirectory(t)
|
||||
name = "myfunc"
|
||||
namespace = "testns"
|
||||
remover = mock.NewRemover()
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
// Remover fails the test if it receives the incorrect name
|
||||
// an incorrect name.
|
||||
remover.RemoveFn = func(n string) error {
|
||||
if n != testname {
|
||||
t.Fatalf("expected delete name %v, got %v", testname, n)
|
||||
// Remover which confirms the name and namespace received are those
|
||||
// originally requested via the CLI flags.
|
||||
remover.RemoveFn = func(n, ns string) error {
|
||||
if n != name {
|
||||
t.Errorf("expected name '%v', got '%v'", name, n)
|
||||
}
|
||||
if ns != namespace {
|
||||
t.Errorf("expected namespace '%v', got '%v'", namespace, ns)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a command with a client constructor fn that instantiates a client
|
||||
// with a the mocked remover.
|
||||
cmd := NewDeleteCmd(NewTestClient(fn.WithRemover(remover)))
|
||||
cmd.SetArgs([]string{testname})
|
||||
// A function which will be created in the requested namespace
|
||||
f := fn.Function{
|
||||
Runtime: "go",
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
Root: root,
|
||||
Registry: TestRegistry,
|
||||
}
|
||||
|
||||
if _, f, err = fn.New().New(ctx, f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = f.Write(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewDeleteCmd(NewTestClient(fn.WithRemover(remover)))
|
||||
cmd.SetArgs([]string{})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -99,17 +63,151 @@ func TestDelete_ByName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestDelete_ByName ensures that running delete specifying the name of the
|
||||
// function explicitly as an argument invokes the remover appropriately.
|
||||
func TestDelete_ByName(t *testing.T) {
|
||||
var (
|
||||
root = FromTempDirectory(t)
|
||||
testname = "testname" // explicit name for the function
|
||||
testnamespace = "testnamespace" // explicit namespace for the function
|
||||
remover = mock.NewRemover() // with a mock remover
|
||||
err error
|
||||
)
|
||||
|
||||
// Remover fails the test if it receives the incorrect name
|
||||
remover.RemoveFn = func(n, _ string) error {
|
||||
if n != testname {
|
||||
t.Fatalf("expected delete name %v, got %v", testname, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
f := fn.Function{
|
||||
Root: root,
|
||||
Runtime: "go",
|
||||
Registry: TestRegistry,
|
||||
Name: "testname",
|
||||
}
|
||||
|
||||
if f, err = fn.New().Init(f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// simulate deployed function in namespace for the client Remover
|
||||
f.Deploy.Namespace = testnamespace
|
||||
|
||||
if err = f.Write(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a command with a client constructor fn that instantiates a client
|
||||
// with a mocked remover.
|
||||
cmd := NewDeleteCmd(NewTestClient(fn.WithRemover(remover)))
|
||||
cmd.SetArgs([]string{testname}) // run: func delete <name>
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Fail if remover's .Remove not invoked at all
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatal("fn.Remover not invoked")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDelete_Namespace ensures that remover is envoked when --namespace flag is
|
||||
// given --> func delete myfunc --namespace myns
|
||||
func TestDelete_Namespace(t *testing.T) {
|
||||
var (
|
||||
namespace = "myns"
|
||||
remover = mock.NewRemover()
|
||||
testname = "testname"
|
||||
)
|
||||
|
||||
remover.RemoveFn = func(_, ns string) error {
|
||||
if ns != namespace {
|
||||
t.Fatalf("expected delete namespace '%v', got '%v'", namespace, ns)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := NewDeleteCmd(NewTestClient(fn.WithRemover(remover)))
|
||||
cmd.SetArgs([]string{testname, "--namespace", namespace})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatal("remover was not invoked")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDelete_NamespaceFlagPriority ensures that even thought there is
|
||||
// a deployed function the namespace flag takes precedence and essentially
|
||||
// ignores the the function on disk
|
||||
func TestDelete_NamespaceFlagPriority(t *testing.T) {
|
||||
var (
|
||||
root = FromTempDirectory(t)
|
||||
namespace = "myns"
|
||||
namespace2 = "myns2"
|
||||
remover = mock.NewRemover()
|
||||
testname = "testname"
|
||||
err error
|
||||
)
|
||||
|
||||
remover.RemoveFn = func(_, ns string) error {
|
||||
if ns != namespace2 {
|
||||
t.Fatalf("expected delete namespace '%v', got '%v'", namespace2, ns)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensure the extant function's namespace is used
|
||||
f := fn.Function{
|
||||
Name: testname,
|
||||
Root: root,
|
||||
Runtime: "go",
|
||||
Registry: TestRegistry,
|
||||
Namespace: namespace,
|
||||
}
|
||||
client := fn.New()
|
||||
_, _, err = client.New(context.Background(), f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewDeleteCmd(NewTestClient(fn.WithRemover(remover)))
|
||||
cmd.SetArgs([]string{testname, "--namespace", namespace2})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatal("remover was not invoked")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDelete_NamespaceWithoutNameFails ensures that providing wrong argument
|
||||
// combination fails nice and fast (no name of the Function)
|
||||
func TestDelete_NamespaceWithoutNameFails(t *testing.T) {
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewDeleteCmd(NewTestClient())
|
||||
cmd.SetArgs([]string{"--namespace=myns"})
|
||||
if err := cmd.Execute(); err == nil {
|
||||
t.Fatal("invoking Delete with namespace BUT without name provided anywhere")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDelete_ByProject ensures that running delete with a valid project as its
|
||||
// context invokes remove and with the correct name (reads name from func.yaml)
|
||||
func TestDelete_ByProject(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
// Write a func.yaml config which specifies a name
|
||||
funcYaml := `name: bar
|
||||
namespace: ""
|
||||
namespace: "func"
|
||||
runtime: go
|
||||
image: ""
|
||||
imageDigest: ""
|
||||
builder: quay.io/boson/faas-go-builder
|
||||
builders:
|
||||
default: quay.io/boson/faas-go-builder
|
||||
|
@ -124,7 +222,7 @@ created: 2021-01-01T00:00:00+00:00
|
|||
|
||||
// A mock remover which fails if the name from the func.yaml is not received.
|
||||
remover := mock.NewRemover()
|
||||
remover.RemoveFn = func(n string) error {
|
||||
remover.RemoveFn = func(n, _ string) error {
|
||||
if n != "bar" {
|
||||
t.Fatalf("expected name 'bar', got '%v'", n)
|
||||
}
|
||||
|
@ -148,6 +246,50 @@ created: 2021-01-01T00:00:00+00:00
|
|||
}
|
||||
}
|
||||
|
||||
// TestDelete_ByPath ensures that providing only path deletes the Function
|
||||
// successfully
|
||||
func TestDelete_ByPath(t *testing.T) {
|
||||
var (
|
||||
|
||||
// A mock remover which will be sampled to ensure it is not invoked.
|
||||
remover = mock.NewRemover()
|
||||
root = FromTempDirectory(t)
|
||||
err error
|
||||
namespace = "func"
|
||||
)
|
||||
|
||||
// Ensure the extant function's namespace is used
|
||||
f := fn.Function{
|
||||
Root: root,
|
||||
Runtime: "go",
|
||||
Registry: TestRegistry,
|
||||
Deploy: fn.DeploySpec{Namespace: namespace},
|
||||
}
|
||||
|
||||
// Initialize a function in temp dir
|
||||
if f, err = fn.New().Init(f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = f.Write(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Command with a Client constructor using the mock remover.
|
||||
cmd := NewDeleteCmd(NewTestClient(fn.WithRemover(remover)))
|
||||
|
||||
// Execute the command only with the path argument
|
||||
cmd.SetArgs([]string{"-p", root})
|
||||
err = cmd.Execute()
|
||||
if err != nil {
|
||||
t.Fatalf("failed with: %v", err)
|
||||
}
|
||||
|
||||
// Also fail if remover's .Remove is not invoked.
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatal("fn.Remover not invoked despite valid argument")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDelete_NameAndPathExclusivity ensures that providing both a name and a
|
||||
// path generates an error.
|
||||
// Providing the --path (-p) flag indicates the name of the function to delete
|
||||
|
|
317
cmd/deploy.go
317
cmd/deploy.go
|
@ -5,14 +5,17 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"knative.dev/client-pkg/pkg/util"
|
||||
"knative.dev/client/pkg/util"
|
||||
|
||||
"knative.dev/func/pkg/builders"
|
||||
"knative.dev/func/pkg/config"
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
|
@ -33,6 +36,7 @@ SYNOPSIS
|
|||
[-b|--build] [--builder] [--builder-image] [-p|--push]
|
||||
[--domain] [--platform] [--build-timestamp] [--pvc-size]
|
||||
[--service-account] [-c|--confirm] [-v|--verbose]
|
||||
[--registry-insecure] [--remote-storage-class]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
@ -51,7 +55,7 @@ DESCRIPTION
|
|||
of --registry.
|
||||
|
||||
To run deploy using an interactive mode, use the --confirm (-c) option.
|
||||
This mode is useful for the first deployment in particular, since subsdequent
|
||||
This mode is useful for the first deployment in particular, since subsequent
|
||||
deployments remember most of the settings provided.
|
||||
|
||||
Building
|
||||
|
@ -124,7 +128,11 @@ EXAMPLES
|
|||
|
||||
`,
|
||||
SuggestFor: []string{"delpoy", "deplyo"},
|
||||
PreRunE: bindEnv("build", "build-timestamp", "builder", "builder-image", "confirm", "domain", "env", "git-branch", "git-dir", "git-url", "image", "namespace", "path", "platform", "push", "pvc-size", "service-account", "registry", "remote", "verbose"),
|
||||
PreRunE: bindEnv("build", "build-timestamp", "builder", "builder-image",
|
||||
"base-image", "confirm", "domain", "env", "git-branch", "git-dir",
|
||||
"git-url", "image", "namespace", "path", "platform", "push", "pvc-size",
|
||||
"service-account", "registry", "registry-insecure", "remote",
|
||||
"username", "password", "token", "verbose", "remote-storage-class"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDeploy(cmd, newClient)
|
||||
},
|
||||
|
@ -151,8 +159,7 @@ EXAMPLES
|
|||
fmt.Sprintf("Builder to use when creating the function's container. Currently supported builders are %s.", KnownBuilders()))
|
||||
cmd.Flags().StringP("registry", "r", cfg.Registry,
|
||||
"Container registry + registry namespace. (ex 'ghcr.io/myuser'). The full image name is automatically determined using this along with function name. ($FUNC_REGISTRY)")
|
||||
cmd.Flags().StringP("namespace", "n", cfg.Namespace,
|
||||
"Deploy into a specific namespace. Will use function's current namespace by default if already deployed, and the currently active namespace if it can be determined. ($FUNC_NAMESPACE)")
|
||||
cmd.Flags().Bool("registry-insecure", cfg.RegistryInsecure, "Skip TLS certificate verification when communicating in HTTPS with the registry ($FUNC_REGISTRY_INSECURE)")
|
||||
|
||||
// Function-Context Flags:
|
||||
// Options whose value is available on the function with context only
|
||||
|
@ -160,6 +167,8 @@ EXAMPLES
|
|||
builderImage := f.Build.BuilderImages[f.Build.Builder]
|
||||
cmd.Flags().String("builder-image", builderImage,
|
||||
"Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE)")
|
||||
cmd.Flags().StringP("base-image", "", f.Build.BaseImage,
|
||||
"Override the base image for your function (host builder only)")
|
||||
cmd.Flags().StringP("image", "i", f.Image,
|
||||
"Full image name in the form [registry]/[namespace]/[name]:[tag]@[digest]. This option takes precedence over --registry. Specifying digest is optional, but if it is given, 'build' and 'push' phases are disabled. ($FUNC_IMAGE)")
|
||||
|
||||
|
@ -175,8 +184,10 @@ EXAMPLES
|
|||
"Git revision (branch) to be used when deploying via the Git repository ($FUNC_GIT_BRANCH)")
|
||||
cmd.Flags().StringP("git-dir", "d", f.Build.Git.ContextDir,
|
||||
"Directory in the Git repository containing the function (default is the root) ($FUNC_GIT_DIR)")
|
||||
cmd.Flags().BoolP("remote", "R", f.Deploy.Remote,
|
||||
cmd.Flags().BoolP("remote", "R", f.Local.Remote,
|
||||
"Trigger a remote deployment. Default is to deploy and build from the local system ($FUNC_REMOTE)")
|
||||
cmd.Flags().StringP("remote-storage-class", "", f.Build.RemoteStorageClass,
|
||||
"Specify a storage class to use for the volume on-cluster during remote builds")
|
||||
cmd.Flags().String("pvc-size", f.Build.PVCSize,
|
||||
"When triggering a remote deployment, set a custom volume size to allocate for the build operation ($FUNC_PVC_SIZE)")
|
||||
cmd.Flags().String("service-account", f.Deploy.ServiceAccountName,
|
||||
|
@ -191,7 +202,22 @@ EXAMPLES
|
|||
"Push the function image to registry before deploying. ($FUNC_PUSH)")
|
||||
cmd.Flags().String("platform", "",
|
||||
"Optionally specify a specific platform to build for (e.g. linux/amd64). ($FUNC_PLATFORM)")
|
||||
cmd.Flags().StringP("username", "", "",
|
||||
"Username to use when pushing to the registry.")
|
||||
cmd.Flags().StringP("password", "", "",
|
||||
"Password to use when pushing to the registry.")
|
||||
cmd.Flags().StringP("token", "", "",
|
||||
"Token to use when pushing to the registry.")
|
||||
cmd.Flags().BoolP("build-timestamp", "", false, "Use the actual time as the created time for the docker image. This is only useful for buildpacks builder.")
|
||||
cmd.Flags().StringP("namespace", "n", defaultNamespace(f, false),
|
||||
"Deploy into a specific namespace. Will use the function's current namespace by default if already deployed, and the currently active context if it can be determined. ($FUNC_NAMESPACE)")
|
||||
|
||||
// Temporarily Hidden Basic Auth Flags
|
||||
// Username, Password and Token flags, which plumb through basic auth, are
|
||||
// currently only available on "host" builder.
|
||||
_ = cmd.Flags().MarkHidden("username")
|
||||
_ = cmd.Flags().MarkHidden("password")
|
||||
_ = cmd.Flags().MarkHidden("token")
|
||||
|
||||
// Oft-shared flags:
|
||||
addConfirmFlag(cmd, cfg.Confirm)
|
||||
|
@ -215,9 +241,6 @@ func runDeploy(cmd *cobra.Command, newClient ClientFactory) (err error) {
|
|||
cfg deployConfig
|
||||
f fn.Function
|
||||
)
|
||||
if err = config.CreatePaths(); err != nil { // for possible auth.json usage
|
||||
return
|
||||
}
|
||||
if cfg, err = newDeployConfig(cmd).Prompt(); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -227,56 +250,112 @@ func runDeploy(cmd *cobra.Command, newClient ClientFactory) (err error) {
|
|||
if f, err = fn.NewFunction(cfg.Path); err != nil {
|
||||
return
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
}
|
||||
if f, err = cfg.Configure(f); err != nil { // Updates f with deploy cfg
|
||||
return
|
||||
}
|
||||
cmd.SetContext(cfg.WithValues(cmd.Context())) // Some optional settings are passed via context
|
||||
|
||||
// TODO: this is duplicate logic with runBuild and runRun.
|
||||
// Refactor both to have this logic part of creating the buildConfig and thus
|
||||
// shared because newDeployConfig uses newBuildConfig for its embedded struct.
|
||||
if f.Registry != "" && !cmd.Flags().Changed("image") && strings.Index(f.Image, "/") > 0 && !strings.HasPrefix(f.Image, f.Registry) {
|
||||
prfx := f.Registry
|
||||
if prfx[len(prfx)-1:] != "/" {
|
||||
prfx = prfx + "/"
|
||||
if !f.Initialized() {
|
||||
if !cfg.Remote || f.Build.Git.URL == "" {
|
||||
// Only error if this is not a fully remote build
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
} else {
|
||||
// TODO: this case is not supported because the pipeline
|
||||
// implementation requires the function's name, which is in the
|
||||
// remote repository. We should inspect the remote repository.
|
||||
// For now, give a more helpful error.
|
||||
return errors.New("please ensure the function's source is also available locally")
|
||||
}
|
||||
}
|
||||
|
||||
changingNamespace := func(f fn.Function) bool {
|
||||
// We're changing namespace if:
|
||||
return f.Deploy.Namespace != "" && // it's already deployed
|
||||
f.Namespace != "" && // a specific (new) namespace is requested
|
||||
(f.Namespace != f.Deploy.Namespace) // and it's different
|
||||
}
|
||||
|
||||
// If we're changing namespace in an OpenShift cluster, we have to
|
||||
// also update the registry because there is a registry per namespace,
|
||||
// and their name includes the namespace.
|
||||
// This saves needing a manual flag ``--registry={destination namespace registry}``
|
||||
if changingNamespace(f) && k8s.IsOpenShift() {
|
||||
// TODO(lkingland): this appears to force use of the openshift
|
||||
// internal registry.
|
||||
f.Registry = "image-registry.openshift-image-registry.svc:5000/" + f.Namespace
|
||||
if cfg.Verbose {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Info: Overriding openshift registry to %s\n", f.Registry)
|
||||
}
|
||||
sps := strings.Split(f.Image, "/")
|
||||
updImg := prfx + sps[len(sps)-1]
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Warning: function has current image '%s' which has a different registry than the currently configured registry '%s'. The new image tag will be '%s'. To use an explicit image, use --image.\n", f.Image, f.Registry, updImg)
|
||||
f.Image = updImg
|
||||
}
|
||||
|
||||
// Informative non-error messages regarding the final deployment request
|
||||
printDeployMessages(cmd.OutOrStdout(), cfg)
|
||||
printDeployMessages(cmd.OutOrStdout(), f)
|
||||
|
||||
// Get options based on the value of the config such as concrete impls
|
||||
// of builders and pushers based on the value of the --builder flag
|
||||
clientOptions, err := cfg.clientOptions()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
client, done := newClient(ClientConfig{Namespace: f.Deploy.Namespace, Verbose: cfg.Verbose}, clientOptions...)
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose, InsecureSkipVerify: cfg.RegistryInsecure}, clientOptions...)
|
||||
defer done()
|
||||
|
||||
// Deploy
|
||||
if cfg.Remote {
|
||||
var url string
|
||||
// Invoke a remote build/push/deploy pipeline
|
||||
// Returned is the function with fields like Registry and Image populated.
|
||||
if f, err = client.RunPipeline(cmd.Context(), f); err != nil {
|
||||
// Returned is the function with fields like Registry, f.Deploy.Image &
|
||||
// f.Deploy.Namespace populated.
|
||||
if url, f, err = client.RunPipeline(cmd.Context(), f); err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Function Deployed at %v\n", url)
|
||||
} else {
|
||||
var buildOptions []fn.BuildOption
|
||||
if buildOptions, err = cfg.buildOptions(); err != nil {
|
||||
return
|
||||
}
|
||||
if f, err = build(cmd, cfg.Build, f, client, buildOptions); err != nil {
|
||||
return
|
||||
}
|
||||
if cfg.Push {
|
||||
if f, err = client.Push(cmd.Context(), f); err != nil {
|
||||
|
||||
var (
|
||||
digested bool
|
||||
justBuilt bool
|
||||
justPushed bool
|
||||
)
|
||||
|
||||
// Validate the image and check whether its digested or not
|
||||
if cfg.Image != "" {
|
||||
digested, err = isDigested(cfg.Image)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// image is valid and undigested
|
||||
if !digested {
|
||||
f.Deploy.Image = cfg.Image
|
||||
}
|
||||
}
|
||||
|
||||
// If user provided --image with digest, they are requesting that specific
|
||||
// image to be used which means building phase should be skipped and image
|
||||
// should be deployed as is
|
||||
if digested {
|
||||
f.Deploy.Image = cfg.Image
|
||||
} else {
|
||||
// NOT digested, build & push the Function unless specified otherwise
|
||||
if f, justBuilt, err = build(cmd, cfg.Build, f, client, buildOptions); err != nil {
|
||||
return
|
||||
}
|
||||
if cfg.Push {
|
||||
if f, justPushed, err = client.Push(cmd.Context(), f); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// TODO: gauron99 - temporary fix for undigested image direct deploy
|
||||
// (w/out build) This might be more complex to do than leaving like this
|
||||
// image digests are created via the registry on push.
|
||||
if (justBuilt || justPushed) && f.Build.Image != "" {
|
||||
// f.Build.Image is set in Push for now, just set it as a deployed image
|
||||
f.Deploy.Image = f.Build.Image
|
||||
}
|
||||
}
|
||||
if f, err = client.Deploy(cmd.Context(), f, fn.WithDeploySkipBuildCheck(cfg.Build == "false")); err != nil {
|
||||
return
|
||||
|
@ -299,26 +378,29 @@ func runDeploy(cmd *cobra.Command, newClient ClientFactory) (err error) {
|
|||
// flag value is explicitly truthy such as 'true' or '1'. Error if flag
|
||||
// is neither 'auto' nor parseable as a boolean. Return CLI-specific error
|
||||
// message verbeage suitable for both Deploy and Run commands which feature an
|
||||
// optional build step.
|
||||
func build(cmd *cobra.Command, flag string, f fn.Function, client *fn.Client, buildOptions []fn.BuildOption) (fn.Function, error) {
|
||||
// optional build step. Boolean return value signifies if the image has gone
|
||||
// through a build process.
|
||||
func build(cmd *cobra.Command, flag string, f fn.Function, client *fn.Client, buildOptions []fn.BuildOption) (fn.Function, bool, error) {
|
||||
var err error
|
||||
if flag == "auto" {
|
||||
if f.Built() {
|
||||
fmt.Fprintln(cmd.OutOrStdout(), "function up-to-date. Force rebuild with --build")
|
||||
return f, false, nil
|
||||
} else {
|
||||
if f, err = client.Build(cmd.Context(), f, buildOptions...); err != nil {
|
||||
return f, err
|
||||
return f, false, err
|
||||
}
|
||||
}
|
||||
} else if build, _ := strconv.ParseBool(flag); build {
|
||||
if f, err = client.Build(cmd.Context(), f, buildOptions...); err != nil {
|
||||
return f, err
|
||||
return f, false, err
|
||||
}
|
||||
} else if _, err = strconv.ParseBool(flag); err != nil {
|
||||
return f, fmt.Errorf("--build ($FUNC_BUILD) %q not recognized. Should be 'auto' or a truthy value such as 'true', 'false', '0', or '1'.", flag)
|
||||
|
||||
return f, false, fmt.Errorf("invalid value for the build flag (%q), valid value is either 'auto' or a boolean", flag)
|
||||
} else if !build {
|
||||
return f, false, nil
|
||||
}
|
||||
return f, nil
|
||||
return f, true, nil
|
||||
}
|
||||
|
||||
func NewRegistryValidator(path string) survey.Validator {
|
||||
|
@ -365,18 +447,7 @@ func KnownBuilders() builders.Known {
|
|||
// However, future third-party integrations may support less than, or more
|
||||
// builders, and certain environmental considerations may alter this list.
|
||||
|
||||
// Also a good place to stick feature-flags; to wit:
|
||||
enable_host, _ := strconv.ParseBool(os.Getenv("FUNC_ENABLE_HOST_BUILDER"))
|
||||
if !enable_host {
|
||||
bb := []string{}
|
||||
for _, b := range builders.All() {
|
||||
if b != builders.Host {
|
||||
bb = append(bb, b)
|
||||
}
|
||||
}
|
||||
return bb
|
||||
}
|
||||
|
||||
// Also a good place to stick feature-flags.
|
||||
return builders.All()
|
||||
}
|
||||
|
||||
|
@ -451,6 +522,10 @@ type deployConfig struct {
|
|||
// be triggered in a remote environment rather than run locally.
|
||||
Remote bool
|
||||
|
||||
// RemoteStorageClass defines the storage class to use for the remote
|
||||
// volume when building on-cluster.
|
||||
RemoteStorageClass string
|
||||
|
||||
// PVCSize configures the PVC size used by the pipeline if --remote flag is set.
|
||||
PVCSize string
|
||||
|
||||
|
@ -461,8 +536,8 @@ type deployConfig struct {
|
|||
|
||||
// newDeployConfig creates a buildConfig populated from command flags and
|
||||
// environment variables; in that precedence.
|
||||
func newDeployConfig(cmd *cobra.Command) (c deployConfig) {
|
||||
c = deployConfig{
|
||||
func newDeployConfig(cmd *cobra.Command) deployConfig {
|
||||
cfg := deployConfig{
|
||||
buildConfig: newBuildConfig(),
|
||||
Build: viper.GetString("build"),
|
||||
Env: viper.GetStringSlice("env"),
|
||||
|
@ -472,6 +547,7 @@ func newDeployConfig(cmd *cobra.Command) (c deployConfig) {
|
|||
GitURL: viper.GetString("git-url"),
|
||||
Namespace: viper.GetString("namespace"),
|
||||
Remote: viper.GetBool("remote"),
|
||||
RemoteStorageClass: viper.GetString("remote-storage-class"),
|
||||
PVCSize: viper.GetString("pvc-size"),
|
||||
Timestamp: viper.GetBool("build-timestamp"),
|
||||
ServiceAccountName: viper.GetString("service-account"),
|
||||
|
@ -480,10 +556,11 @@ func newDeployConfig(cmd *cobra.Command) (c deployConfig) {
|
|||
// results and appears to be an open issue since 2017:
|
||||
// https://github.com/spf13/viper/issues/380
|
||||
var err error
|
||||
if c.Env, err = cmd.Flags().GetStringArray("env"); err != nil {
|
||||
if cfg.Env, err = cmd.Flags().GetStringArray("env"); err != nil {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "error reading envs: %v", err)
|
||||
}
|
||||
return
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Configure the given function. Updates a function struct with all
|
||||
|
@ -502,12 +579,13 @@ func (c deployConfig) Configure(f fn.Function) (fn.Function, error) {
|
|||
|
||||
// Configure basic members
|
||||
f.Domain = c.Domain
|
||||
f.Namespace = c.Namespace
|
||||
f.Build.Git.URL = c.GitURL
|
||||
f.Build.Git.ContextDir = c.GitDir
|
||||
f.Build.Git.Revision = c.GitBranch // TODO: should match; perhaps "refSpec"
|
||||
f.Deploy.Namespace = c.Namespace
|
||||
f.Deploy.Remote = c.Remote
|
||||
f.Build.RemoteStorageClass = c.RemoteStorageClass
|
||||
f.Deploy.ServiceAccountName = c.ServiceAccountName
|
||||
f.Local.Remote = c.Remote
|
||||
|
||||
// PVCSize
|
||||
// If a specific value is requested, ensure it parses as a resource.Quantity
|
||||
|
@ -518,17 +596,6 @@ func (c deployConfig) Configure(f fn.Function) (fn.Function, error) {
|
|||
f.Build.PVCSize = c.PVCSize
|
||||
}
|
||||
|
||||
// ImageDigest
|
||||
// Parsed off f.Image if provided. Deploying adds the ability to specify a
|
||||
// digest on the associated image (not available on build as nonsensical).
|
||||
newDigest, err := imageDigest(f.Image)
|
||||
if err != nil {
|
||||
return f, err
|
||||
}
|
||||
if newDigest != "" {
|
||||
f.ImageDigest = newDigest
|
||||
}
|
||||
|
||||
// Envs
|
||||
// Preprocesses any Envs provided (which may include removals) into a final
|
||||
// set
|
||||
|
@ -625,10 +692,11 @@ func (c deployConfig) Validate(cmd *cobra.Command) (err error) {
|
|||
}
|
||||
|
||||
// Check Image Digest was included
|
||||
// (will be set on the function during .Configure)
|
||||
var digest string
|
||||
if digest, err = imageDigest(c.Image); err != nil {
|
||||
return
|
||||
var digest bool
|
||||
if c.Image != "" {
|
||||
if digest, err = isDigested(c.Image); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// --build can be "auto"|true|false
|
||||
|
@ -643,12 +711,14 @@ func (c deployConfig) Validate(cmd *cobra.Command) (err error) {
|
|||
v, _ := strconv.ParseBool(s)
|
||||
return v
|
||||
}
|
||||
if digest != "" && truthy(c.Build) {
|
||||
|
||||
// Can not build when specifying an --image with digest
|
||||
if digest && truthy(c.Build) {
|
||||
return errors.New("building can not be enabled when using an image with digest")
|
||||
}
|
||||
|
||||
// Can not push when specifying an --image with digest
|
||||
if digest != "" && c.Push {
|
||||
if digest && c.Push {
|
||||
return errors.New("pushing is not valid when specifying an image with digest")
|
||||
}
|
||||
|
||||
|
@ -672,54 +742,25 @@ func (c deployConfig) Validate(cmd *cobra.Command) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// imageDigest returns the image digest from a full image string if it exists,
|
||||
// and includes basic validation that a provided digest is correctly formatted.
|
||||
func imageDigest(v string) (digest string, err error) {
|
||||
vv := strings.Split(v, "@")
|
||||
if len(vv) < 2 {
|
||||
return // has no digest
|
||||
} else if len(vv) > 2 {
|
||||
err = fmt.Errorf("image '%v' contains an invalid digest (extra '@')", v)
|
||||
return
|
||||
}
|
||||
digest = vv[1]
|
||||
|
||||
if !strings.HasPrefix(digest, "sha256:") {
|
||||
err = fmt.Errorf("image digest '%s' requires 'sha256:' prefix", digest)
|
||||
return
|
||||
}
|
||||
|
||||
if len(digest[7:]) != 64 {
|
||||
err = fmt.Errorf("image digest '%v' has an invalid sha256 hash length of %v when it should be 64", digest, len(digest[7:]))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// printDeployMessages to the output. Non-error deployment messages.
|
||||
func printDeployMessages(out io.Writer, cfg deployConfig) {
|
||||
// Digest
|
||||
// ------
|
||||
// If providing an image digest, print this, and note that the values
|
||||
// of push and build are ignored.
|
||||
// TODO: perhaps just error if either --push or --build were actually
|
||||
// provided (using the cobra .Changed accessor)
|
||||
digest, err := imageDigest(cfg.Image)
|
||||
if err != nil && digest != "" {
|
||||
fmt.Fprintf(out, "Deploying image '%v' with digest '%s'. Build and push are disabled.\n", cfg.Image, digest)
|
||||
func printDeployMessages(out io.Writer, f fn.Function) {
|
||||
digest, err := isDigested(f.Image)
|
||||
if err == nil && digest {
|
||||
fmt.Fprintf(out, "Deploying image '%v', which has a digest. Build and push are disabled.\n", f.Image)
|
||||
}
|
||||
|
||||
// Namespace
|
||||
// ---------
|
||||
f, _ := fn.NewFunction(cfg.Path)
|
||||
currentNamespace := f.Deploy.Namespace // will be "" if no initialed f at path.
|
||||
targetNamespace := cfg.Namespace
|
||||
targetNamespace := f.Namespace
|
||||
if targetNamespace == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// If potentially creating a duplicate deployed function in a different
|
||||
// namespace. TODO: perhaps add a --delete or --force flag which will
|
||||
// automagically delete the deployment in the "old" namespace.
|
||||
// If creating a duplicate deployed function in a different
|
||||
// namespace.
|
||||
if targetNamespace != currentNamespace && currentNamespace != "" {
|
||||
fmt.Fprintf(out, "Warning: function is in namespace '%s', but requested namespace is '%s'. Continuing with deployment to '%v'.\n", currentNamespace, targetNamespace, targetNamespace)
|
||||
fmt.Fprintf(out, "Info: chosen namespace has changed from '%s' to '%s'. Undeploying function from '%s' and deploying new in '%s'.\n", currentNamespace, targetNamespace, currentNamespace, targetNamespace)
|
||||
}
|
||||
|
||||
// Namespace Changing
|
||||
|
@ -727,9 +768,9 @@ func printDeployMessages(out io.Writer, cfg deployConfig) {
|
|||
// If the target namespace is provided but differs from active, warn because
|
||||
// the function won't be visible to other commands such as kubectl unless
|
||||
// context namespace is switched.
|
||||
activeNamespace, err := k8s.GetNamespace("")
|
||||
activeNamespace, err := k8s.GetDefaultNamespace()
|
||||
if err == nil && targetNamespace != "" && targetNamespace != activeNamespace {
|
||||
fmt.Fprintf(out, "Warning: namespace chosen is '%s', but currently active namespace is '%s'. Continuing with deployment to '%s'.\n", cfg.Namespace, activeNamespace, cfg.Namespace)
|
||||
fmt.Fprintf(out, "Warning: namespace chosen is '%s', but currently active namespace is '%s'. Continuing with deployment to '%s'.\n", targetNamespace, activeNamespace, targetNamespace)
|
||||
}
|
||||
|
||||
// Git Args
|
||||
|
@ -749,8 +790,50 @@ func printDeployMessages(out io.Writer, cfg deployConfig) {
|
|||
// function source does include a reference to a git repository, but that it
|
||||
// will be ignored in favor of the local source code since --remote was not
|
||||
// specified.
|
||||
if !cfg.Remote && (cfg.GitURL != "" || cfg.GitBranch != "" || cfg.GitDir != "") {
|
||||
|
||||
// TODO update names of these to Source--Revision--Dir
|
||||
if !f.Local.Remote && (f.Build.Git.URL != "" || f.Build.Git.Revision != "" || f.Build.Git.ContextDir != "") {
|
||||
fmt.Fprintf(out, "Warning: git settings are only applicable when running with --remote. Local source code will be used.")
|
||||
}
|
||||
|
||||
// Git Branch Mismatch
|
||||
// -------------------
|
||||
// When doing a remote build with --git-branch, warn if the local branch
|
||||
// doesn't match, as this can lead to confusion about which func.yaml is used.
|
||||
if f.Local.Remote && f.Build.Git.URL != "" && f.Build.Git.Revision != "" {
|
||||
// Doing a remote build, specified a git repository to pull from, and
|
||||
// specified a reference within that remote.
|
||||
currentBranch, err := getCurrentGitBranch()
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, "Warning: unable to verify local and remote references match. %v\n", err)
|
||||
} else if currentBranch != f.Build.Git.Revision {
|
||||
fmt.Fprintf(out, "Warning: Local git branch '%s' does not match --git-branch '%s'. The local func.yaml will be used for function metadata (name, runtime, etc). Ensure your local branch matches the remote branch to avoid deployment issues.\n", currentBranch, f.Build.Git.Revision)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getCurrentGitBranch returns the current git branch name
|
||||
func getCurrentGitBranch() (string, error) {
|
||||
gitCmd := os.Getenv("FUNC_GIT")
|
||||
if gitCmd == "" {
|
||||
gitCmd = "git"
|
||||
}
|
||||
|
||||
cmd := exec.Command(gitCmd, "rev-parse", "--abbrev-ref", "HEAD")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(output)), nil
|
||||
}
|
||||
|
||||
// isDigested checks that the given image reference has a digest. Invalid
|
||||
// reference return error.
|
||||
func isDigested(v string) (validDigest bool, err error) {
|
||||
ref, err := name.ParseReference(v)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, ok := ref.(name.Digest)
|
||||
return ok, nil
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
102
cmd/describe.go
102
cmd/describe.go
|
@ -3,6 +3,7 @@ package cmd
|
|||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -49,7 +50,7 @@ the current directory or from the directory specified with --path.
|
|||
|
||||
// Flags
|
||||
cmd.Flags().StringP("output", "o", "human", "Output format (human|plain|json|xml|yaml|url) ($FUNC_OUTPUT)")
|
||||
cmd.Flags().StringP("namespace", "n", cfg.Namespace, "The namespace in which to look for the named function. ($FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("namespace", "n", defaultNamespace(fn.Function{}, false), "The namespace in which to look for the named function. ($FUNC_NAMESPACE)")
|
||||
addPathFlag(cmd)
|
||||
addVerboseFlag(cmd, cfg.Verbose)
|
||||
|
||||
|
@ -61,43 +62,36 @@ the current directory or from the directory specified with --path.
|
|||
}
|
||||
|
||||
func runDescribe(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg := newDescribeConfig(args)
|
||||
|
||||
if err = cfg.Validate(cmd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var f fn.Function
|
||||
|
||||
if cfg.Name == "" {
|
||||
if f, err = fn.NewFunction(cfg.Path); err != nil {
|
||||
return
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
}
|
||||
// Use Function's Namespace with precedence
|
||||
//
|
||||
// Unless the namespace flag was explicitly provided (not the default),
|
||||
// use the function's current namespace.
|
||||
//
|
||||
// TODO(lkingland): this stanza can be removed when Global Config: Function
|
||||
// Context is merged.
|
||||
if !cmd.Flags().Changed("namespace") {
|
||||
cfg.Namespace = f.Deploy.Namespace
|
||||
}
|
||||
}
|
||||
|
||||
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
// TODO(lkingland): update API to use the above function instance rather than path
|
||||
d, err := client.Describe(cmd.Context(), cfg.Name, f)
|
||||
cfg, err := newDescribeConfig(cmd, args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// TODO cfg.Prompt()
|
||||
|
||||
write(os.Stdout, info(d), cfg.Output)
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
var details fn.Instance
|
||||
if cfg.Name != "" { // Describe by name if provided
|
||||
details, err = client.Describe(cmd.Context(), cfg.Name, cfg.Namespace, fn.Function{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
f, err := fn.NewFunction(cfg.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return errors.New("function not found at this path and no name provided")
|
||||
}
|
||||
details, err = client.Describe(cmd.Context(), "", "", f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
write(os.Stdout, info(details), cfg.Output)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -112,22 +106,29 @@ type describeConfig struct {
|
|||
Verbose bool
|
||||
}
|
||||
|
||||
func newDescribeConfig(args []string) describeConfig {
|
||||
c := describeConfig{
|
||||
func newDescribeConfig(cmd *cobra.Command, args []string) (cfg describeConfig, err error) {
|
||||
var name string
|
||||
if len(args) > 0 {
|
||||
name = args[0]
|
||||
}
|
||||
cfg = describeConfig{
|
||||
Name: name,
|
||||
Namespace: viper.GetString("namespace"),
|
||||
Output: viper.GetString("output"),
|
||||
Path: viper.GetString("path"),
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
}
|
||||
if len(args) > 0 {
|
||||
c.Name = args[0]
|
||||
if cfg.Name == "" && cmd.Flags().Changed("namespace") {
|
||||
// logicially inconsistent to supply only a namespace.
|
||||
// Either use the function's local state in its entirety, or specify
|
||||
// both a name and a namespace to ignore any local function source.
|
||||
err = fmt.Errorf("must also specify a name when specifying namespace")
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c describeConfig) Validate(cmd *cobra.Command) (err error) {
|
||||
if c.Name != "" && c.Path != "" && cmd.Flags().Changed("path") {
|
||||
return fmt.Errorf("Only one of --path or [NAME] should be provided")
|
||||
if cfg.Name != "" && cmd.Flags().Changed("path") {
|
||||
// logically inconsistent to provide both a name and a path to source.
|
||||
// Either use the function's local state on disk (--path), or specify
|
||||
// a name and a namespace to ignore any local function source.
|
||||
err = fmt.Errorf("only one of --path and [NAME] should be provided")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -156,6 +157,13 @@ func (i info) Human(w io.Writer) error {
|
|||
fmt.Fprintf(w, " %v %v %v\n", s.Source, s.Type, s.Broker)
|
||||
}
|
||||
}
|
||||
|
||||
if len(i.Labels) > 0 {
|
||||
fmt.Fprintln(w, "Labels:")
|
||||
for k, v := range i.Labels {
|
||||
fmt.Fprintf(w, " %v: %v\n", k, v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -173,6 +181,12 @@ func (i info) Plain(w io.Writer) error {
|
|||
fmt.Fprintf(w, "Subscription %v %v %v\n", s.Source, s.Type, s.Broker)
|
||||
}
|
||||
}
|
||||
|
||||
if len(i.Labels) > 0 {
|
||||
for k, v := range i.Labels {
|
||||
fmt.Fprintf(w, "Label %v %v\n", k, v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,67 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/mock"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestDescribe_Default ensures that running describe when there is no
|
||||
// function in the given directory fails correctly.
|
||||
func TestDescribe_Default(t *testing.T) {
|
||||
_ = FromTempDirectory(t)
|
||||
describer := mock.NewDescriber()
|
||||
|
||||
cmd := NewDescribeCmd(NewTestClient(fn.WithDescriber(describer)))
|
||||
cmd.SetArgs([]string{})
|
||||
err := cmd.Execute()
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("describing a nonexistent function should error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "function not found at this path and no name provided") {
|
||||
t.Fatalf("Unexpected error text returned: %v", err)
|
||||
}
|
||||
if describer.DescribeInvoked {
|
||||
t.Fatal("Describer incorrectly invoked")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDescribe_Undeployed ensures that describing a function which exists,
|
||||
// but has not been deployed, does not error but rather delegates to the
|
||||
// deployer which will presumably describe it as being !deployed (See deployer
|
||||
// test suite)
|
||||
func TestDescribe_Undeployed(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
client := fn.New()
|
||||
_, err := client.Init(fn.Function{
|
||||
Name: "testfunc",
|
||||
Runtime: "go",
|
||||
Registry: TestRegistry,
|
||||
Root: root,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
describer := mock.NewDescriber()
|
||||
|
||||
cmd := NewDescribeCmd(NewTestClient(fn.WithDescriber(describer)))
|
||||
cmd.SetArgs([]string{})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !describer.DescribeInvoked {
|
||||
t.Fatal("Describer should have been invoked for any initialized function")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDescribe_ByName ensures that describing a function by name invokes
|
||||
// the describer appropriately.
|
||||
func TestDescribe_ByName(t *testing.T) {
|
||||
|
@ -15,9 +70,9 @@ func TestDescribe_ByName(t *testing.T) {
|
|||
describer = mock.NewDescriber()
|
||||
)
|
||||
|
||||
describer.DescribeFn = func(n string) (fn.Instance, error) {
|
||||
if n != testname {
|
||||
t.Fatalf("expected describe name '%v', got '%v'", testname, n)
|
||||
describer.DescribeFn = func(_ context.Context, name, namespace string) (fn.Instance, error) {
|
||||
if name != testname {
|
||||
t.Fatalf("expected describe name '%v', got '%v'", testname, name)
|
||||
}
|
||||
return fn.Instance{}, nil
|
||||
}
|
||||
|
@ -37,10 +92,11 @@ func TestDescribe_ByName(t *testing.T) {
|
|||
// (func created in the current working directory) invokes the describer with
|
||||
// its name correctly.
|
||||
func TestDescribe_ByProject(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
root := FromTempDirectory(t)
|
||||
expected := "testname"
|
||||
|
||||
_, err := fn.New().Init(fn.Function{
|
||||
Name: "testname",
|
||||
Name: expected,
|
||||
Runtime: "go",
|
||||
Registry: TestRegistry,
|
||||
Root: root,
|
||||
|
@ -50,9 +106,9 @@ func TestDescribe_ByProject(t *testing.T) {
|
|||
}
|
||||
|
||||
describer := mock.NewDescriber()
|
||||
describer.DescribeFn = func(n string) (i fn.Instance, err error) {
|
||||
if n != "testname" {
|
||||
t.Fatalf("expected describer to receive name 'testname', got '%v'", n)
|
||||
describer.DescribeFn = func(_ context.Context, name, namespace string) (i fn.Instance, err error) {
|
||||
if name != expected {
|
||||
t.Fatalf("expected describer to receive name %q, got %q", expected, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -77,63 +133,3 @@ func TestDescribe_NameAndPathExclusivity(t *testing.T) {
|
|||
t.Fatal("describer was invoked when conflicting flags were provided")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDescribe_Namespace ensures that the namespace provided to the client
|
||||
// for use when describing a function is set
|
||||
// 1. Blank when not provided nor available (delegate to the describer impl to
|
||||
// choose current kube context)
|
||||
// 2. The namespace of the contextually active function
|
||||
// 3. The flag /env variable if provided
|
||||
func TestDescribe_Namespace(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
|
||||
client := fn.New(fn.WithDescriber(mock.NewDescriber()))
|
||||
|
||||
// Ensure that the default is "", indicating the describer should use
|
||||
// config.DefaultNamespace
|
||||
cmd := NewDescribeCmd(func(cc ClientConfig, _ ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != "" {
|
||||
t.Fatalf("expected '', got '%v'", cc.Namespace)
|
||||
}
|
||||
return client, func() {}
|
||||
})
|
||||
cmd.SetArgs([]string{"somefunc"}) // by name such that no f need be created
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure the extant function's namespace is used
|
||||
f := fn.Function{
|
||||
Root: root,
|
||||
Runtime: "go",
|
||||
Deploy: fn.DeploySpec{
|
||||
Namespace: "deployed",
|
||||
},
|
||||
}
|
||||
if _, err := client.Init(f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cmd = NewDescribeCmd(func(cc ClientConfig, _ ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != "deployed" {
|
||||
t.Fatalf("expected 'deployed', got '%v'", cc.Namespace)
|
||||
}
|
||||
return client, func() {}
|
||||
})
|
||||
cmd.SetArgs([]string{})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure an explicit namespace is plumbed through
|
||||
cmd = NewDescribeCmd(func(cc ClientConfig, _ ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != "ns" {
|
||||
t.Fatalf("expected 'ns', got '%v'", cc.Namespace)
|
||||
}
|
||||
return client, func() {}
|
||||
})
|
||||
cmd.SetArgs([]string{"--namespace", "ns"})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -15,6 +16,7 @@ import (
|
|||
"knative.dev/func/pkg/config"
|
||||
"knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/k8s"
|
||||
"knative.dev/func/pkg/pipelines/tekton"
|
||||
)
|
||||
|
||||
var format string = "json"
|
||||
|
@ -28,7 +30,7 @@ NAME
|
|||
{{rootCmdUse}} environment - display function execution environment information
|
||||
|
||||
SYNOPSIS
|
||||
{{rootCmdUse}} environment [-e|--env-format] [-v|--verbose]
|
||||
{{rootCmdUse}} environment [-f|--format] [-v|--verbose] [-p|--path]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -36,8 +38,7 @@ DESCRIPTION
|
|||
the version of func, the version of the function spec, the default builder,
|
||||
available runtimes, and available templates.
|
||||
`,
|
||||
SuggestFor: []string{"env", "environemtn", "enviroment", "enviornment", "enviroment"},
|
||||
PreRunE: bindEnv("verbose", "format"),
|
||||
PreRunE: bindEnv("verbose", "format", "path"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runEnvironment(cmd, newClient, version)
|
||||
},
|
||||
|
@ -48,6 +49,7 @@ DESCRIPTION
|
|||
}
|
||||
|
||||
cmd.Flags().StringP("format", "f", format, "Format of output environment information, 'json' or 'yaml'. ($FUNC_FORMAT)")
|
||||
addPathFlag(cmd)
|
||||
addVerboseFlag(cmd, cfg.Verbose)
|
||||
|
||||
return cmd
|
||||
|
@ -59,12 +61,18 @@ type Environment struct {
|
|||
SpecVersion string
|
||||
SocatImage string
|
||||
TarImage string
|
||||
FuncUtilsImage string
|
||||
DeployerImage string
|
||||
ScaffoldImage string
|
||||
S2IImage string
|
||||
Languages []string
|
||||
DefaultImageBuilders map[string]map[string]string
|
||||
Templates map[string][]string
|
||||
Environment []string
|
||||
Cluster string
|
||||
Defaults config.Global
|
||||
Function *functions.Function `json:",omitempty" yaml:",omitempty"`
|
||||
Instance *functions.Instance `json:",omitempty" yaml:",omitempty"`
|
||||
}
|
||||
|
||||
func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (err error) {
|
||||
|
@ -125,6 +133,10 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er
|
|||
SpecVersion: functions.LastSpecVersion(),
|
||||
SocatImage: k8s.SocatImage,
|
||||
TarImage: k8s.TarImage,
|
||||
FuncUtilsImage: tekton.FuncUtilImage,
|
||||
DeployerImage: tekton.DeployerImage,
|
||||
ScaffoldImage: tekton.ScaffoldImage,
|
||||
S2IImage: tekton.S2IImage,
|
||||
Languages: r,
|
||||
DefaultImageBuilders: builderimagesdefault,
|
||||
Templates: t,
|
||||
|
@ -133,6 +145,14 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er
|
|||
Defaults: defaults,
|
||||
}
|
||||
|
||||
function, instance := describeFuncInformation(cmd.Context(), newClient, cfg)
|
||||
if function != nil {
|
||||
environment.Function = function
|
||||
}
|
||||
if instance != nil {
|
||||
environment.Instance = instance
|
||||
}
|
||||
|
||||
var s []byte
|
||||
switch cfg.Format {
|
||||
case "json":
|
||||
|
@ -170,16 +190,33 @@ func getTemplates(client *functions.Client, runtimes []string) (map[string][]str
|
|||
return templateMap, nil
|
||||
}
|
||||
|
||||
func describeFuncInformation(context context.Context, newClient ClientFactory, cfg environmentConfig) (*functions.Function, *functions.Instance) {
|
||||
function, err := functions.NewFunction(cfg.Path)
|
||||
if err != nil || !function.Initialized() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
instance, err := client.Describe(context, function.Name, function.Deploy.Namespace, function)
|
||||
if err != nil {
|
||||
return &function, nil
|
||||
}
|
||||
return &function, &instance
|
||||
}
|
||||
|
||||
type environmentConfig struct {
|
||||
Verbose bool
|
||||
Format string
|
||||
Path string
|
||||
}
|
||||
|
||||
func newEnvironmentConfig() (cfg environmentConfig, err error) {
|
||||
cfg = environmentConfig{
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
Format: viper.GetString("format"),
|
||||
Path: viper.GetString("path"),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func write(out io.Writer, s Formatter, formatName string) {
|
|||
case URL:
|
||||
err = s.URL(out)
|
||||
default:
|
||||
err = fmt.Errorf("format not recognized: %v\n", formatName)
|
||||
err = fmt.Errorf("format not recognized: %v", formatName)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
//go:build exclude_graphdriver_btrfs || !cgo
|
||||
// +build exclude_graphdriver_btrfs !cgo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/openshift/source-to-image/pkg/cmd/cli"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"knative.dev/func/pkg/builders/s2i"
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/k8s"
|
||||
"knative.dev/func/pkg/knative"
|
||||
"knative.dev/func/pkg/scaffolding"
|
||||
"knative.dev/func/pkg/tar"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-sigs
|
||||
cancel()
|
||||
<-sigs // second sigint/sigterm is treated as sigkill
|
||||
os.Exit(137)
|
||||
}()
|
||||
|
||||
var cmd = unknown
|
||||
|
||||
switch filepath.Base(os.Args[0]) {
|
||||
case "deploy":
|
||||
cmd = deploy
|
||||
case "scaffold":
|
||||
cmd = scaffold
|
||||
case "s2i":
|
||||
cmd = s2iCmd
|
||||
case "socat":
|
||||
cmd = socat
|
||||
case "sh":
|
||||
cmd = sh
|
||||
case "s2i-generate":
|
||||
cmd = s2iGenerate
|
||||
}
|
||||
|
||||
err := cmd(ctx)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func unknown(_ context.Context) error {
|
||||
return fmt.Errorf("unknown command: %q", os.Args[0])
|
||||
}
|
||||
|
||||
func socat(ctx context.Context) error {
|
||||
cmd := newSocatCmd()
|
||||
cmd.SetContext(ctx)
|
||||
return cmd.Execute()
|
||||
}
|
||||
|
||||
func scaffold(ctx context.Context) error {
|
||||
|
||||
if len(os.Args) != 2 {
|
||||
return fmt.Errorf("expected exactly one positional argument (function project path)")
|
||||
}
|
||||
|
||||
path := os.Args[1]
|
||||
|
||||
f, err := fn.NewFunction(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load func project: %w", err)
|
||||
}
|
||||
|
||||
if f.Runtime != "go" && f.Runtime != "python" {
|
||||
// Scaffolding is for now supported/needed only for Go.
|
||||
return nil
|
||||
}
|
||||
|
||||
embeddedRepo, err := fn.NewRepository("", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot initialize repository: %w", err)
|
||||
}
|
||||
|
||||
appRoot := filepath.Join(f.Root, ".s2i", "builds", "last")
|
||||
_ = os.RemoveAll(appRoot)
|
||||
|
||||
err = scaffolding.Write(appRoot, f.Root, f.Runtime, f.Invoke, embeddedRepo.FS())
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot write the scaffolding: %w", err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(f.Root, ".s2i", "bin"), 0755); err != nil {
|
||||
return fmt.Errorf("unable to create .s2i bin dir. %w", err)
|
||||
}
|
||||
|
||||
var asm string
|
||||
switch f.Runtime {
|
||||
case "go":
|
||||
asm = s2i.GoAssembler
|
||||
case "python":
|
||||
asm = s2i.PythonAssembler
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(f.Root, ".s2i", "bin", "assemble"), []byte(asm), 0755); err != nil {
|
||||
return fmt.Errorf("unable to write go assembler. %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func s2iCmd(ctx context.Context) error {
|
||||
klog.InitFlags(flag.CommandLine)
|
||||
cmd := cli.CommandFor()
|
||||
cmd.SetContext(ctx)
|
||||
return cmd.Execute()
|
||||
}
|
||||
|
||||
func deploy(ctx context.Context) error {
|
||||
var err error
|
||||
deployer := knative.NewDeployer(
|
||||
knative.WithDeployerVerbose(true),
|
||||
knative.WithDeployerDecorator(deployDecorator{}))
|
||||
|
||||
var root string
|
||||
if len(os.Args) > 1 {
|
||||
root = os.Args[1]
|
||||
} else {
|
||||
root, err = os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot determine working directory: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
f, err := fn.NewFunction(root)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load function: %w", err)
|
||||
}
|
||||
if len(os.Args) > 2 {
|
||||
f.Deploy.Image = os.Args[2]
|
||||
}
|
||||
if f.Deploy.Image == "" {
|
||||
f.Deploy.Image = f.Image
|
||||
}
|
||||
|
||||
res, err := deployer.Deploy(ctx, f)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannont deploy the function: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("function has been deployed\n%+v\n", res)
|
||||
return nil
|
||||
}
|
||||
|
||||
type deployDecorator struct {
|
||||
oshDec k8s.OpenshiftMetadataDecorator
|
||||
}
|
||||
|
||||
func (d deployDecorator) UpdateAnnotations(function fn.Function, annotations map[string]string) map[string]string {
|
||||
if k8s.IsOpenShift() {
|
||||
return d.oshDec.UpdateAnnotations(function, annotations)
|
||||
}
|
||||
return annotations
|
||||
}
|
||||
|
||||
func (d deployDecorator) UpdateLabels(function fn.Function, labels map[string]string) map[string]string {
|
||||
if k8s.IsOpenShift() {
|
||||
return d.oshDec.UpdateLabels(function, labels)
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
func sh(ctx context.Context) error {
|
||||
if !slices.Equal(os.Args[1:], []string{"-c", "umask 0000 && exec tar -xmf -"}) {
|
||||
return fmt.Errorf("this is a fake sh (only for backward compatiblility purposes)")
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get working directory: %w", err)
|
||||
}
|
||||
|
||||
unix.Umask(0)
|
||||
|
||||
return tar.Extract(os.Stdin, wd)
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
//go:build exclude_graphdriver_btrfs || !cgo
|
||||
// +build exclude_graphdriver_btrfs !cgo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/openshift/source-to-image/pkg/api"
|
||||
"github.com/openshift/source-to-image/pkg/build"
|
||||
"github.com/openshift/source-to-image/pkg/build/strategies"
|
||||
"github.com/openshift/source-to-image/pkg/scm/git"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
)
|
||||
|
||||
func s2iGenerate(ctx context.Context) error {
|
||||
cmd := newS2IGenerateCmd()
|
||||
err := cmd.ExecuteContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot s2i generate: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type genConfig struct {
|
||||
target string
|
||||
pathContext string
|
||||
builderImage string
|
||||
registry string
|
||||
imageScriptUrl string
|
||||
logLevel string
|
||||
envVars []string
|
||||
}
|
||||
|
||||
func newS2IGenerateCmd() *cobra.Command {
|
||||
var config genConfig
|
||||
|
||||
genCmd := &cobra.Command{
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
config.envVars = args
|
||||
return runS2IGenerate(cmd.Context(), config)
|
||||
},
|
||||
}
|
||||
genCmd.Flags().StringVar(&config.target, "target", "/gen-source", "")
|
||||
genCmd.Flags().StringVar(&config.pathContext, "path-context", ".", "")
|
||||
genCmd.Flags().StringVar(&config.builderImage, "builder-image", "", "")
|
||||
genCmd.Flags().StringVar(&config.registry, "registry", "", "")
|
||||
genCmd.Flags().StringVar(&config.imageScriptUrl, "image-script-url", "image:///usr/libexec/s2i", "")
|
||||
genCmd.Flags().StringVar(&config.logLevel, "log-level", "0", "")
|
||||
|
||||
return genCmd
|
||||
}
|
||||
|
||||
func runS2IGenerate(ctx context.Context, c genConfig) error {
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get working directory: %w", err)
|
||||
}
|
||||
|
||||
funcRoot := filepath.Join(wd, c.pathContext)
|
||||
|
||||
// replace registry in func.yaml
|
||||
f, err := fn.NewFunction(funcRoot)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load function: %w", err)
|
||||
}
|
||||
f.Registry = c.registry
|
||||
err = f.Write()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot write function: %w", err)
|
||||
}
|
||||
|
||||
// append node_modules into .s2iignore
|
||||
s2iIgnorePath := filepath.Join(funcRoot, ".s2iignore")
|
||||
if fi, _ := os.Stat(s2iIgnorePath); fi != nil {
|
||||
var file *os.File
|
||||
|
||||
file, err = os.OpenFile(s2iIgnorePath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot open s2i ignore file for append: %w", err)
|
||||
}
|
||||
defer func(file *os.File) {
|
||||
_ = file.Close()
|
||||
|
||||
}(file)
|
||||
|
||||
_, err = file.Write([]byte("\nnode_modules"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot append node_modules directory to s2i ignore file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// prepare envvars
|
||||
var envs = make([]api.EnvironmentSpec, 0, len(c.envVars))
|
||||
for _, e := range c.envVars {
|
||||
var es api.EnvironmentSpec
|
||||
part := strings.SplitN(e, "=", 2)
|
||||
switch len(part) {
|
||||
case 1:
|
||||
es.Name = part[0]
|
||||
case 2:
|
||||
es.Name = part[0]
|
||||
es.Value = part[1]
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if es.Name != "" {
|
||||
envs = append(envs, es)
|
||||
}
|
||||
}
|
||||
|
||||
s2iConfig := api.Config{
|
||||
Source: &git.URL{
|
||||
URL: url.URL{Path: funcRoot},
|
||||
Type: git.URLTypeLocal,
|
||||
},
|
||||
BuilderImage: c.builderImage,
|
||||
ImageScriptsURL: c.imageScriptUrl,
|
||||
KeepSymlinks: true,
|
||||
Environment: envs,
|
||||
AsDockerfile: filepath.Join(c.target, "Dockerfile.gen"),
|
||||
}
|
||||
|
||||
builder, _, err := strategies.Strategy(nil, &s2iConfig, build.Overrides{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create builder: %w", err)
|
||||
}
|
||||
|
||||
_, err = builder.Build(&s2iConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot build: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func newSocatCmd() *cobra.Command {
|
||||
var (
|
||||
uniDir bool
|
||||
dbg string
|
||||
)
|
||||
cmd := cobra.Command{
|
||||
Use: "socat [-u] <address> <address>",
|
||||
Short: "Minimalistic socat.",
|
||||
Long: `Minimalistic socat.
|
||||
Implements only TCP, OPEN and stdio ("-") addresses with no options.
|
||||
Only supported flag is -u.`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
stdio := rwc{
|
||||
ReadCloser: cmd.InOrStdin().(io.ReadCloser),
|
||||
WriteCloser: cmd.OutOrStdout().(io.WriteCloser),
|
||||
}
|
||||
left, err := createConnection(args[0], stdio)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer left.Close()
|
||||
right, err := createConnection(args[1], stdio)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer right.Close()
|
||||
return connect(left, right, uniDir)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&uniDir, "unidirect", "u", false, "unidirectional mode (left to right)")
|
||||
cmd.Flags().StringVarP(&dbg, "debug", "d", "", "log level (this flag is present only for compatibility and has no effect)")
|
||||
|
||||
return &cmd
|
||||
}
|
||||
|
||||
func createConnection(address string, stdio connection) (connection, error) {
|
||||
if address == "-" {
|
||||
return stdio, nil
|
||||
}
|
||||
parts := strings.SplitN(address, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("cannot parse address: %q", address)
|
||||
}
|
||||
typ := strings.ToLower(parts[0])
|
||||
parts = strings.Split(parts[1], ",")
|
||||
if len(parts) > 1 {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "ignored options: %q\n", parts[1])
|
||||
}
|
||||
addr := parts[0]
|
||||
switch typ {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
_, _ = fmt.Fprintln(os.Stderr, "opening connection")
|
||||
var laddr net.TCPAddr
|
||||
raddr, err := net.ResolveTCPAddr(typ, addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("name does not resolve: %w", err)
|
||||
}
|
||||
|
||||
conn, err := net.DialTCP(typ, &laddr, raddr)
|
||||
if err == nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "successfully connected to %v\n", raddr)
|
||||
}
|
||||
return conn, err
|
||||
case "open":
|
||||
return os.OpenFile(addr, os.O_RDWR, 0644)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported address: %q", address)
|
||||
}
|
||||
}
|
||||
|
||||
func connect(left, right connection, uniDir bool) error {
|
||||
g := errgroup.Group{}
|
||||
g.SetLimit(2)
|
||||
|
||||
if !uniDir {
|
||||
g.Go(func() error {
|
||||
_, err := io.Copy(left, right)
|
||||
tryCloseWriteSide(left)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
g.Go(func() error {
|
||||
_, err := io.Copy(right, left)
|
||||
tryCloseWriteSide(right)
|
||||
return err
|
||||
})
|
||||
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
type connection interface {
|
||||
io.Reader
|
||||
io.Writer
|
||||
io.Closer
|
||||
}
|
||||
|
||||
type writeCloser interface {
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
type rwc struct {
|
||||
io.ReadCloser
|
||||
io.WriteCloser
|
||||
}
|
||||
|
||||
func (r rwc) Close() error {
|
||||
err := r.WriteCloser.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.ReadCloser.Close()
|
||||
}
|
||||
|
||||
func (r rwc) CloseWrite() error {
|
||||
return r.WriteCloser.Close()
|
||||
}
|
||||
|
||||
func tryCloseWriteSide(c connection) {
|
||||
if wc, ok := c.(writeCloser); ok {
|
||||
err := wc.CloseWrite()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "waring: cannot close write side: %+v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRootCmd(t *testing.T) {
|
||||
|
||||
/* Begin prepare TCP server and the files */
|
||||
addr := startTCPEcho(t)
|
||||
|
||||
const testData = "file-content\n"
|
||||
tmpDir := t.TempDir()
|
||||
inputFile := filepath.Join(tmpDir, "a.txt")
|
||||
err := os.WriteFile(inputFile, []byte(testData), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputFile := filepath.Join(tmpDir, "b.txt")
|
||||
err = os.WriteFile(outputFile, []byte{}, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
/* End prepare TCP server and the files */
|
||||
|
||||
type matcher = func(string) bool
|
||||
contains := func(pattern string) func(string) bool {
|
||||
return func(s string) bool { return strings.Contains(s, pattern) }
|
||||
}
|
||||
equalsTo := func(pattern string) func(string) bool {
|
||||
return func(s string) bool { return s == pattern }
|
||||
}
|
||||
|
||||
type args struct {
|
||||
args []string
|
||||
inputString string
|
||||
outMatcher matcher
|
||||
errOutMatcher matcher
|
||||
outFileMatcher matcher
|
||||
wantErr bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "stdio<->tcp",
|
||||
args: args{
|
||||
args: []string{"-", "TCP:" + addr},
|
||||
inputString: testData,
|
||||
outMatcher: equalsTo(testData),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tcp<->stdio",
|
||||
args: args{
|
||||
args: []string{"TCP:" + addr, "-"},
|
||||
inputString: testData,
|
||||
outMatcher: equalsTo(testData),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tcp-no-such-host",
|
||||
args: args{
|
||||
args: []string{"-", "TCP:does.not.exist:10000"},
|
||||
inputString: "tcp-echo",
|
||||
errOutMatcher: contains("not resolve"),
|
||||
wantErr: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "file->stdio",
|
||||
args: args{
|
||||
args: []string{"-u", "OPEN:" + inputFile, "-"},
|
||||
inputString: "",
|
||||
outMatcher: equalsTo(testData),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "stdio->file",
|
||||
args: args{
|
||||
args: []string{"-u", "-", "OPEN:" + outputFile},
|
||||
inputString: testData,
|
||||
outFileMatcher: equalsTo(testData),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
|
||||
stdout := &testWriter{Writer: &out}
|
||||
stderr := &testWriter{Writer: &errOut}
|
||||
cmd := newSocatCmd()
|
||||
cmd.SetIn(io.NopCloser(strings.NewReader(tt.args.inputString)))
|
||||
cmd.SetOut(stdout)
|
||||
cmd.SetErr(stderr)
|
||||
cmd.SetArgs(tt.args.args)
|
||||
|
||||
err = cmd.Execute()
|
||||
if err != nil && !tt.args.wantErr {
|
||||
t.Error(err)
|
||||
t.Logf("errOut: %q", errOut.String())
|
||||
}
|
||||
|
||||
if err == nil && tt.args.wantErr {
|
||||
t.Error("expected error but got nil")
|
||||
}
|
||||
|
||||
if tt.args.outMatcher != nil && !tt.args.outMatcher(out.String()) {
|
||||
t.Error("bad standard output")
|
||||
}
|
||||
if tt.args.errOutMatcher != nil && !tt.args.errOutMatcher(errOut.String()) {
|
||||
t.Error("bad standard error output")
|
||||
}
|
||||
if tt.args.outFileMatcher != nil {
|
||||
bs, e := os.ReadFile(outputFile)
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
if !tt.args.outFileMatcher(string(bs)) {
|
||||
t.Error("bad content of the output file")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type testWriter struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (n *testWriter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func startTCPEcho(t *testing.T) (addr string) {
|
||||
l, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
addr = l.Addr().String()
|
||||
go func() {
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
if errors.Is(err, net.ErrClosed) {
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
go func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
_, err = io.Copy(conn, conn)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}(conn)
|
||||
}
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
l.Close()
|
||||
})
|
||||
return addr
|
||||
}
|
||||
|
||||
func TestNewRootCmdWithPipe(t *testing.T) {
|
||||
addr := startTCPEcho(t)
|
||||
|
||||
r, stdOut, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stdIn, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var data = []byte("testing data")
|
||||
|
||||
go func() {
|
||||
var err error
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
var err error
|
||||
var errBuff bytes.Buffer
|
||||
cmd := newSocatCmd()
|
||||
cmd.SetIn(stdIn)
|
||||
cmd.SetOut(stdOut)
|
||||
cmd.SetErr(&errBuff)
|
||||
cmd.SetArgs([]string{"-dd", "-", "TCP:" + addr})
|
||||
|
||||
err = cmd.Execute()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
bs, e := io.ReadAll(r)
|
||||
if e != nil {
|
||||
t.Error(e)
|
||||
}
|
||||
t.Log(string(data))
|
||||
if !bytes.Equal(data, bs) {
|
||||
t.Errorf("bad data: %q", string(bs))
|
||||
}
|
||||
}
|
|
@ -1,73 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
"knative.dev/func/cmd"
|
||||
"knative.dev/func/pkg/docker"
|
||||
)
|
||||
|
||||
// Statically-populated build metadata set by `make build`.
|
||||
var vers, kver, hash string
|
||||
import "knative.dev/func/pkg/app"
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-sigs
|
||||
cancel()
|
||||
<-sigs // second sigint/sigterm is treated as sigkill
|
||||
os.Exit(137)
|
||||
}()
|
||||
|
||||
cfg := cmd.RootCommandConfig{
|
||||
Name: "func",
|
||||
Version: cmd.Version{
|
||||
Vers: vers,
|
||||
Kver: kver,
|
||||
Hash: hash,
|
||||
}}
|
||||
|
||||
if err := cmd.NewRootCmd(cfg).ExecuteContext(ctx); err != nil {
|
||||
if !errors.Is(err, terminal.InterruptErr) {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
}
|
||||
if ctx.Err() != nil || errors.Is(err, terminal.InterruptErr) {
|
||||
os.Exit(130)
|
||||
}
|
||||
|
||||
if errors.Is(err, docker.ErrNoDocker) {
|
||||
if !dockerOrPodmanInstalled() {
|
||||
fmt.Fprintln(os.Stderr, `Docker/Podman not installed.
|
||||
Please consider installing one of these:
|
||||
https://podman-desktop.io/
|
||||
https://www.docker.com/products/docker-desktop/`)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, `Possible causes:
|
||||
The docker/podman daemon is not running.
|
||||
The DOCKER_HOST environment variable is not set.`)
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func dockerOrPodmanInstalled() bool {
|
||||
_, err := exec.LookPath("podman")
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
_, err = exec.LookPath("docker")
|
||||
return err == nil
|
||||
app.Main()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -100,9 +99,14 @@ EXAMPLES
|
|||
o Allow insecure server connections when using SSL
|
||||
$ {{rootCmdUse}} invoke --insecure
|
||||
|
||||
o In case you need to specifically send GET request
|
||||
$ {{rootCmdUse}} invoke --request-type=GET
|
||||
`,
|
||||
SuggestFor: []string{"emit", "emti", "send", "emit", "exec", "nivoke", "onvoke", "unvoke", "knvoke", "imvoke", "ihvoke", "ibvoke"},
|
||||
PreRunE: bindEnv("path", "format", "target", "id", "source", "type", "data", "content-type", "file", "insecure", "confirm", "verbose"),
|
||||
SuggestFor: []string{"emit", "emti", "send", "emit", "exec", "nivoke",
|
||||
"onvoke", "unvoke", "knvoke", "imvoke", "ihvoke", "ibvoke"},
|
||||
PreRunE: bindEnv("path", "format", "target", "id", "source", "type",
|
||||
"data", "content-type", "request-type", "file", "insecure",
|
||||
"confirm", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runInvoke(cmd, args, newClient)
|
||||
},
|
||||
|
@ -121,6 +125,7 @@ EXAMPLES
|
|||
cmd.Flags().StringP("source", "", fn.DefaultInvokeSource, "Source value for the request data. ($FUNC_SOURCE)")
|
||||
cmd.Flags().StringP("type", "", fn.DefaultInvokeType, "Type value for the request data. ($FUNC_TYPE)")
|
||||
cmd.Flags().StringP("content-type", "", fn.DefaultInvokeContentType, "Content Type of the data. ($FUNC_CONTENT_TYPE)")
|
||||
cmd.Flags().StringP("request-type", "", fn.DefaultInvokeRequestType, "Type of request to use. Can be POST or GET. ($FUNC_REQUEST_TYPE)")
|
||||
cmd.Flags().StringP("data", "", fn.DefaultInvokeData, "Data to send in the request. ($FUNC_DATA)")
|
||||
cmd.Flags().StringP("file", "", "", "Path to a file to use as data. Overrides --data flag and should be sent with a correct --content-type. ($FUNC_FILE)")
|
||||
cmd.Flags().BoolP("insecure", "i", false, "Allow insecure server connections when using SSL. ($FUNC_INSECURE)")
|
||||
|
@ -132,9 +137,9 @@ EXAMPLES
|
|||
}
|
||||
|
||||
// Run
|
||||
func runInvoke(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
func runInvoke(cmd *cobra.Command, _ []string, newClient ClientFactory) (err error) {
|
||||
// Gather flag values for the invocation
|
||||
cfg, err := newInvokeConfig(newClient)
|
||||
cfg, err := newInvokeConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -153,7 +158,7 @@ func runInvoke(cmd *cobra.Command, args []string, newClient ClientFactory) (err
|
|||
}
|
||||
|
||||
// Client instance from env vars, flags, args and user prompts (if --confirm)
|
||||
client, done := newClient(ClientConfig{Namespace: f.Deploy.Namespace, Verbose: cfg.Verbose, InsecureSkipVerify: cfg.Insecure})
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose, InsecureSkipVerify: cfg.Insecure})
|
||||
defer done()
|
||||
|
||||
// Message to send the running function built from parameters gathered
|
||||
|
@ -163,6 +168,7 @@ func runInvoke(cmd *cobra.Command, args []string, newClient ClientFactory) (err
|
|||
Source: cfg.Source,
|
||||
Type: cfg.Type,
|
||||
ContentType: cfg.ContentType,
|
||||
RequestType: strings.ToUpper(cfg.RequestType),
|
||||
Data: cfg.Data,
|
||||
Format: cfg.Format,
|
||||
}
|
||||
|
@ -173,7 +179,7 @@ func runInvoke(cmd *cobra.Command, args []string, newClient ClientFactory) (err
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Data = base64.StdEncoding.EncodeToString(content)
|
||||
m.Data = content
|
||||
}
|
||||
|
||||
// Invoke
|
||||
|
@ -218,15 +224,16 @@ type invokeConfig struct {
|
|||
ID string
|
||||
Source string
|
||||
Type string
|
||||
Data string
|
||||
Data []byte
|
||||
ContentType string
|
||||
RequestType string
|
||||
File string
|
||||
Confirm bool
|
||||
Verbose bool
|
||||
Insecure bool
|
||||
}
|
||||
|
||||
func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
|
||||
func newInvokeConfig() (cfg invokeConfig, err error) {
|
||||
cfg = invokeConfig{
|
||||
Path: viper.GetString("path"),
|
||||
Target: viper.GetString("target"),
|
||||
|
@ -234,8 +241,9 @@ func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
|
|||
ID: viper.GetString("id"),
|
||||
Source: viper.GetString("source"),
|
||||
Type: viper.GetString("type"),
|
||||
Data: viper.GetString("data"),
|
||||
Data: []byte(viper.GetString("data")),
|
||||
ContentType: viper.GetString("content-type"),
|
||||
RequestType: viper.GetString("request-type"),
|
||||
File: viper.GetString("file"),
|
||||
Confirm: viper.GetBool("confirm"),
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
|
@ -248,7 +256,7 @@ func newInvokeConfig(newClient ClientFactory) (cfg invokeConfig, err error) {
|
|||
if err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
cfg.Data = string(b)
|
||||
cfg.Data = b
|
||||
}
|
||||
|
||||
// if not in confirm/prompting mode, the cfg structure is complete.
|
||||
|
@ -369,7 +377,7 @@ func (c invokeConfig) prompt() (invokeConfig, error) {
|
|||
Name: "Data",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Data Content",
|
||||
Default: c.Data,
|
||||
Default: string(c.Data),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -390,7 +398,8 @@ func (c invokeConfig) prompt() (invokeConfig, error) {
|
|||
Message: contentTypeMessage,
|
||||
Default: c.ContentType,
|
||||
},
|
||||
}}
|
||||
},
|
||||
}
|
||||
if err := survey.Ask(qs, &c); err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
@ -402,7 +411,8 @@ func (c invokeConfig) prompt() (invokeConfig, error) {
|
|||
Message: "Allow insecure server connections when using SSL",
|
||||
Default: c.Insecure,
|
||||
},
|
||||
}}
|
||||
},
|
||||
}
|
||||
if err := survey.Ask(qs, &c); err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
|
|
@ -13,11 +13,12 @@ import (
|
|||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/mock"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestInvoke command executes the invocation path.
|
||||
func TestInvoke(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
var invoked int32
|
||||
|
||||
|
@ -29,7 +30,7 @@ func TestInvoke(t *testing.T) {
|
|||
// Mock Runner
|
||||
// Starts a service which sets invoked=1 on any request
|
||||
runner := mock.NewRunner()
|
||||
runner.RunFn = func(ctx context.Context, f fn.Function, _ time.Duration) (job *fn.Job, err error) {
|
||||
runner.RunFn = func(ctx context.Context, f fn.Function, _ string, _ time.Duration) (job *fn.Job, err error) {
|
||||
var (
|
||||
l net.Listener
|
||||
h = http.NewServeMux()
|
||||
|
@ -77,31 +78,3 @@ func TestInvoke(t *testing.T) {
|
|||
t.Fatal("function was not invoked")
|
||||
}
|
||||
}
|
||||
|
||||
// TestInvoke_Namespace ensures that invocation uses the Function's namespace
|
||||
// despite the currently active.
|
||||
func TestInvoke_Namespace(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
|
||||
// Create a Function in a non-active namespace
|
||||
f := fn.Function{Runtime: "go", Root: root, Deploy: fn.DeploySpec{Namespace: "ns"}}
|
||||
_, err := fn.New().Init(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// The shared Client constructor should receive the current function's
|
||||
// namespace when constructing its describer (used when finding the
|
||||
// function's route), not the currently active namespace.
|
||||
namespace := ""
|
||||
newClient := func(conf ClientConfig, opts ...fn.Option) (*fn.Client, func()) {
|
||||
namespace = conf.Namespace // should be set to that of the function
|
||||
return NewClient(conf, opts...)
|
||||
}
|
||||
cmd := NewInvokeCmd(newClient)
|
||||
_ = cmd.Execute() // invocation error expected
|
||||
|
||||
if namespace != "ns" {
|
||||
t.Fatalf("expected client to receive function's current namespace 'ns', got '%v'", namespace)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ EXAMPLES
|
|||
"panguages", "manguages", "kanguages", "lsnguages", "lznguages"},
|
||||
PreRunE: bindEnv("json", "repository", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runLanguages(cmd, args, newClient)
|
||||
return runLanguages(cmd, newClient)
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@ EXAMPLES
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runLanguages(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg, err := newLanguagesConfig(newClient)
|
||||
func runLanguages(cmd *cobra.Command, newClient ClientFactory) (err error) {
|
||||
cfg, err := newLanguagesConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ type languagesConfig struct {
|
|||
JSON bool // output as JSON
|
||||
}
|
||||
|
||||
func newLanguagesConfig(newClient ClientFactory) (cfg languagesConfig, err error) {
|
||||
func newLanguagesConfig() (cfg languagesConfig, err error) {
|
||||
cfg = languagesConfig{
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
Repository: viper.GetString("repository"),
|
||||
|
|
|
@ -2,13 +2,15 @@ package cmd
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestLanguages_Default ensures that the default behavior of listing
|
||||
// all supported languages is to print a plain text list of all the builtin
|
||||
// language runtimes.
|
||||
func TestLanguages_Default(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
buf := piped(t) // gather output
|
||||
cmd := NewLanguagesCmd(NewClient)
|
||||
|
@ -33,7 +35,7 @@ typescript`
|
|||
// TestLanguages_JSON ensures that listing languages in --json format returns
|
||||
// builtin languages as a JSON array.
|
||||
func TestLanguages_JSON(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
buf := piped(t) // gather output
|
||||
cmd := NewLanguagesCmd(NewClient)
|
||||
|
|
55
cmd/list.go
55
cmd/list.go
|
@ -23,7 +23,7 @@ func NewListCmd(newClient ClientFactory) *cobra.Command {
|
|||
Short: "List deployed functions",
|
||||
Long: `List deployed functions
|
||||
|
||||
Lists all deployed functions in a given namespace.
|
||||
Lists deployed functions.
|
||||
`,
|
||||
Example: `
|
||||
# List all functions in the current namespace with human readable output
|
||||
|
@ -50,17 +50,25 @@ Lists all deployed functions in a given namespace.
|
|||
|
||||
// Namespace Config
|
||||
// Differing from other commands, the default namespace for the list
|
||||
// command is always the currently active namespace as returned by
|
||||
// config.DefaultNamespace(). The -A flag clears this value indicating
|
||||
// the lister implementation should not filter by namespace and instead
|
||||
// list from all namespaces. This logic is sligtly inverse to the other
|
||||
// namespace-sensitive commands which default to the currently active
|
||||
// function if available, and delegate to the implementation to use
|
||||
// the config default otherwise.
|
||||
// command is set to the currently active namespace as returned by
|
||||
// calling k8s.DefaultNamespace(). This way a call to `func list` will
|
||||
// show functions in the currently active namespace. If the value can
|
||||
// not be determined due to error, a warning is printed to log and
|
||||
// no namespace is passed to the lister, which should result in the
|
||||
// lister showing functions for all namespaces.
|
||||
//
|
||||
// This also extends to the treatment of the global setting for
|
||||
// namespace. This is likewise intended for command which require a
|
||||
// namespace no matter what. Therefore the global namespace setting is
|
||||
// not applicable to this command because "default" really means "all".
|
||||
//
|
||||
// This is slightly different than other commands wherein their
|
||||
// default is often to presume namespace "default" if none was either
|
||||
// supplied nor available.
|
||||
|
||||
// Flags
|
||||
cmd.Flags().BoolP("all-namespaces", "A", false, "List functions in all namespaces. If set, the --namespace flag is ignored.")
|
||||
cmd.Flags().StringP("namespace", "n", config.DefaultNamespace(), "The namespace for which to list functions. ($FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("namespace", "n", defaultNamespace(fn.Function{}, false), "The namespace for which to list functions. ($FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("output", "o", "human", "Output format (human|plain|json|xml|yaml) ($FUNC_OUTPUT)")
|
||||
addVerboseFlag(cmd, cfg.Verbose)
|
||||
|
||||
|
@ -72,16 +80,15 @@ Lists all deployed functions in a given namespace.
|
|||
}
|
||||
|
||||
func runList(cmd *cobra.Command, _ []string, newClient ClientFactory) (err error) {
|
||||
cfg := newListConfig()
|
||||
|
||||
if err := cfg.Validate(cmd); err != nil {
|
||||
cfg, err := newListConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
|
||||
client, done := newClient(ClientConfig{Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
items, err := client.List(cmd.Context())
|
||||
items, err := client.List(cmd.Context(), cfg.Namespace)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -109,26 +116,24 @@ type listConfig struct {
|
|||
Verbose bool
|
||||
}
|
||||
|
||||
func newListConfig() listConfig {
|
||||
c := listConfig{
|
||||
func newListConfig(cmd *cobra.Command) (cfg listConfig, err error) {
|
||||
cfg = listConfig{
|
||||
Namespace: viper.GetString("namespace"),
|
||||
Output: viper.GetString("output"),
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
}
|
||||
// Lister instantiated by newClient explicitly expects "" namespace to
|
||||
// inidicate it should list from all namespaces, so remove default "default"
|
||||
// when -A.
|
||||
// If --all-namespaces, zero out any value for namespace (such as)
|
||||
// "all" to the lister.
|
||||
if viper.GetBool("all-namespaces") {
|
||||
c.Namespace = ""
|
||||
cfg.Namespace = ""
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c listConfig) Validate(cmd *cobra.Command) error {
|
||||
// specifying both -A and --namespace is logically inconsistent
|
||||
if cmd.Flags().Changed("namespace") && viper.GetBool("all-namespaces") {
|
||||
return errors.New("Both --namespace and --all-namespaces specified.")
|
||||
err = errors.New("both --namespace and --all-namespaces specified")
|
||||
}
|
||||
return nil
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Output Formatting (serializers)
|
||||
|
|
|
@ -1,37 +1,53 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/mock"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestList_Namespace ensures that list command options for specifying a
|
||||
// namespace (--namespace) or all namespaces (--all-namespaces) are properly
|
||||
// evaluated.
|
||||
// TestList_Namespace ensures that list command handles namespace options
|
||||
// namespace (--namespace) and all namespaces (--all-namespaces) correctly
|
||||
// and that the current kube context is used by default.
|
||||
func TestList_Namespace(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
all bool // --all-namespaces
|
||||
namespace string // use specific namespace
|
||||
expected string // expected
|
||||
namespace string // --namespace flag (use specific namespace)
|
||||
all bool // --all-namespaces (no namespace filter)
|
||||
allShort bool // -A (no namespace filter)
|
||||
expected string // expected value passed to lister
|
||||
err bool // expected error
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
expected: "func", // see ./testdata/default_kubeconfig
|
||||
name: "default (none specififed)",
|
||||
namespace: "",
|
||||
all: false,
|
||||
allShort: false,
|
||||
expected: "func", // see testdata kubeconfig
|
||||
},
|
||||
{
|
||||
name: "namespace provided",
|
||||
namespace: "ns",
|
||||
all: false,
|
||||
allShort: false,
|
||||
expected: "ns",
|
||||
},
|
||||
{
|
||||
name: "all namespaces",
|
||||
all: true,
|
||||
name: "all namespaces",
|
||||
namespace: "",
|
||||
all: true,
|
||||
allShort: false,
|
||||
expected: "", // --all-namespaces | -A explicitly mean none specified
|
||||
},
|
||||
{
|
||||
name: "all namespaces - short flag",
|
||||
all: false,
|
||||
allShort: true,
|
||||
expected: "", // blank is implemented by lister as meaning all
|
||||
},
|
||||
{
|
||||
|
@ -43,33 +59,51 @@ func TestList_Namespace(t *testing.T) {
|
|||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var (
|
||||
lister = mock.NewLister()
|
||||
client = fn.New(fn.WithLister(lister))
|
||||
)
|
||||
cmd := NewListCmd(func(cc ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != test.expected {
|
||||
t.Fatalf("expected '%v', got '%v'", test.expected, cc.Namespace)
|
||||
// create a mock lister implementation which validates the expected
|
||||
// value has been passed.
|
||||
lister := mock.NewLister()
|
||||
lister.ListFn = func(_ context.Context, namespace string) ([]fn.ListItem, error) {
|
||||
if namespace != test.expected {
|
||||
t.Fatalf("expected list namespace %q, got %q", test.expected, namespace)
|
||||
}
|
||||
return client, func() {}
|
||||
})
|
||||
return []fn.ListItem{}, nil
|
||||
}
|
||||
|
||||
// Create an instance of the command which sets the flags
|
||||
// according to the test case
|
||||
cmd := NewListCmd(NewTestClient(fn.WithLister(lister)))
|
||||
args := []string{}
|
||||
if test.namespace != "" {
|
||||
args = append(args, "--namespace", test.namespace)
|
||||
}
|
||||
if test.all {
|
||||
args = append(args, "--all-namespaces")
|
||||
}
|
||||
if test.allShort {
|
||||
args = append(args, "-A")
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
|
||||
// Execute
|
||||
err := cmd.Execute()
|
||||
if err != nil && !test.err {
|
||||
// TODO: typed error for --namespace with -A. Perhaps ErrFlagConflict?
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err == nil && test.err {
|
||||
|
||||
// Check for expected error
|
||||
if err != nil {
|
||||
if !test.err {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
// expected error received
|
||||
return
|
||||
} else if test.err {
|
||||
t.Fatalf("did not receive expected error ")
|
||||
}
|
||||
|
||||
// For tests which did not expect an error, ensure the lister
|
||||
// was invoked
|
||||
if !lister.ListInvoked {
|
||||
t.Fatalf("%v: the lister was not invoked", test.name)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"knative.dev/func/pkg/mcp"
|
||||
)
|
||||
|
||||
func NewMCPServerCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "mcp",
|
||||
Short: "Start MCP server",
|
||||
Long: `
|
||||
NAME
|
||||
{{rootCmdUse}} mcp - start a Model Context Protocol (MCP) server
|
||||
|
||||
SYNOPSIS
|
||||
{{rootCmdUse}} mcp [flags]
|
||||
|
||||
DESCRIPTION
|
||||
Starts a Model Context Protocol (MCP) server over standard input/output (stdio) transport.
|
||||
This implementation aims to support tools for deploying and creating serverless functions.
|
||||
|
||||
Note: This command is still under development.
|
||||
|
||||
EXAMPLES
|
||||
|
||||
o Run an MCP server:
|
||||
{{rootCmdUse}} mcp
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runMCPServer(cmd, args)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runMCPServer(cmd *cobra.Command, args []string) error {
|
||||
s := mcp.NewServer()
|
||||
if err := s.Start(); err != nil {
|
||||
log.Fatalf("Server error: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -15,16 +15,15 @@ import (
|
|||
"knative.dev/func/pkg/docker/creds"
|
||||
)
|
||||
|
||||
func NewPromptForCredentials(in io.Reader, out, errOut io.Writer) func(registry string) (docker.Credentials, error) {
|
||||
func NewPromptForCredentials(in io.Reader, out, errOut io.Writer) func(repository string) (docker.Credentials, error) {
|
||||
firstTime := true
|
||||
return func(registry string) (docker.Credentials, error) {
|
||||
return func(repository string) (docker.Credentials, error) {
|
||||
var result docker.Credentials
|
||||
|
||||
if firstTime {
|
||||
firstTime = false
|
||||
fmt.Fprintf(out, "Please provide credentials for image registry (%s).\n", registry)
|
||||
fmt.Fprintf(out, "Please provide credentials for image repository '%s'.\n", repository)
|
||||
} else {
|
||||
fmt.Fprintln(out, "Incorrect credentials, please try again.")
|
||||
fmt.Fprintf(out, "Incorrect credentials for repository '%s'. Please make sure the repository is correct and try again.\n", repository)
|
||||
}
|
||||
|
||||
var qs = []*survey.Question{
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Netflix/go-expect"
|
||||
"github.com/creack/pty"
|
||||
"github.com/hinshun/vt10x"
|
||||
|
||||
"knative.dev/func/pkg/docker"
|
||||
|
@ -24,11 +26,16 @@ func Test_NewPromptForCredentials(t *testing.T) {
|
|||
Password: "testpwd",
|
||||
}
|
||||
|
||||
console, _, err := vt10x.NewVT10XConsole()
|
||||
ptm, pts, err := pty.Open()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer console.Close()
|
||||
term := vt10x.New(vt10x.WithWriter(pts))
|
||||
console, err := expect.NewConsole(expect.WithStdin(ptm), expect.WithStdout(term), expect.WithCloser(ptm, pts))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { console.Close() })
|
||||
|
||||
go func() {
|
||||
_, _ = console.ExpectEOF()
|
||||
|
|
|
@ -108,7 +108,7 @@ EXAMPLES
|
|||
$ {{rootCmdUse}} repository -c
|
||||
|
||||
o Add a repository and create a new function using a template from it:
|
||||
$ {{rootCmdUse}} repository add functastic https://github.com/knative-sandbox/func-tastic
|
||||
$ {{rootCmdUse}} repository add functastic https://github.com/knative-extensions/func-tastic
|
||||
$ {{rootCmdUse}} repository list
|
||||
default
|
||||
functastic
|
||||
|
@ -116,7 +116,7 @@ EXAMPLES
|
|||
...
|
||||
|
||||
o Add a repository specifying the branch to use (metacontroller):
|
||||
$ {{rootCmdUse}} repository add metacontroller https://github.com/knative-sandbox/func-tastic#metacontroler
|
||||
$ {{rootCmdUse}} repository add metacontroller https://github.com/knative-extensions/func-tastic#metacontroler
|
||||
$ {{rootCmdUse}} repository list
|
||||
default
|
||||
metacontroller
|
||||
|
@ -126,7 +126,7 @@ EXAMPLES
|
|||
o List all repositories including the URL from which remotes were installed
|
||||
$ {{rootCmdUse}} repository list -v
|
||||
default
|
||||
metacontroller https://github.com/knative-sandbox/func-tastic#metacontroller
|
||||
metacontroller https://github.com/knative-extensions/func-tastic#metacontroller
|
||||
|
||||
o Rename an installed repository
|
||||
$ {{rootCmdUse}} repository list
|
||||
|
@ -174,7 +174,7 @@ func NewRepositoryListCmd(newClient ClientFactory) *cobra.Command {
|
|||
Aliases: []string{"ls"},
|
||||
PreRunE: bindEnv("confirm", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRepositoryList(cmd, args, newClient)
|
||||
return runRepositoryList(cmd, newClient)
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -258,7 +258,7 @@ func NewRepositoryRemoveCmd(newClient ClientFactory) *cobra.Command {
|
|||
// Run
|
||||
// (list by default or interactive with -c|--confirm)
|
||||
func runRepository(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg, err := newRepositoryConfig(args)
|
||||
cfg, err := newRepositoryConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ func runRepository(cmd *cobra.Command, args []string, newClient ClientFactory) (
|
|||
// Run the command indicated
|
||||
switch answer.Action {
|
||||
case "list":
|
||||
return runRepositoryList(cmd, args, newClient)
|
||||
return runRepositoryList(cmd, newClient)
|
||||
case "add":
|
||||
return runRepositoryAdd(cmd, args, newClient)
|
||||
case "rename":
|
||||
|
@ -297,8 +297,8 @@ func runRepository(cmd *cobra.Command, args []string, newClient ClientFactory) (
|
|||
}
|
||||
|
||||
// List
|
||||
func runRepositoryList(_ *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg, err := newRepositoryConfig(args)
|
||||
func runRepositoryList(_ *cobra.Command, newClient ClientFactory) (err error) {
|
||||
cfg, err := newRepositoryConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ func runRepositoryAdd(_ *cobra.Command, args []string, newClient ClientFactory)
|
|||
// but only requires them if not prompting. If prompting, those values
|
||||
// become the prompt defaults.
|
||||
|
||||
cfg, err := newRepositoryConfig(args)
|
||||
cfg, err := newRepositoryConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ func runRepositoryAdd(_ *cobra.Command, args []string, newClient ClientFactory)
|
|||
|
||||
// Rename
|
||||
func runRepositoryRename(_ *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg, err := newRepositoryConfig(args)
|
||||
cfg, err := newRepositoryConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ func runRepositoryRename(_ *cobra.Command, args []string, newClient ClientFactor
|
|||
|
||||
// Remove
|
||||
func runRepositoryRemove(_ *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
cfg, err := newRepositoryConfig(args)
|
||||
cfg, err := newRepositoryConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ func runRepositoryRemove(_ *cobra.Command, args []string, newClient ClientFactor
|
|||
}
|
||||
|
||||
if len(repositories) == 0 {
|
||||
return errors.New("No repositories installed. use 'add' to install")
|
||||
return errors.New("no repositories installed. use 'add' to install")
|
||||
}
|
||||
|
||||
// Confirm (interactive prompt mode)
|
||||
|
@ -608,7 +608,7 @@ type repositoryConfig struct {
|
|||
// newRepositoryConfig creates a configuration suitable for use instantiating the
|
||||
// fn Client. Note that parameters for the individual commands (add, remove etc)
|
||||
// are collected separately in their requisite run functions.
|
||||
func newRepositoryConfig(args []string) (cfg repositoryConfig, err error) {
|
||||
func newRepositoryConfig() (cfg repositoryConfig, err error) {
|
||||
// initial config is populated based on flags, which are themselves
|
||||
// first populated by static defaults, then environment variables,
|
||||
// finally command flags.
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
// set of repositories by name for builtin repositories, by explicitly
|
||||
// setting the repositories' path to a new path which includes no others.
|
||||
func TestRepository_List(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewRepositoryListCmd(NewClient)
|
||||
cmd.SetArgs([]string{}) // Do not use test command args
|
||||
|
@ -33,8 +33,8 @@ func TestRepository_List(t *testing.T) {
|
|||
// arguments, respects the repositories' path flag, and the expected name is echoed
|
||||
// upon subsequent 'list'.
|
||||
func TestRepository_Add(t *testing.T) {
|
||||
url := ServeRepo("repository.git#main", t)
|
||||
_ = fromTempDirectory(t)
|
||||
url := ServeRepo("repository.git", t) + "#main"
|
||||
_ = FromTempDirectory(t)
|
||||
t.Log(url)
|
||||
|
||||
var (
|
||||
|
@ -75,7 +75,7 @@ func TestRepository_Add(t *testing.T) {
|
|||
// reflected as having been renamed upon subsequent 'list'.
|
||||
func TestRepository_Rename(t *testing.T) {
|
||||
url := ServeRepo("repository.git", t)
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
var (
|
||||
add = NewRepositoryAddCmd(NewClient)
|
||||
|
@ -123,7 +123,7 @@ func TestRepository_Rename(t *testing.T) {
|
|||
// subsequent 'list'.
|
||||
func TestRepository_Remove(t *testing.T) {
|
||||
url := ServeRepo("repository.git", t)
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
var (
|
||||
add = NewRepositoryAddCmd(NewClient)
|
||||
|
|
111
cmd/root.go
111
cmd/root.go
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
"golang.org/x/term"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"knative.dev/client-pkg/pkg/util"
|
||||
"knative.dev/client/pkg/util"
|
||||
|
||||
"knative.dev/func/cmd/templates"
|
||||
"knative.dev/func/pkg/config"
|
||||
|
@ -21,6 +21,13 @@ import (
|
|||
"knative.dev/func/pkg/k8s"
|
||||
)
|
||||
|
||||
// DefaultVersion when building source directly (bypassing the Makefile)
|
||||
const DefaultVersion = "v0.0.0+source"
|
||||
|
||||
// DefaultNamespace is the global static default namespace, and is equivalent
|
||||
// to the Kubernetes default namespace.
|
||||
const DefaultNamespace = "default"
|
||||
|
||||
type RootCommandConfig struct {
|
||||
Name string // usually `func` or `kn func`
|
||||
Version
|
||||
|
@ -55,7 +62,13 @@ Learn more about Knative at: https://knative.dev`, cfg.Name),
|
|||
// a version prefixed by "FUNC_"
|
||||
viper.AutomaticEnv() // read in environment variables for FUNC_<flag>
|
||||
viper.SetEnvPrefix("func") // ensure that all have the prefix
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
|
||||
// check if permissions for FUNC HOME are sufficient; warn if otherwise
|
||||
cp := config.File()
|
||||
if _, err := os.ReadFile(cp); os.IsPermission(err) {
|
||||
fmt.Fprintf(os.Stderr, "Warning: Insufficient permissions to read config file at '%s' - continuing without it\n", cp)
|
||||
}
|
||||
// Client
|
||||
// Use the provided ClientFactory or default to NewClient
|
||||
newClient := cfg.NewClient
|
||||
|
@ -73,6 +86,7 @@ Learn more about Knative at: https://knative.dev`, cfg.Name),
|
|||
NewDeployCmd(newClient),
|
||||
NewDeleteCmd(newClient),
|
||||
NewListCmd(newClient),
|
||||
NewSubscribeCmd(),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -93,11 +107,18 @@ Learn more about Knative at: https://knative.dev`, cfg.Name),
|
|||
NewEnvironmentCmd(newClient, &cfg.Version),
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "MCP Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
NewMCPServerCmd(),
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "Other Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
NewCompletionCmd(),
|
||||
NewVersionCmd(cfg.Version),
|
||||
NewTektonClusterTasksCmd(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -146,6 +167,45 @@ func effectivePath() (path string) {
|
|||
return path
|
||||
}
|
||||
|
||||
// defaultNamespace to use when none is provided explicitly.
|
||||
// This requires a bit more logic than normal flag defaults, which rely
|
||||
// on the order of precedence Static Config -> Global Config -> Current Func ->
|
||||
// -> Environment Variables -> Flags. This default calculation adds the
|
||||
// step of using the active Kubernetes namespace after Static Config and before
|
||||
// the optional Global Config setting. The static default is "default"
|
||||
func defaultNamespace(f fn.Function, verbose bool) string {
|
||||
// Specifically-requested
|
||||
if f.Namespace != "" {
|
||||
return f.Namespace
|
||||
}
|
||||
|
||||
// Last deployed
|
||||
if f.Deploy.Namespace != "" {
|
||||
return f.Deploy.Namespace
|
||||
}
|
||||
|
||||
// Active K8S namespace
|
||||
namespace, err := k8s.GetDefaultNamespace()
|
||||
if err != nil {
|
||||
if verbose {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get current active kubernetes namespace. Defaults will be used. %v", err)
|
||||
}
|
||||
} else if namespace != "" {
|
||||
return namespace
|
||||
}
|
||||
|
||||
// Globally-defined default in ~/.config/func/config.yaml is next
|
||||
cfg, err := config.NewDefault()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading global config at '%v'. %v\n", config.File(), err)
|
||||
} else if cfg.Namespace != "" {
|
||||
return cfg.Namespace
|
||||
}
|
||||
|
||||
// Static Default is the standard Kubernetes default "default"
|
||||
return DefaultNamespace
|
||||
}
|
||||
|
||||
// interactiveTerminal returns whether or not the currently attached process
|
||||
// terminal is interactive. Used for determining whether or not to
|
||||
// interactively prompt the user to confirm default choices, etc.
|
||||
|
@ -166,6 +226,7 @@ func bindEnv(flags ...string) bindFunc {
|
|||
}
|
||||
viper.AutomaticEnv() // read in environment variables for FUNC_<flag>
|
||||
viper.SetEnvPrefix("func") // ensure that all have the prefix
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -210,46 +271,6 @@ func deriveNameAndAbsolutePathFromPath(path string) (string, string) {
|
|||
return pathParts[len(pathParts)-1], absPath
|
||||
}
|
||||
|
||||
// deriveImage returns the same image name which will be used.
|
||||
// I.e. if the explicit name is empty, derive one from the configured registry
|
||||
// (registry plus username) and the function's name.
|
||||
//
|
||||
// This is calculated preemptively here in the CLI (prior to invoking the
|
||||
// client), only in order to provide information to the user via the prompt.
|
||||
// The client will calculate this same value if the image override is not
|
||||
// provided.
|
||||
//
|
||||
// Derivation logic:
|
||||
// deriveImage attempts to arrive at a final, full image name:
|
||||
//
|
||||
// format: [registry]/[username]/[functionName]:[tag]
|
||||
// example: quay.io/myname/my.function.name:tag.
|
||||
//
|
||||
// Registry can optionally be omitted, in which case DefaultRegistry
|
||||
// will be prepended.
|
||||
//
|
||||
// If the image flag is provided, this value is used directly (the user supplied
|
||||
// --image or $FUNC_IMAGE). Otherwise, the function at 'path' is loaded, and
|
||||
// the Image name therein is used (i.e. it was previously calculated).
|
||||
// Finally, the default registry is used, which is prepended to the function
|
||||
// name, and appended with ':latest':
|
||||
func deriveImage(explicitImage, defaultRegistry, path string) string {
|
||||
if explicitImage != "" {
|
||||
return explicitImage // use the explicit value provided.
|
||||
}
|
||||
f, err := fn.NewFunction(path)
|
||||
if err != nil {
|
||||
return "" // unable to derive due to load error (uninitialized?)
|
||||
}
|
||||
if f.Image != "" {
|
||||
return f.Image // use value previously provided or derived.
|
||||
}
|
||||
// Use the func system's derivation logic.
|
||||
// Errors deriving result in an empty return
|
||||
derivedValue, _ := f.ImageName()
|
||||
return derivedValue
|
||||
}
|
||||
|
||||
func mergeEnvs(envs []fn.Env, envToUpdate *util.OrderedMap, envToRemove []string) ([]fn.Env, int, error) {
|
||||
updated := sets.NewString()
|
||||
|
||||
|
@ -288,7 +309,7 @@ func mergeEnvs(envs []fn.Env, envToUpdate *util.OrderedMap, envToRemove []string
|
|||
|
||||
errMsg := fn.ValidateEnvs(envs)
|
||||
if len(errMsg) > 0 {
|
||||
return []fn.Env{}, 0, fmt.Errorf(strings.Join(errMsg, "\n"))
|
||||
return []fn.Env{}, 0, fmt.Errorf("error(s) while validating envs: %s", strings.Join(errMsg, "\n"))
|
||||
}
|
||||
|
||||
return envs, counter, nil
|
||||
|
@ -336,6 +357,12 @@ type Version struct {
|
|||
|
||||
// Return the stringification of the Version struct.
|
||||
func (v Version) String() string {
|
||||
// Initialize the default value to the zero semver with a descriptive
|
||||
// metadta tag indicating this must have been built from source if
|
||||
// undefined:
|
||||
if v.Vers == "" {
|
||||
v.Vers = DefaultVersion
|
||||
}
|
||||
if v.Verbose {
|
||||
return v.StringVerbose()
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/ory/viper"
|
||||
"knative.dev/client-pkg/pkg/util"
|
||||
"knative.dev/client/pkg/util"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
|
@ -271,6 +271,61 @@ func TestRoot_effectivePath(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
// Test_defaultNamespace ensures that the order of precedence for
|
||||
// determining the effective namespace is followed.
|
||||
// to use for the next deployment.
|
||||
func Test_defaultNamespace(t *testing.T) {
|
||||
// Clear non-test envs and set the test KUBECONFIG to nonexistent, but
|
||||
// save the current working directory for setting kube context in some
|
||||
// test cases.
|
||||
cwd := Cwd()
|
||||
_ = FromTempDirectory(t) // clears non-test envs and enters a temp dir.
|
||||
t.Setenv("KUBECONFIG", filepath.Join(t.TempDir(), "nonexistent"))
|
||||
|
||||
// also clear the test KUBECONFIG env
|
||||
tests := []struct {
|
||||
name string
|
||||
context bool
|
||||
global bool
|
||||
expected string
|
||||
}{
|
||||
// TODO cases for function state f.Namespace and f.Deploy.Namespace
|
||||
{
|
||||
name: "static default",
|
||||
context: false, // no active kube context
|
||||
global: false, // no global
|
||||
expected: DefaultNamespace, // expect static default
|
||||
}, {
|
||||
name: "global config",
|
||||
context: false,
|
||||
global: true, // see the global defined in FUNC_HOME testdata
|
||||
expected: "globaldefault", // expect global to override static
|
||||
}, {
|
||||
name: "active context",
|
||||
context: true, // see the config in KUBECONFIG testdata
|
||||
global: true,
|
||||
expected: "mynamespace", // active context overrides global default
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
if test.global { // enable a global config setting
|
||||
t.Setenv("XDG_CONFIG_HOME", filepath.Join(cwd, "testdata", "Test_defaultNamespace"))
|
||||
}
|
||||
if test.context { // enable an active kube context
|
||||
t.Setenv("KUBECONFIG", filepath.Join(cwd, "testdata", "Test_defaultNamespace", "kubeconfig"))
|
||||
}
|
||||
|
||||
namespace := defaultNamespace(fn.Function{}, false)
|
||||
if namespace != test.expected {
|
||||
t.Fatalf("%v: expected namespace %q, got %q", test.name, test.expected, namespace)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
// -------
|
||||
|
||||
|
@ -309,28 +364,3 @@ func piped(t *testing.T) func() string {
|
|||
return strings.TrimSpace(b.String())
|
||||
}
|
||||
}
|
||||
|
||||
// fromTempDirectory is a test helper which endeavors to create
|
||||
// an environment clean of developer's settings for use during CLI testing.
|
||||
func fromTempDirectory(t *testing.T) string {
|
||||
t.Helper()
|
||||
ClearEnvs(t)
|
||||
|
||||
// We have to define KUBECONFIG, or the file at ~/.kube/config (if extant)
|
||||
// will be used (disrupting tests by using the current user's environment).
|
||||
// The test kubeconfig set below has the current namespace set to 'func'
|
||||
// NOTE: the below settings affect unit tests only, and we do explicitly
|
||||
// want all unit tests to start in an empty environment with tests "opting in"
|
||||
// to config, not opting out.
|
||||
t.Setenv("KUBECONFIG", filepath.Join(cwd(), "testdata", "default_kubeconfig"))
|
||||
|
||||
// By default unit tests presum no config exists unless provided in testdata.
|
||||
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
|
||||
|
||||
// creates and CDs to a temp directory
|
||||
d, done := Mktemp(t)
|
||||
|
||||
// Return to original directory and resets viper.
|
||||
t.Cleanup(func() { done(); viper.Reset() })
|
||||
return d
|
||||
}
|
||||
|
|
183
cmd/run.go
183
cmd/run.go
|
@ -2,11 +2,12 @@ package cmd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ory/viper"
|
||||
|
@ -15,6 +16,7 @@ import (
|
|||
"knative.dev/func/pkg/config"
|
||||
"knative.dev/func/pkg/docker"
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/oci"
|
||||
)
|
||||
|
||||
func NewRunCmd(newClient ClientFactory) *cobra.Command {
|
||||
|
@ -26,9 +28,9 @@ NAME
|
|||
{{rootCmdUse}} run - Run a function locally
|
||||
|
||||
SYNOPSIS
|
||||
{{rootCmdUse}} run [-t|--container] [-r|--registry] [-i|--image] [-e|--env]
|
||||
[--build] [-b|--builder] [--builder-image] [-c|--confirm]
|
||||
[-v|--verbose]
|
||||
{{rootCmdUse}} run [-r|--registry] [-i|--image] [-e|--env] [--build]
|
||||
[-b|--builder] [--builder-image] [-c|--confirm]
|
||||
[--address] [--json] [-v|--verbose]
|
||||
|
||||
DESCRIPTION
|
||||
Run the function locally.
|
||||
|
@ -36,21 +38,19 @@ DESCRIPTION
|
|||
Values provided for flags are not persisted to the function's metadata.
|
||||
|
||||
Containerized Runs
|
||||
The --container flag indicates that the function's container shuould be
|
||||
run rather than running the source code directly. This may require that
|
||||
the function's container first be rebuilt. Building the container on or
|
||||
off can be altered using the --build flag. The default value --build=auto
|
||||
indicates the system should automatically build the container only if
|
||||
necessary.
|
||||
You can build your function in a container using the Pack or S2i builders.
|
||||
On the contrary, non-containerized run is achieved via Host builder which
|
||||
will use your host OS' environment to build the function. This builder is
|
||||
currently enabled for Go and Python. Building defaults to using the Host
|
||||
builder when available. You can alter this by using the --builder flag
|
||||
eg: --builder=s2i.
|
||||
|
||||
Process Scaffolding
|
||||
This is an Experimental Feature currently available only to Go projects.
|
||||
When running a function with --container=false (host-based runs), the
|
||||
function is first wrapped code which presents it as a process.
|
||||
This "scaffolding" is transient, written for each build or run, and should
|
||||
in most cases be transparent to a function author. However, to customize,
|
||||
or even completely replace this scafolding code, see the 'scaffold'
|
||||
subcommand.
|
||||
This is an Experimental Feature currently available only to Go and Python
|
||||
projects. When running a function with --builder=host, the function is
|
||||
first wrapped with code which presents it as a process. This "scaffolding"
|
||||
is transient, written for each build or run, and should in most cases be
|
||||
transparent to a function author.
|
||||
|
||||
EXAMPLES
|
||||
|
||||
|
@ -58,16 +58,25 @@ EXAMPLES
|
|||
$ {{rootCmdUse}} run
|
||||
|
||||
o Run the function locally from within its container, forcing a rebuild
|
||||
of the container even if no filesysem changes are detected
|
||||
$ {{rootCmdUse}} run --build
|
||||
of the container even if no filesystem changes are detected. There are 2
|
||||
builders available for containerized build - 'pack' and 's2i'.
|
||||
$ {{rootCmdUse}} run --build=<builder>
|
||||
|
||||
o Run the function locally on the host with no containerization (Go only).
|
||||
$ {{rootCmdUse}} run --container=false
|
||||
o Run the function locally on the host with no containerization (Go/Python only).
|
||||
$ {{rootCmdUse}} run --builder=host
|
||||
|
||||
o Run the function locally on a specific address.
|
||||
$ {{rootCmdUse}} run --address='[::]:8081'
|
||||
|
||||
o Run the function locally and output JSON with the service address.
|
||||
$ {{rootCmdUse}} run --json
|
||||
`,
|
||||
SuggestFor: []string{"rnu"},
|
||||
PreRunE: bindEnv("build", "builder", "builder-image", "confirm", "container", "env", "image", "path", "registry", "start-timeout", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRun(cmd, args, newClient)
|
||||
PreRunE: bindEnv("build", "builder", "builder-image", "base-image",
|
||||
"confirm", "env", "image", "path", "registry",
|
||||
"start-timeout", "verbose", "address", "json"),
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return runRun(cmd, newClient)
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -97,6 +106,8 @@ EXAMPLES
|
|||
builderImage := f.Build.BuilderImages[f.Build.Builder]
|
||||
cmd.Flags().String("builder-image", builderImage,
|
||||
"Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE)")
|
||||
cmd.Flags().StringP("base-image", "", f.Build.BaseImage,
|
||||
"Override the base image for your function (host builder only)")
|
||||
cmd.Flags().StringP("image", "i", f.Image,
|
||||
"Full image name in the form [registry]/[namespace]/[name]:[tag]. This option takes precedence over --registry. Specifying tag is optional. ($FUNC_IMAGE)")
|
||||
cmd.Flags().StringArrayP("env", "e", []string{},
|
||||
|
@ -117,8 +128,9 @@ EXAMPLES
|
|||
cmd.Flags().String("build", "auto",
|
||||
"Build the function. [auto|true|false]. ($FUNC_BUILD)")
|
||||
cmd.Flags().Lookup("build").NoOptDefVal = "true" // register `--build` as equivalient to `--build=true`
|
||||
cmd.Flags().BoolP("container", "t", true,
|
||||
"Run the function in a container. ($FUNC_CONTAINER)")
|
||||
cmd.Flags().String("address", "",
|
||||
"Interface and port on which to bind and listen. Default is 127.0.0.1:8080, or an available port if 8080 is not available. ($FUNC_ADDRESS)")
|
||||
cmd.Flags().Bool("json", false, "Output as JSON. ($FUNC_JSON)")
|
||||
|
||||
// Oft-shared flags:
|
||||
addConfirmFlag(cmd, cfg.Confirm)
|
||||
|
@ -137,39 +149,33 @@ EXAMPLES
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runRun(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
func runRun(cmd *cobra.Command, newClient ClientFactory) (err error) {
|
||||
var (
|
||||
cfg runConfig
|
||||
f fn.Function
|
||||
)
|
||||
if cfg, err = newRunConfig(cmd).Prompt(); err != nil {
|
||||
return
|
||||
}
|
||||
cfg = newRunConfig(cmd) // Will add Prompt on upcoming UX refactor
|
||||
|
||||
if f, err = fn.NewFunction(cfg.Path); err != nil {
|
||||
return
|
||||
}
|
||||
if err = cfg.Validate(cmd, f); err != nil {
|
||||
return
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
}
|
||||
|
||||
if err = cfg.Validate(cmd, f); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if f, err = cfg.Configure(f); err != nil { // Updates f with deploy cfg
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: this is duplicate logic with runBuild and runRun.
|
||||
// Refactor both to have this logic part of creating the buildConfig and thus
|
||||
// shared because newRunConfig uses newBuildConfig for its embedded struct.
|
||||
if f.Registry != "" && !cmd.Flags().Changed("image") && strings.Index(f.Image, "/") > 0 && !strings.HasPrefix(f.Image, f.Registry) {
|
||||
prfx := f.Registry
|
||||
if prfx[len(prfx)-1:] != "/" {
|
||||
prfx = prfx + "/"
|
||||
}
|
||||
sps := strings.Split(f.Image, "/")
|
||||
updImg := prfx + sps[len(sps)-1]
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "Warning: function has current image '%s' which has a different registry than the currently configured registry '%s'. The new image tag will be '%s'. To use an explicit image, use --image.\n", f.Image, f.Registry, updImg)
|
||||
f.Image = updImg
|
||||
container := f.Build.Builder != "host"
|
||||
|
||||
// Ignore the verbose flag if JSON output
|
||||
if cfg.JSON {
|
||||
cfg.Verbose = false
|
||||
}
|
||||
|
||||
// Client
|
||||
|
@ -177,7 +183,7 @@ func runRun(cmd *cobra.Command, args []string, newClient ClientFactory) (err err
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cfg.Container {
|
||||
if container {
|
||||
clientOptions = append(clientOptions, fn.WithRunner(docker.NewRunner(cfg.Verbose, os.Stdout, os.Stderr)))
|
||||
}
|
||||
if cfg.StartTimeout != 0 {
|
||||
|
@ -191,13 +197,40 @@ func runRun(cmd *cobra.Command, args []string, newClient ClientFactory) (err err
|
|||
//
|
||||
// If requesting to run via the container, build the container if it is
|
||||
// either out-of-date or a build was explicitly requested.
|
||||
if cfg.Container {
|
||||
if container {
|
||||
var digested bool
|
||||
|
||||
buildOptions, err := cfg.buildOptions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f, err = build(cmd, cfg.Build, f, client, buildOptions); err != nil {
|
||||
return err
|
||||
|
||||
// if image was specified, check if its digested and do basic validation
|
||||
if cfg.Image != "" {
|
||||
digested, err = isDigested(cfg.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// image was parsed and both digested AND undigested imgs are valid
|
||||
f.Build.Image = cfg.Image
|
||||
}
|
||||
|
||||
// actual build step
|
||||
if !digested {
|
||||
if f, _, err = build(cmd, cfg.Build, f, client, buildOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else { // if !container
|
||||
// dont run digested image without a container
|
||||
if cfg.Image != "" {
|
||||
digested, err := isDigested(cfg.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if digested {
|
||||
return fmt.Errorf("cannot use digested image with non-containerized builds (--builder=host)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,7 +240,7 @@ func runRun(cmd *cobra.Command, args []string, newClient ClientFactory) (err err
|
|||
// For the former, build is required and a container runtime. For the
|
||||
// latter, scaffolding is first applied and the local host must be
|
||||
// configured to build/run the language of the function.
|
||||
job, err := client.Run(cmd.Context(), f)
|
||||
job, err := client.Run(cmd.Context(), f, fn.RunWithAddress(cfg.Address))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -217,7 +250,27 @@ func runRun(cmd *cobra.Command, args []string, newClient ClientFactory) (err err
|
|||
}
|
||||
}()
|
||||
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Running on host port %v\n", job.Port)
|
||||
// Output based on format
|
||||
if cfg.JSON {
|
||||
// Create JSON output structure
|
||||
output := struct {
|
||||
Address string `json:"address"`
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
}{
|
||||
Address: fmt.Sprintf("http://%s:%s", job.Host, job.Port),
|
||||
Host: job.Host,
|
||||
Port: job.Port,
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal JSON output: %w", err)
|
||||
}
|
||||
fmt.Fprintln(cmd.OutOrStdout(), string(jsonData))
|
||||
} else {
|
||||
fmt.Fprintf(cmd.OutOrStderr(), "Function running on %s\n", net.JoinHostPort(job.Host, job.Port))
|
||||
}
|
||||
|
||||
select {
|
||||
case <-cmd.Context().Done():
|
||||
|
@ -248,16 +301,18 @@ type runConfig struct {
|
|||
// Can be 'auto' or a truthy value.
|
||||
Build string
|
||||
|
||||
// Container indicates the function should be run in a container.
|
||||
// Requires the container be built.
|
||||
Container bool
|
||||
|
||||
// Env variables. may include removals using a "-"
|
||||
Env []string
|
||||
|
||||
// StartTimeout optionally adjusts the startup timeout from the client's
|
||||
// default of fn.DefaultStartTimeout.
|
||||
StartTimeout time.Duration
|
||||
|
||||
// Address is the interface and port to bind (e.g. "0.0.0.0:8081")
|
||||
Address string
|
||||
|
||||
// JSON output format
|
||||
JSON bool
|
||||
}
|
||||
|
||||
func newRunConfig(cmd *cobra.Command) (c runConfig) {
|
||||
|
@ -265,8 +320,9 @@ func newRunConfig(cmd *cobra.Command) (c runConfig) {
|
|||
buildConfig: newBuildConfig(),
|
||||
Build: viper.GetString("build"),
|
||||
Env: viper.GetStringSlice("env"),
|
||||
Container: viper.GetBool("container"),
|
||||
StartTimeout: viper.GetDuration("start-timeout"),
|
||||
Address: viper.GetString("address"),
|
||||
JSON: viper.GetBool("json"),
|
||||
}
|
||||
// NOTE: .Env should be viper.GetStringSlice, but this returns unparsed
|
||||
// results and appears to be an open issue since 2017:
|
||||
|
@ -289,7 +345,7 @@ func (c runConfig) Configure(f fn.Function) (fn.Function, error) {
|
|||
|
||||
f.Run.Envs, err = applyEnvs(f.Run.Envs, c.Env)
|
||||
|
||||
// The other members; build, path, and container; are not part of function
|
||||
// The other members; build and path; are not part of function
|
||||
// state, so are not mentioned here in Configure.
|
||||
return f, err
|
||||
}
|
||||
|
@ -322,20 +378,13 @@ func (c runConfig) Validate(cmd *cobra.Command, f fn.Function) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is currently no local host runner implemented, so specifying
|
||||
// --container=false should return an informative error for runtimes other
|
||||
// than Go that is more helpful than the cryptic, though correct, error
|
||||
// from the Client that it was instantated without a runner.
|
||||
// TODO: modify this check when the local host runner is available to
|
||||
// only generate this error when --container==false && the --language is
|
||||
// not yet implemented.
|
||||
if !c.Container && f.Runtime != "go" {
|
||||
return errors.New("the ability to run functions outside of a container via 'func run' is coming soon.")
|
||||
if f.Build.Builder == "host" && !oci.IsSupported(f.Runtime) {
|
||||
return fmt.Errorf("the %q runtime currently requires being run in a container", f.Runtime)
|
||||
}
|
||||
|
||||
// When the docker runner respects the StartTimeout, this validation check
|
||||
// can be removed
|
||||
if c.StartTimeout != 0 && c.Container {
|
||||
if c.StartTimeout != 0 && f.Build.Builder != "host" {
|
||||
return errors.New("the ability to specify the startup timeout for containerized runs is coming soon")
|
||||
}
|
||||
|
||||
|
|
432
cmd/run_test.go
432
cmd/run_test.go
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
"knative.dev/func/pkg/mock"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
func TestRun_Run(t *testing.T) {
|
||||
|
@ -20,6 +21,7 @@ func TestRun_Run(t *testing.T) {
|
|||
runError error // Set the runner to yield this error
|
||||
buildInvoked bool // should Builder.Build be invoked?
|
||||
runInvoked bool // should Runner.Run be invoked?
|
||||
jsonOutput bool // expect JSON output format
|
||||
}{
|
||||
{
|
||||
name: "run and build by default",
|
||||
|
@ -99,14 +101,22 @@ func TestRun_Run(t *testing.T) {
|
|||
buildInvoked: true,
|
||||
runInvoked: false,
|
||||
},
|
||||
{
|
||||
name: "run with json output",
|
||||
desc: "Should output JSON format when --json flag is used",
|
||||
args: []string{"--json"},
|
||||
buildInvoked: true,
|
||||
runInvoked: true,
|
||||
jsonOutput: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
root := fromTempDirectory(t)
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
runner := mock.NewRunner()
|
||||
if tt.runError != nil {
|
||||
runner.RunFn = func(context.Context, fn.Function, time.Duration) (*fn.Job, error) { return nil, tt.runError }
|
||||
runner.RunFn = func(context.Context, fn.Function, string, time.Duration) (*fn.Job, error) { return nil, tt.runError }
|
||||
}
|
||||
|
||||
builder := mock.NewBuilder()
|
||||
|
@ -173,3 +183,421 @@ func TestRun_Run(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRun_Images ensures that runnning 'func run' with --image
|
||||
// (and additional flags) works as intended
|
||||
func TestRun_Images(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
buildInvoked bool
|
||||
runInvoked bool
|
||||
|
||||
runError error
|
||||
buildError error
|
||||
}{
|
||||
{
|
||||
name: "image with digest",
|
||||
args: []string{"--image", "exampleimage@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},
|
||||
runInvoked: true,
|
||||
buildInvoked: false,
|
||||
},
|
||||
{
|
||||
name: "image with tag direct deploy",
|
||||
args: []string{"--image", "username/exampleimage:latest", "--build=false"},
|
||||
runInvoked: true,
|
||||
buildInvoked: false,
|
||||
},
|
||||
{
|
||||
name: "digested image without container should fail",
|
||||
args: []string{"--container=false", "--image", "exampleimage@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},
|
||||
runInvoked: false,
|
||||
buildInvoked: false,
|
||||
buildError: fmt.Errorf("cannot use digested image with --container=false"),
|
||||
},
|
||||
{
|
||||
name: "image should build even with tagged image given",
|
||||
args: []string{"--image", "username/exampleimage:latest"},
|
||||
runInvoked: true,
|
||||
buildInvoked: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
runner := mock.NewRunner()
|
||||
|
||||
if tt.runError != nil {
|
||||
runner.RunFn = func(context.Context, fn.Function, string, time.Duration) (*fn.Job, error) { return nil, tt.runError }
|
||||
}
|
||||
|
||||
builder := mock.NewBuilder()
|
||||
if tt.buildError != nil {
|
||||
builder.BuildFn = func(f fn.Function) error { return tt.buildError }
|
||||
}
|
||||
|
||||
// using a command whose client will be populated with mock
|
||||
// builder and mock runner, each of which may be set to error if the
|
||||
// test has an error defined.
|
||||
cmd := NewRunCmd(NewTestClient(
|
||||
fn.WithRunner(runner),
|
||||
fn.WithBuilder(builder),
|
||||
fn.WithRegistry("ghcr.com/reg"),
|
||||
))
|
||||
cmd.SetArgs(tt.args) // Do not use test command args
|
||||
|
||||
// set test case's function instance
|
||||
_, err := fn.New().Init(fn.Function{Root: root, Runtime: "go"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
runErrCh := make(chan error, 1)
|
||||
go func() {
|
||||
t0 := tt // capture tt into closure
|
||||
_, err := cmd.ExecuteContextC(ctx)
|
||||
if err != nil && t0.buildError != nil {
|
||||
// This is an expected error, so simply continue execution ignoring
|
||||
// the error (send nil on the channel to release the parent routine
|
||||
runErrCh <- nil
|
||||
return
|
||||
} else if err != nil {
|
||||
runErrCh <- err // error not expected
|
||||
return
|
||||
}
|
||||
|
||||
// No errors, but an error was expected:
|
||||
if t0.buildError != nil {
|
||||
runErrCh <- fmt.Errorf("Expected error: %v but got %v\n", t0.buildError, err)
|
||||
}
|
||||
|
||||
// Ensure invocations match expectations
|
||||
if builder.BuildInvoked != tt.buildInvoked {
|
||||
runErrCh <- fmt.Errorf("Function was expected to build is: %v but build execution was: %v", tt.buildInvoked, builder.BuildInvoked)
|
||||
}
|
||||
if runner.RunInvoked != tt.runInvoked {
|
||||
runErrCh <- fmt.Errorf("Function was expected to run is: %v but run execution was: %v", tt.runInvoked, runner.RunInvoked)
|
||||
}
|
||||
|
||||
close(runErrCh) // release the waiting parent process
|
||||
}()
|
||||
cancel() // trigger the return of cmd.ExecuteContextC in the routine
|
||||
<-ctx.Done()
|
||||
if err := <-runErrCh; err != nil { // wait for completion of assertions
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRun_CorrectImage enusures that correct image gets passed through to the
|
||||
// runner.
|
||||
func TestRun_CorrectImage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
image string
|
||||
args []string
|
||||
buildInvoked bool
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "image with digest, auto build",
|
||||
args: []string{"--image", "exampleimage@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},
|
||||
image: "exampleimage@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
|
||||
buildInvoked: false,
|
||||
},
|
||||
{
|
||||
name: "image with tag direct deploy",
|
||||
args: []string{"--image", "username/exampleimage:latest", "--build=false"},
|
||||
image: "username/exampleimage:latest",
|
||||
buildInvoked: false,
|
||||
},
|
||||
{
|
||||
name: "digested image without container should fail",
|
||||
args: []string{"--container=false", "--image", "exampleimage@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},
|
||||
image: "",
|
||||
buildInvoked: false,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "image should build even with tagged image given",
|
||||
args: []string{"--image", "username/exampleimage:latest"},
|
||||
image: "username/exampleimage:latest",
|
||||
buildInvoked: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
runner := mock.NewRunner()
|
||||
|
||||
runner.RunFn = func(_ context.Context, f fn.Function, _ string, _ time.Duration) (*fn.Job, error) {
|
||||
// TODO: add if for empty image? -- should fail beforehand
|
||||
if f.Build.Image != tt.image {
|
||||
return nil, fmt.Errorf("Expected image: %v but got: %v", tt.image, f.Build.Image)
|
||||
}
|
||||
errs := make(chan error, 1)
|
||||
stop := func() error { return nil }
|
||||
return fn.NewJob(f, "127.0.0.1", "8080", errs, stop, false)
|
||||
}
|
||||
|
||||
builder := mock.NewBuilder()
|
||||
if tt.expectError {
|
||||
builder.BuildFn = func(f fn.Function) error { return fmt.Errorf("expected error") }
|
||||
}
|
||||
|
||||
cmd := NewRunCmd(NewTestClient(
|
||||
fn.WithRunner(runner),
|
||||
fn.WithBuilder(builder),
|
||||
fn.WithRegistry("ghcr.com/reg"),
|
||||
))
|
||||
cmd.SetArgs(tt.args)
|
||||
|
||||
// set test case's function instance
|
||||
_, err := fn.New().Init(fn.Function{Root: root, Runtime: "go"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
runErrCh := make(chan error, 1)
|
||||
go func() {
|
||||
t0 := tt // capture tt into closure
|
||||
_, err := cmd.ExecuteContextC(ctx)
|
||||
if err != nil && t0.expectError {
|
||||
// This is an expected error, so simply continue execution ignoring
|
||||
// the error (send nil on the channel to release the parent routine
|
||||
runErrCh <- nil
|
||||
return
|
||||
} else if err != nil {
|
||||
runErrCh <- err // error not expected
|
||||
return
|
||||
}
|
||||
|
||||
// No errors, but an error was expected:
|
||||
if t0.expectError {
|
||||
runErrCh <- fmt.Errorf("Expected error but got '%v'\n", err)
|
||||
}
|
||||
|
||||
// Ensure invocations match expectations
|
||||
if builder.BuildInvoked != tt.buildInvoked {
|
||||
runErrCh <- fmt.Errorf("Function was expected to build is: %v but build execution was: %v", tt.buildInvoked, builder.BuildInvoked)
|
||||
}
|
||||
|
||||
close(runErrCh) // release the waiting parent process
|
||||
}()
|
||||
cancel() // trigger the return of cmd.ExecuteContextC in the routine
|
||||
<-ctx.Done()
|
||||
if err := <-runErrCh; err != nil { // wait for completion of assertions
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRun_DirectOverride tests that an --image passed after a function has
|
||||
// already been build, the given --image with digest will override built function
|
||||
func TestRun_DirectOverride(t *testing.T) {
|
||||
const overrideImage = "registry/myrepo/myimage@sha256:0000000000000000000000000000000000000000000000000000000000000000"
|
||||
root := FromTempDirectory(t)
|
||||
runner := mock.NewRunner()
|
||||
|
||||
runner.RunFn = func(_ context.Context, f fn.Function, _ string, _ time.Duration) (*fn.Job, error) {
|
||||
if f.Build.Image != overrideImage {
|
||||
return nil, fmt.Errorf("Expected image to be overridden with '%v' but got: '%v'", overrideImage, f.Build.Image)
|
||||
}
|
||||
errs := make(chan error, 1)
|
||||
stop := func() error { return nil }
|
||||
return fn.NewJob(f, "127.0.0.1", "8080", errs, stop, false)
|
||||
}
|
||||
|
||||
builder1 := mock.NewBuilder()
|
||||
|
||||
// SETUP THE ENVIRONMENT & SITUATION
|
||||
// create function
|
||||
_, err := fn.New().Init(fn.Function{Root: root, Runtime: "go"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// build function
|
||||
cmdBuild := NewBuildCmd(NewTestClient(fn.WithBuilder(builder1), fn.WithRegistry("example.com/ns-to-override")))
|
||||
if err := cmdBuild.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// fetch the functions state
|
||||
_, err = fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// builder for 'func run' -- shall not be invoked
|
||||
builder2 := mock.NewBuilder()
|
||||
builder2.BuildFn = func(f fn.Function) error {
|
||||
return fmt.Errorf("should not be invoked")
|
||||
}
|
||||
|
||||
// RUN THE ACTUAL TESTED COMMAND
|
||||
cmd := NewRunCmd(NewTestClient(
|
||||
fn.WithRunner(runner),
|
||||
fn.WithBuilder(builder2),
|
||||
fn.WithRegistry("ghcr.com/reg"),
|
||||
))
|
||||
cmd.SetArgs([]string{fmt.Sprintf("--image=%s", overrideImage)})
|
||||
|
||||
// run function with above argument
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
runErrCh := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := cmd.ExecuteContextC(ctx)
|
||||
if err != nil {
|
||||
runErrCh <- err // error was not expected
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure invocation doesnt happen for the second time as the image was
|
||||
// provided with a digest (should not build)
|
||||
if builder2.BuildInvoked {
|
||||
runErrCh <- fmt.Errorf("Function was not expected to build again but it did")
|
||||
}
|
||||
|
||||
close(runErrCh) // release the waiting parent process
|
||||
}()
|
||||
cancel() // trigger the return of cmd.ExecuteContextC in the routine
|
||||
<-ctx.Done()
|
||||
if err := <-runErrCh; err != nil { // wait for completion of assertions
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRun_Address ensures that the --address flag is passed to the runner.
|
||||
func TestRun_Address(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
_, err := fn.New().Init(fn.Function{Root: root, Runtime: "go"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testAddr := "0.0.0.0:1234"
|
||||
|
||||
runner := mock.NewRunner()
|
||||
runner.RunFn = func(_ context.Context, f fn.Function, addr string, _ time.Duration) (*fn.Job, error) {
|
||||
if addr != testAddr {
|
||||
return nil, fmt.Errorf("Expected address '%v' but got: '%v'", testAddr, addr)
|
||||
}
|
||||
errs := make(chan error, 1)
|
||||
stop := func() error { return nil }
|
||||
return fn.NewJob(f, "127.0.0.1", "8080", errs, stop, false)
|
||||
}
|
||||
|
||||
// RUN THE ACTUAL TESTED COMMAND
|
||||
cmd := NewRunCmd(NewTestClient(
|
||||
fn.WithRunner(runner),
|
||||
fn.WithRegistry("ghcr.com/reg"),
|
||||
))
|
||||
cmd.SetArgs([]string{"--address", testAddr})
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
runErrCh := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := cmd.ExecuteContextC(ctx)
|
||||
if err != nil {
|
||||
runErrCh <- err // error was not expected
|
||||
return
|
||||
}
|
||||
close(runErrCh) // release the waiting parent process
|
||||
}()
|
||||
cancel() // trigger the return of cmd.ExecuteContextC in the routine
|
||||
<-ctx.Done()
|
||||
if err := <-runErrCh; err != nil { // wait for completion of assertions
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRun_BaseImage ensures that running func run --base-image with various
|
||||
// other
|
||||
func TestRun_BaseImage(t *testing.T) {
|
||||
const baseImage = "example.com/repo/baseImage"
|
||||
tests := []struct {
|
||||
name string
|
||||
runtime string
|
||||
builder string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "should-succeed: python-runtime with host-builder",
|
||||
runtime: "python",
|
||||
builder: "host",
|
||||
},
|
||||
{
|
||||
name: "should-succeed: go-runtime with host-builder",
|
||||
runtime: "go",
|
||||
builder: "host",
|
||||
},
|
||||
{
|
||||
name: "should-fail: python-runtime with pack-builder",
|
||||
runtime: "python",
|
||||
builder: "pack",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
runner := mock.NewRunner()
|
||||
|
||||
runner.RunFn = func(_ context.Context, f fn.Function, _ string, _ time.Duration) (*fn.Job, error) {
|
||||
errs := make(chan error, 1)
|
||||
stop := func() error { return nil }
|
||||
return fn.NewJob(f, "127.0.0.1", "8080", errs, stop, false)
|
||||
}
|
||||
|
||||
builder := mock.NewBuilder()
|
||||
//if tt.expectError {
|
||||
// builder.BuildFn = func(f fn.Function) error { return fmt.Errorf("expected error") }
|
||||
//}
|
||||
|
||||
cmd := NewRunCmd(NewTestClient(
|
||||
fn.WithRunner(runner),
|
||||
fn.WithBuilder(builder),
|
||||
fn.WithRegistry(TestRegistry),
|
||||
))
|
||||
args := []string{"--build=true", fmt.Sprintf("--builder=%s", tt.builder), fmt.Sprintf("--base-image=%s", baseImage)}
|
||||
cmd.SetArgs(args)
|
||||
|
||||
// set test case's function instance
|
||||
_, err := fn.New().Init(fn.Function{Root: root, Runtime: tt.runtime})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
runErrCh := make(chan error, 1)
|
||||
go func() {
|
||||
t0 := tt // capture tt into closure
|
||||
_, err := cmd.ExecuteContextC(ctx)
|
||||
if err != nil && t0.expectError {
|
||||
// This is an expected error, so simply continue execution ignoring
|
||||
// the error (send nil on the channel to release the parent routine
|
||||
runErrCh <- nil
|
||||
return
|
||||
} else if err != nil {
|
||||
runErrCh <- err // error not expected
|
||||
return
|
||||
}
|
||||
|
||||
// No errors, but an error was expected:
|
||||
if t0.expectError {
|
||||
runErrCh <- fmt.Errorf("Expected error but got '%v'\n", err)
|
||||
}
|
||||
close(runErrCh) // release the waiting parent process
|
||||
}()
|
||||
cancel() // trigger the return of cmd.ExecuteContextC in the routine
|
||||
<-ctx.Done()
|
||||
if err := <-runErrCh; err != nil { // wait for completion of assertions
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
)
|
||||
|
||||
func NewSubscribeCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "subscribe",
|
||||
Short: "Subscribe a function to events",
|
||||
Long: `Subscribe a function to events
|
||||
|
||||
Subscribe the function to a set of events, matching a set of filters for Cloud Event metadata
|
||||
and a Knative Broker from where the events are consumed.
|
||||
`,
|
||||
Example: `
|
||||
# Subscribe the function to the 'default' broker where events have 'type' of 'com.example'
|
||||
and an 'extension' attribute for the value 'my-extension-value'.
|
||||
{{rootCmdUse}} subscribe --filter type=com.example --filter extension=my-extension-value
|
||||
|
||||
# Subscribe the function to the 'my-broker' broker where events have 'type' of 'com.example'
|
||||
and an 'extension' attribute for the value 'my-extension-value'.
|
||||
{{rootCmdUse}} subscribe --filter type=com.example --filter extension=my-extension-value --source my-broker
|
||||
`,
|
||||
SuggestFor: []string{"subcsribe"}, //nolint:misspell
|
||||
PreRunE: bindEnv("filter", "source"),
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return runSubscribe(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringArrayP("filter", "f", []string{}, "Filter for the Cloud Event metadata")
|
||||
|
||||
cmd.Flags().StringP("source", "s", "default", "The source, like a Knative Broker")
|
||||
|
||||
addPathFlag(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runSubscribe(cmd *cobra.Command) (err error) {
|
||||
var (
|
||||
cfg subscibeConfig
|
||||
f fn.Function
|
||||
)
|
||||
cfg = newSubscribeConfig(cmd)
|
||||
|
||||
if f, err = fn.NewFunction(effectivePath()); err != nil {
|
||||
return
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fn.NewErrNotInitialized(f.Root)
|
||||
}
|
||||
|
||||
// add subscription to function
|
||||
f.Deploy.Subscriptions = updateOrAddSubscription(f.Deploy.Subscriptions, cfg)
|
||||
|
||||
// pump it
|
||||
return f.Write()
|
||||
}
|
||||
|
||||
func extractFilterMap(filters []string) map[string]string {
|
||||
subscriptionFilters := make(map[string]string)
|
||||
for _, filter := range filters {
|
||||
kv := strings.Split(filter, "=")
|
||||
if len(kv) != 2 {
|
||||
fmt.Println("Invalid pair:", filter)
|
||||
continue
|
||||
}
|
||||
key := kv[0]
|
||||
value := kv[1]
|
||||
subscriptionFilters[key] = value
|
||||
}
|
||||
return subscriptionFilters
|
||||
}
|
||||
|
||||
type subscibeConfig struct {
|
||||
Filter []string
|
||||
Source string
|
||||
}
|
||||
|
||||
func updateOrAddSubscription(subscriptions []fn.KnativeSubscription, cfg subscibeConfig) []fn.KnativeSubscription {
|
||||
found := false
|
||||
newFilters := extractFilterMap(cfg.Filter)
|
||||
|
||||
// Iterate over subscriptions to find if one with the same source already exists
|
||||
for i, subscription := range subscriptions {
|
||||
if subscription.Source == cfg.Source {
|
||||
found = true
|
||||
|
||||
if subscription.Filters == nil {
|
||||
subscription.Filters = make(map[string]string)
|
||||
}
|
||||
|
||||
// Update filters. Override if the key already exists.
|
||||
for newKey, newValue := range newFilters {
|
||||
subscription.Filters[newKey] = newValue
|
||||
}
|
||||
subscriptions[i] = subscription // Reassign the updated subscription
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If a subscription with the source was not found, add a new one
|
||||
if !found {
|
||||
subscriptions = append(subscriptions, fn.KnativeSubscription{
|
||||
Source: cfg.Source,
|
||||
Filters: newFilters,
|
||||
})
|
||||
}
|
||||
return subscriptions
|
||||
}
|
||||
|
||||
func newSubscribeConfig(cmd *cobra.Command) (c subscibeConfig) {
|
||||
c = subscibeConfig{
|
||||
Filter: viper.GetStringSlice("filter"),
|
||||
Source: viper.GetString("source"),
|
||||
}
|
||||
// NOTE: .Filter should be viper.GetStringSlice, but this returns unparsed
|
||||
// results and appears to be an open issue since 2017:
|
||||
// https://github.com/spf13/viper/issues/380
|
||||
var err error
|
||||
if c.Filter, err = cmd.Flags().GetStringArray("filter"); err != nil {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "error reading filter arguments: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
func TestSubscribeWithAll(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
_, err := fn.New().Init(fn.Function{Runtime: "go", Root: root})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=go"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err := fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "my-broker" {
|
||||
t.Fatalf("Expected subscription for broker to be 'my-broker', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "go" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'go', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscribeWithMultiple(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
_, err := fn.New().Init(fn.Function{Runtime: "go", Root: root})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=go"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err := fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "my-broker" {
|
||||
t.Fatalf("Expected subscription for broker to be 'my-broker', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "go" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'go', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
|
||||
cmd = NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "bar=foo"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err = fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "my-broker" {
|
||||
t.Fatalf("Expected subscription for broker to be 'my-broker', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "go" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'go', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Filters["bar"] != "foo" {
|
||||
t.Fatalf("Expected subscription filter for 'bar' to be 'foo', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSubscribeWithMultipleBrokersAndOverride(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
_, err := fn.New().Init(fn.Function{Runtime: "go", Root: root})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=go"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err := fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "my-broker" {
|
||||
t.Fatalf("Expected subscription for broker to be 'my-broker', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "go" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'go', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
|
||||
cmd = NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--filter", "bar=foo"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err = fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[1].Source != "default" {
|
||||
t.Fatalf("Expected subscription for broker to be 'default', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[1].Filters["bar"] != "foo" {
|
||||
t.Fatalf("Expected subscription filter for 'bar' to be 'foo', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
|
||||
cmd = NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=golang"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err = fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "my-broker" {
|
||||
t.Fatalf("Expected subscription for broker to be 'my-broker', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "golang" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'golang', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscribeWithNoExplicitSourceAll(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
_, err := fn.New().Init(fn.Function{Runtime: "go", Root: root})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--filter", "foo=go"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err := fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "default" {
|
||||
t.Fatalf("Expected subscription for broker to be 'default', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "go" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'go', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscribeWithDuplicated(t *testing.T) {
|
||||
root := FromTempDirectory(t)
|
||||
|
||||
_, err := fn.New().Init(fn.Function{Runtime: "go", Root: root})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=go"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err := fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions == nil {
|
||||
t.Fatal("Expected subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Source != "my-broker" {
|
||||
t.Fatalf("Expected subscription for broker to be 'my-broker', but got '%v'", f.Deploy.Subscriptions[0].Source)
|
||||
}
|
||||
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "go" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'go', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
|
||||
// call it again with same
|
||||
cmd = NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=go"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err = fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(f.Deploy.Subscriptions) > 1 {
|
||||
t.Fatal("Expected only one subscription to be present ")
|
||||
}
|
||||
|
||||
// call it again and override
|
||||
cmd = NewSubscribeCmd()
|
||||
cmd.SetArgs([]string{"--source", "my-broker", "--filter", "foo=gogo"})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Now load the function and ensure that the subscription is set correctly.
|
||||
f, err = fn.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(f.Deploy.Subscriptions) > 1 {
|
||||
t.Fatal("Expected only one subscription to be present ")
|
||||
}
|
||||
if f.Deploy.Subscriptions[0].Filters["foo"] != "gogo" {
|
||||
t.Fatalf("Expected subscription filter for 'foo' to be 'gogo', but got '%v'", f.Deploy.Subscriptions[0].Filters["foo"])
|
||||
}
|
||||
|
||||
}
|
|
@ -56,11 +56,6 @@ EXAMPLES
|
|||
o Return Go templates in a specific repository
|
||||
$ {{rootCmdUse}} templates go --repository=https://github.com/boson-project/templates
|
||||
`,
|
||||
SuggestFor: []string{"template", "templtaes", "templatse", "remplates",
|
||||
"gemplates", "yemplates", "tenplates", "tekplates", "tejplates",
|
||||
"temolates", "temllates", "temppates", "tempmates", "tempkates",
|
||||
"templstes", "templztes", "templqtes", "templares", "templages", //nolint:misspell
|
||||
"templayes", "templatee", "templatea", "templated", "templatew"},
|
||||
PreRunE: bindEnv("json", "repository", "verbose"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runTemplates(cmd, args, newClient)
|
||||
|
@ -81,7 +76,7 @@ EXAMPLES
|
|||
|
||||
func runTemplates(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
||||
// Gather config
|
||||
cfg, err := newTemplatesConfig(newClient)
|
||||
cfg, err := newTemplatesConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -174,7 +169,7 @@ type templatesConfig struct {
|
|||
JSON bool // output as JSON
|
||||
}
|
||||
|
||||
func newTemplatesConfig(newClient ClientFactory) (cfg templatesConfig, err error) {
|
||||
func newTemplatesConfig() (cfg templatesConfig, err error) {
|
||||
cfg = templatesConfig{
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
Repository: viper.GetString("repository"),
|
||||
|
|
|
@ -21,8 +21,8 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
"knative.dev/client-pkg/pkg/util"
|
||||
"knative.dev/client-pkg/pkg/util/test"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/client/pkg/util/test"
|
||||
)
|
||||
|
||||
var groups = CommandGroups{
|
||||
|
|
|
@ -23,8 +23,8 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
"knative.dev/client-pkg/pkg/util"
|
||||
"knative.dev/client-pkg/pkg/util/test"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/client/pkg/util/test"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
|
|
|
@ -6,12 +6,13 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"gotest.tools/v3/assert"
|
||||
. "knative.dev/func/pkg/testing"
|
||||
)
|
||||
|
||||
// TestTemplates_Default ensures that the default behavior is listing all
|
||||
// templates for all language runtimes.
|
||||
func TestTemplates_Default(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
buf := piped(t) // gather output
|
||||
cmd := NewTemplatesCmd(NewClient)
|
||||
|
@ -26,9 +27,7 @@ go http
|
|||
node cloudevents
|
||||
node http
|
||||
python cloudevents
|
||||
python flask
|
||||
python http
|
||||
python wsgi
|
||||
quarkus cloudevents
|
||||
quarkus http
|
||||
rust cloudevents
|
||||
|
@ -46,7 +45,7 @@ typescript http`
|
|||
// TestTemplates_JSON ensures that listing templates respects the --json
|
||||
// output format.
|
||||
func TestTemplates_JSON(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
buf := piped(t) // gather output
|
||||
cmd := NewTemplatesCmd(NewClient)
|
||||
|
@ -66,9 +65,7 @@ func TestTemplates_JSON(t *testing.T) {
|
|||
],
|
||||
"python": [
|
||||
"cloudevents",
|
||||
"flask",
|
||||
"http",
|
||||
"wsgi"
|
||||
"http"
|
||||
],
|
||||
"quarkus": [
|
||||
"cloudevents",
|
||||
|
@ -96,7 +93,7 @@ func TestTemplates_JSON(t *testing.T) {
|
|||
// TestTemplates_ByLanguage ensures that the output is correctly filtered
|
||||
// by language runtime when provided.
|
||||
func TestTemplates_ByLanguage(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewTemplatesCmd(NewClient)
|
||||
cmd.SetArgs([]string{"go"})
|
||||
|
@ -135,7 +132,7 @@ http`
|
|||
}
|
||||
|
||||
func TestTemplates_ErrTemplateRepoDoesNotExist(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewTemplatesCmd(NewClient)
|
||||
cmd.SetArgs([]string{"--repository", "https://github.com/boson-project/repo-does-not-exist"})
|
||||
|
@ -145,7 +142,7 @@ func TestTemplates_ErrTemplateRepoDoesNotExist(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTemplates_WrongRepositoryUrl(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
_ = FromTempDirectory(t)
|
||||
|
||||
cmd := NewTemplatesCmd(NewClient)
|
||||
cmd.SetArgs([]string{"--repository", "wrong://github.com/boson-project/repo-does-not-exist"})
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
namespace: "globaldefault"
|
|
@ -1,25 +0,0 @@
|
|||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
insecure-skip-tls-verify: true
|
||||
server: https://cluster.example.com:6443
|
||||
name: cluster-example-com:6443
|
||||
contexts:
|
||||
- context:
|
||||
cluster: cluster-example-com:6443
|
||||
namespace: default
|
||||
user: kube:admin/cluster-example-com:6443
|
||||
name: default/cluster-example-com:6443/kube:admin
|
||||
- context:
|
||||
cluster: cluster-example-com:6443
|
||||
namespace: mynamespace
|
||||
user: kube:admin/cluster-example-com:6443
|
||||
name: mynamespace/cluster-example-com:6443/kube:admin
|
||||
current-context: mynamespace/cluster-example-com:6443/kube:admin
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kubeadmin
|
||||
user:
|
||||
token: sha256~XXXXexample-test-hash
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"knative.dev/func/pkg/pipelines/tekton"
|
||||
)
|
||||
|
||||
func NewTektonClusterTasksCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tkn-tasks",
|
||||
Short: "List tekton cluster tasks as multi-document yaml",
|
||||
Long: `This command prints tekton tekton task embed in the func binary.
|
||||
Some advanced functionality like OpenShift's Web Console build my require installation of these tasks.
|
||||
Installation: func tkn-tasks | kubectl apply -f -
|
||||
`,
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
_, err := fmt.Fprintln(cmd.OutOrStdout(), tekton.GetClusterTasks())
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
|
@ -31,10 +31,10 @@ DESCRIPTION
|
|||
$ {{rootCmdUse}} version -v
|
||||
|
||||
`,
|
||||
SuggestFor: []string{"vers", "verison"}, //nolint:misspell
|
||||
SuggestFor: []string{"vers", "version"}, //nolint:misspell
|
||||
PreRunE: bindEnv("verbose"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
runVersion(cmd, args, version)
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
runVersion(cmd, version)
|
||||
},
|
||||
}
|
||||
cfg, err := config.NewDefault()
|
||||
|
@ -47,7 +47,7 @@ DESCRIPTION
|
|||
}
|
||||
|
||||
// Run
|
||||
func runVersion(cmd *cobra.Command, args []string, version Version) {
|
||||
func runVersion(cmd *cobra.Command, version Version) {
|
||||
version.Verbose = viper.GetBool("verbose")
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%v\n", version)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,10 @@ To build the core project, run `make` from the repository root. This will resul
|
|||
|
||||
To remove built artifacts, use `make clean`.
|
||||
|
||||
### Build affecting environment variables
|
||||
* `FUNC_REPO_REF` affects which github repo will be used to fetch tekton tasks for on cluster build. Default: `knative/func`.
|
||||
* `FUNC_REPO_BRANCH_REF` affects which github branch will be used to fetch tekton tasks for on cluster build. Default: `main`.
|
||||
|
||||
## Testing
|
||||
|
||||
To run core unit tests, use `make test`.
|
||||
|
@ -25,7 +29,7 @@ The source of these templates is `./templates`; a directory subdivided by langua
|
|||
For example, the Go HTTP template is located in `./templates/go/http`.
|
||||
The client library and CLI are self-contained
|
||||
by encoding this directory as a ZIP byte array in the `./generate/zz_filesystem_generated.go` file.
|
||||
Therefore, any updates to templates requires re-generating this file.
|
||||
Therefore, any updates to templates require re-generating this file.
|
||||
|
||||
When changes are made to files in the `./templates` directory,
|
||||
regenerate `./generate/zz_filesystem_generated.go` by running `make generate/zz_filesystem_generated.go`.
|
||||
|
@ -72,7 +76,7 @@ exit 0
|
|||
|
||||
If you would like to run integration tests prior to opening a pull request against origin, you can enable Actions in your fork of this repository and create a pull request to your own main branch.
|
||||
|
||||
If you would like to run integraiton tests locally, or would like to use the CLI / Client Library directly against a local cluster, the cluster allocation script can be used locally as well, by following the steps below.
|
||||
If you would like to run integration tests locally, or would like to use the CLI / Client Library directly against a local cluster, the cluster allocation script can be used locally as well, by following the steps below.
|
||||
|
||||
|
||||
### Prerequisites
|
||||
|
@ -89,16 +93,16 @@ Allocate a new local cluster by running `hack/allocate.sh`.
|
|||
|
||||
### Registry
|
||||
|
||||
The allocation script sets up a local container registry and connects it to the cluster. This registry must be set as trusted and its address entered in the local hosts file. This is a one-time configuration and on Linux can be accomplished by running `hack/registry.sh`.
|
||||
The allocation script sets up a local container registry and connects it to the cluster. This registry must be set as trusted and its address entered in the local `hosts` file. This is a one-time configuration and on Linux can be accomplished by running `hack/registry.sh`.
|
||||
|
||||
On other systems, add `127.0.0.1 kind-registry` to your local hosts file and `"insecure-registries" = ["kind-registry:50000"]` to your docker daemon config (`docker/daemon.json`).
|
||||
On other systems, add `127.0.0.1 kind-registry` to your local `hosts` file and `"insecure-registries" = ["kind-registry:50000"]` to your docker daemon config (`docker/daemon.json`).
|
||||
|
||||
|
||||
### Using the Cluster
|
||||
|
||||
Once the cluster has been allocated, the `func` CLI (or client library) will automatically use it (see the [Kubeconfig Docs](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) for more)
|
||||
|
||||
Functions will be available at the address `[Function Name].default.127.0.0.1.sslip.io`
|
||||
Functions will be available at the address `[Function Name].default.localtest.me`
|
||||
|
||||
To run integration tests, use `make test-integration`.
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
This guide describes how you can build a Function on Cluster with Tekton Pipelines. The on cluster build is enabled by fetching Function source code from a remote Git repository. Buildpacks or S2I builder strategy can be used to build the Function image.
|
||||
|
||||
> **Note**
|
||||
> Not all runtimes support on cluster builds. **Go** and **Rust** are not currently supported.
|
||||
|
||||
## Prerequisite
|
||||
1. Install Tekton Pipelines on the cluster. Please refer to [Tekton Pipelines documentation](https://github.com/tektoncd/pipeline/blob/main/docs/install.md) or run the following command:
|
||||
1. Install Tekton Pipelines on the cluster.
|
||||
|
||||
**Note:** If you're using `./hack/allocate.sh` for development/testing, Tekton and PAC are automatically installed.
|
||||
|
||||
For production environments, please refer to [Tekton Pipelines documentation](https://github.com/tektoncd/pipeline/blob/main/docs/install.md) or run the following command:
|
||||
```bash
|
||||
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.49.0/release.yaml
|
||||
```
|
||||
|
@ -34,12 +35,14 @@ git remote add origin git@github.com:my-repo/my-function.git
|
|||
```
|
||||
4. Update the Function configuration in `func.yaml` to enable on cluster builds for the Git repository:
|
||||
```yaml
|
||||
build: git # required, specify `git` build type
|
||||
git:
|
||||
url: https://github.com/my-repo/my-function.git # required, git repository with the function source code
|
||||
revision: main # optional, git revision to be used (branch, tag, commit)
|
||||
# contextDir: myfunction # optional, needed only if the function is not located
|
||||
# in the repository root folder
|
||||
build:
|
||||
git:
|
||||
url: https://github.com/my-repo/my-function.git # required, git repository with the function source code
|
||||
revision: main # optional, git revision to be used (branch, tag, commit)
|
||||
# contextDir: myfunction # optional, needed only if the function is not located in the repository root folder
|
||||
buildpacks: []
|
||||
builder: ""
|
||||
buildEnvs: []
|
||||
```
|
||||
5. Implement the business logic of your Function, then commit and push changes
|
||||
```bash
|
||||
|
|
|
@ -43,7 +43,7 @@ After the function has been built, it can be run locally.
|
|||
❯ func run
|
||||
```
|
||||
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
You can test to see if the function is working by using your browser to visit
|
||||
http://localhost:8080. You can also access liveness and readiness
|
||||
endpoints at http://localhost:8080/health/liveness and
|
||||
|
@ -69,7 +69,7 @@ You can get the URL for your deployed function with the `info` command.
|
|||
|
||||
|
||||
Go functions can be tested locally on your computer. In the project there is
|
||||
a `handle_test.go` file which contains simple test which can be extended as needed.
|
||||
a `handle_test.go` file which contains simple test which can be extended as needed.
|
||||
Yo can run this test locally as you would do with any Go project.
|
||||
|
||||
```
|
||||
|
@ -79,8 +79,8 @@ Yo can run this test locally as you would do with any Go project.
|
|||
## Function reference
|
||||
|
||||
Boson Go functions have very few restrictions. You can add any required dependencies
|
||||
in `go.mod` and you may include additional local Go files. The only real requirement are
|
||||
that your project is defined in a `function` module and exports the function `Handle()`
|
||||
in `go.mod` and you may include additional local Go files. The only real requirement are
|
||||
that your project is defined in a `function` module and exports the function `Handle()`
|
||||
(supported contracts of this function will be discussed more deeply later).
|
||||
In this section, we will look in a little more detail at how Boson functions are invoked,
|
||||
and what APIs are available to you as a developer.
|
||||
|
@ -94,16 +94,14 @@ They each will listen and respond to incoming HTTP events.
|
|||
|
||||
#### Function triggered by HTTP request
|
||||
|
||||
When an incoming request is received, your function will be invoked with a standard
|
||||
Golang [Context](https://golang.org/pkg/context/) as the first parameter followed by
|
||||
two parameters: Golang's [http.ResponseWriter](https://golang.org/pkg/net/http/#ResponseWriter)
|
||||
and [http.Request](https://golang.org/pkg/net/http/#Request).
|
||||
When an incoming request is received, your function will be invoked with two parameters:
|
||||
Golang's [http.ResponseWriter](https://golang.org/pkg/net/http/#ResponseWriter) and [http.Request](https://golang.org/pkg/net/http/#Request).
|
||||
|
||||
Then you can use standard Golang techniques to access the request (eg. read the body)
|
||||
and set a proper HTTP response of your function, as you can see on the following example:
|
||||
|
||||
```go
|
||||
func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
|
||||
func Handle(res http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// Read body
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
|
@ -141,10 +139,10 @@ Handle(context.Context, cloudevents.Event) *cloudevents.Event
|
|||
Handle(context.Context, cloudevents.Event) (*cloudevents.Event, error)
|
||||
```
|
||||
|
||||
For example, a `CloudEvent` is received which contains a JSON string such as this in its data property,
|
||||
For example, a `CloudEvent` is received which contains a JSON string such as this in its data property,
|
||||
|
||||
```json
|
||||
{
|
||||
{
|
||||
"customerId": "0123456",
|
||||
"productId": "6543210"
|
||||
}
|
||||
|
@ -160,7 +158,7 @@ type Purchase struct {
|
|||
}
|
||||
|
||||
func Handle(ctx context.Context, event cloudevents.Event) err error {
|
||||
|
||||
|
||||
purchase := &Purchase{}
|
||||
if err = cloudevents.DataAs(purchase); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to parse incoming CloudEvent %s\n", err)
|
||||
|
|
|
@ -44,7 +44,7 @@ After the function has been built, it can be run locally.
|
|||
❯ func run
|
||||
```
|
||||
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
You can test to see if the function is working by using your browser to visit
|
||||
http://localhost:8080. You can also access liveness and readiness
|
||||
endpoints at http://localhost:8080/health/liveness and
|
||||
|
@ -108,7 +108,7 @@ parameter. For example, a `CloudEvent` is received which contains a
|
|||
JSON string such as this in its data property,
|
||||
|
||||
```json
|
||||
{
|
||||
{
|
||||
"customerId": "0123456",
|
||||
"productId": "6543210"
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ extracted and sent with the response to the caller.
|
|||
function processCustomer(customer) {
|
||||
// process customer and return custom headers
|
||||
// the response will be '204 No content'
|
||||
return { headers: { customerid: customer.id } };
|
||||
return { headers: { customerid: customer.id } };
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -168,7 +168,7 @@ function processCustomer(customer) {
|
|||
// process customer
|
||||
if (customer.restricted) {
|
||||
return { statusCode: 451 }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,7 +182,7 @@ function processCustomer(customer) {
|
|||
const err = new Error(‘Unavailable for legal reasons’);
|
||||
err.statusCode = 451;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -214,7 +214,7 @@ Access the function via `curl` to invoke it.
|
|||
curl http://example.com
|
||||
```
|
||||
|
||||
The function will log
|
||||
The function will log
|
||||
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"Processing customer"}
|
||||
|
@ -223,7 +223,7 @@ The function will log
|
|||
Developers can control the log level by setting the `logLevel` value in
|
||||
`func.yaml` The possible options for this adhere to the options available
|
||||
for [`pino`](https://getpino.io/#/docs/api?id=level-string),
|
||||
and may be one of
|
||||
and may be one of
|
||||
`'fatal'`, `'error'`, `'warn'`, `'info'`, `'debug'`, `'trace'` or `'silent'`.
|
||||
|
||||
To temporarily override this value, set the environment variable `FUNC_LOG_LEVEL`
|
||||
|
@ -249,7 +249,7 @@ Access the function via `curl` to invoke it.
|
|||
```sh
|
||||
curl http://example.com?name=tiger
|
||||
```
|
||||
The function will log
|
||||
The function will log
|
||||
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"tiger"}
|
||||
|
@ -274,7 +274,7 @@ Access the function via `curl` to invoke it.
|
|||
curl -X POST -d '{"hello": "world"}' -H'Content-type: application/json' http://example.com
|
||||
```
|
||||
|
||||
The function will log
|
||||
The function will log
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"world"}
|
||||
```
|
||||
|
@ -293,7 +293,7 @@ Access the function via `curl` to invoke it.
|
|||
```console
|
||||
curl -H'x-custom-header: some-value’' http://example.com
|
||||
```
|
||||
The function will log
|
||||
The function will log
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"some-value"}
|
||||
```
|
||||
|
|
|
@ -1,160 +1,379 @@
|
|||
# Python Function Developer's Guide
|
||||
|
||||
When creating a Python function using the `func` CLI, the project directory
|
||||
looks like a typical Python project. Both HTTP and Event functions have the same
|
||||
template structure.
|
||||
Python Functions allow for the direct deployment of source code as a production
|
||||
service to any Kubernetes cluster with Knative installed. The request handler
|
||||
method signature follows the ASGI (Asynchronous Server Gateway Interface)
|
||||
standard, allowing for integration with any supporting library.
|
||||
|
||||
## Project Structure
|
||||
|
||||
When you create a Python function using `func create -l python`, you get a standard Python project structure:
|
||||
|
||||
```
|
||||
❯ func create -l python fn
|
||||
Project path: /home/developer/src/fn
|
||||
Function name: fn
|
||||
Runtime: python
|
||||
|
||||
❯ tree
|
||||
fn
|
||||
├── func.py
|
||||
├── func.yaml
|
||||
├── requirements.txt
|
||||
└── test_func.py
|
||||
|
||||
❯ func create -l python myfunc
|
||||
❯ tree myfunc
|
||||
myfunc/
|
||||
├── func.yaml # Function configuration
|
||||
├── pyproject.toml # Python project metadata
|
||||
├── function/
|
||||
│ ├── __init__.py
|
||||
│ └── func.py # Your function implementation
|
||||
└── tests/
|
||||
└── test_func.py # Unit tests
|
||||
```
|
||||
|
||||
Aside from the `func.yaml` file, this looks like the beginning of just about
|
||||
any Python project. For now, we will ignore the `func.yaml` file, and just
|
||||
say that it is a configuration file that is used when building your project.
|
||||
If you're really interested, check out the [reference doc](../reference/func_yaml.md).
|
||||
To learn more about the CLI and the details for each supported command, see
|
||||
the [CLI Commands document](../reference/func.md).
|
||||
The `func.yaml` file contains build and deployment configuration. For details,
|
||||
see the [func.yaml reference](../reference/func_yaml.md).
|
||||
|
||||
## Running the function locally
|
||||
## Function Implementation
|
||||
|
||||
To run a function, you'll first need to build it. This step creates an OCI
|
||||
container image that can be run locally on your computer, or on a Kubernetes
|
||||
cluster.
|
||||
|
||||
```
|
||||
❯ func build
|
||||
```
|
||||
|
||||
After the function has been built, it can be run locally.
|
||||
|
||||
```
|
||||
❯ func run
|
||||
```
|
||||
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
You can test to see if the function is working by using your browser to visit
|
||||
http://localhost:8080. You can also access liveness and readiness
|
||||
endpoints at http://localhost:8080/health/liveness and
|
||||
http://localhost:8080/health/readiness. These two endpoints are used
|
||||
by Kubernetes to determine the health of your function. If everything
|
||||
is good, both of these will return `OK`.
|
||||
|
||||
## Deploying the function to a cluster
|
||||
|
||||
To deploy your function to a Kubernetes cluster, use the `deploy` command.
|
||||
|
||||
```
|
||||
❯ func deploy
|
||||
```
|
||||
|
||||
You can get the URL for your deployed function with the `info` command.
|
||||
|
||||
```
|
||||
❯ func info
|
||||
```
|
||||
|
||||
## Testing a function locally
|
||||
|
||||
|
||||
Python functions can be tested locally on your computer. In the project there is
|
||||
a `test_func.py` file which contains a simple unit test. To run the test locally,
|
||||
you'll need to install the required dependencies. You do this as you would
|
||||
with any Python project.
|
||||
|
||||
```
|
||||
❯ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Once you have done this, you can run the provided tests with `python3 test_func.py`.
|
||||
The default test framework for Python functions is `unittest`. If you prefer another,
|
||||
that's no problem. Just install a test framework more to your liking.
|
||||
|
||||
## Function reference
|
||||
|
||||
Boson Python functions have very few restrictions. You can add any required dependencies
|
||||
in `requirements.txt`, and you may include additional local Python files. The only real
|
||||
requirements are that your project contain a `func.py` file which contains a `main()` function.
|
||||
In this section, we will look in a little more detail at how Boson functions are invoked,
|
||||
and what APIs are available to you as a developer.
|
||||
|
||||
### Invocation parameters
|
||||
|
||||
When using the `func` CLI to create a function project, you may choose to generate a project
|
||||
that responds to a `CloudEvent` or simple HTTP. `CloudEvents` in Knative are transported over
|
||||
HTTP as a `POST` request, so in many ways, the two types of functions are very much the same.
|
||||
They each will listen and respond to incoming HTTP events.
|
||||
|
||||
When an incoming request is received, your function will be invoked with a `Context`
|
||||
object as the first parameter. This object is a Python class with two attributes. The
|
||||
`request` attribute will always be present, and contains the Flask `request` object.
|
||||
The second attribute, `cloud_event`, will be populated if the incoming request is a
|
||||
`CloudEvent`. Developers may access any `CloudEvent` data from the context object.
|
||||
For example:
|
||||
Python functions must implement a method `new()` which returns a new instance
|
||||
of your Function class:
|
||||
|
||||
```python
|
||||
def main(context: Context):
|
||||
"""
|
||||
The context parameter contains the Flask request object and any
|
||||
CloudEvent received with the request.
|
||||
"""
|
||||
print(f"Method: {context.request.method}")
|
||||
print(f"Event data {context.cloud_event.data})
|
||||
# ... business logic here
|
||||
def new():
|
||||
"""Factory function that returns a Function instance."""
|
||||
return Function()
|
||||
|
||||
class Function:
|
||||
"""Your function implementation."""
|
||||
pass
|
||||
```
|
||||
|
||||
### Return Values
|
||||
Functions may return any value supported by Flask, as the invocation framework
|
||||
proxies these values directly to the Flask server. See the Flask
|
||||
[documentation](https://flask.palletsprojects.com/en/1.1.x/quickstart/#about-responses)
|
||||
for more information.
|
||||
### Core Methods
|
||||
|
||||
#### Example
|
||||
```python
|
||||
def main(context: Context):
|
||||
body = { "message": "Howdy!" }
|
||||
headers = { "content-type": "application/json" }
|
||||
return body, 200, headers
|
||||
```
|
||||
Your function class can implement several optional methods:
|
||||
|
||||
Note that functions may set both headers and response codes as secondary
|
||||
and tertiary response values from function invocation.
|
||||
|
||||
### CloudEvents
|
||||
All event messages in Knative are sent as `CloudEvents` over HTTP. As noted
|
||||
above, function developers may access an event through the `context` parameter
|
||||
when the function is invoked. Additionally, developers may use an `@event`
|
||||
decorator to inform the invoker that this function's return value should be
|
||||
converted to a `CloudEvent` before sending the response. For example:
|
||||
#### `handle(self, scope, receive, send)`
|
||||
The main request handler following ASGI protocol. This async method processes all HTTP requests except health checks.
|
||||
|
||||
```python
|
||||
@event("event_source"="/my/function", "event_type"="my.type")
|
||||
def main(context):
|
||||
# business logic here
|
||||
data = do_something()
|
||||
# more data processing
|
||||
return data
|
||||
async def handle(self, scope, receive, send):
|
||||
"""Handle HTTP requests."""
|
||||
# Process the request
|
||||
await send({
|
||||
'type': 'http.response.start',
|
||||
'status': 200,
|
||||
'headers': [[b'content-type', b'text/plain']],
|
||||
})
|
||||
await send({
|
||||
'type': 'http.response.body',
|
||||
'body': b'Hello, World!',
|
||||
})
|
||||
```
|
||||
|
||||
This will result in a `CloudEvent` as the response value, with a type of
|
||||
`"my.type"`, a source of `"/my/function"`, and the data property set to `data`.
|
||||
Both the `event_source` and `event_type` decorator attributes are optional.
|
||||
If not supplied, the CloudEvent's source attribute will be set to
|
||||
`"/parliament/function"` and the type will be set to `"parliament.response"`.
|
||||
#### `start(self, cfg)`
|
||||
|
||||
## Dependencies
|
||||
Developers are not restricted to the dependencies provided in the template
|
||||
`requirements.txt` file. Additional dependencies can be added as they would be
|
||||
in any other project by simply adding them to the `requirements.txt` file.
|
||||
When the project is built for deployment, these dependencies will be included
|
||||
in the container image.
|
||||
Called when a function instance starts (e.g., during scaling or updates). Receives configuration as a dictionary.
|
||||
|
||||
```python
|
||||
def start(self, cfg):
|
||||
"""Initialize function with configuration."""
|
||||
self.debug = cfg.get('DEBUG', 'false').lower() == 'true'
|
||||
logging.info("Function initialized")
|
||||
```
|
||||
|
||||
#### `stop(self)`
|
||||
|
||||
Called when a function instance stops. Use for cleanup operations.
|
||||
|
||||
```python
|
||||
def stop(self):
|
||||
"""Clean up resources."""
|
||||
# Close database connections, flush buffers, etc.
|
||||
logging.info("Function shutting down")
|
||||
```
|
||||
|
||||
#### `alive(self)` and `ready(self)`
|
||||
|
||||
Health check methods exposed at `/health/liveness` and `/health/readiness`:
|
||||
|
||||
```python
|
||||
def alive(self):
|
||||
"""Liveness check."""
|
||||
return True, "Function is alive"
|
||||
|
||||
def ready(self):
|
||||
"""Readiness check."""
|
||||
if self.database_connected:
|
||||
return True, "Ready to serve"
|
||||
return False, "Database not connected"
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
### Running Your Function
|
||||
|
||||
```bash
|
||||
# Build and run on the host (not in a container)
|
||||
func run --builder=host
|
||||
|
||||
# Force rebuild even if no changes detected
|
||||
func run --build
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
Test your function with HTTP requests:
|
||||
|
||||
```bash
|
||||
# Test the main endpoint
|
||||
curl http://localhost:8080
|
||||
|
||||
# Check health endpoints
|
||||
curl http://localhost:8080/health/liveness
|
||||
curl http://localhost:8080/health/readiness
|
||||
```
|
||||
|
||||
### Testing CloudEvent Functions
|
||||
|
||||
Create a CloudEvent function:
|
||||
|
||||
```bash
|
||||
# Create a new CloudEvent function
|
||||
func create -l python -t cloudevents myeventfunc
|
||||
```
|
||||
|
||||
Test CloudEvent functions using curl with proper headers:
|
||||
|
||||
```bash
|
||||
# Invoke with a CloudEvent
|
||||
curl -X POST http://localhost:8080 \
|
||||
-H "Ce-Specversion: 1.0" \
|
||||
-H "Ce-Type: com.example.sampletype" \
|
||||
-H "Ce-Source: example/source" \
|
||||
-H "Ce-Id: 1234-5678-9101" \
|
||||
-H "Ce-Subject: example-subject" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"message": "Hello CloudEvent!"}'
|
||||
```
|
||||
|
||||
Also see `func invoke` which automates this for basic testing.
|
||||
|
||||
### Unit Testing
|
||||
|
||||
Python functions use modern Python packaging with `pyproject.toml` and include
|
||||
pytest with async support for testing ASGI functions. The generated project
|
||||
includes example tests in `tests/test_func.py` that demonstrate how to test the
|
||||
async handler.
|
||||
|
||||
#### Setting Up Your Development Environment
|
||||
|
||||
It's best practice to use a virtual environment to isolate your function's dependencies:
|
||||
|
||||
```bash
|
||||
# Create a virtual environment (Python 3.3+)
|
||||
python3 -m venv venv
|
||||
|
||||
# Activate the virtual environment
|
||||
# On Linux/macOS:
|
||||
source venv/bin/activate
|
||||
# On Windows:
|
||||
# venv\Scripts\activate
|
||||
|
||||
# Upgrade pip to ensure you have the latest version
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
# Install the function package and its dependencies (including test dependencies)
|
||||
pip install -e .
|
||||
|
||||
# Run tests with pytest
|
||||
pytest
|
||||
|
||||
# Run tests with verbose output
|
||||
pytest -v
|
||||
|
||||
# Run tests with coverage (requires pytest-cov)
|
||||
pip install pytest-cov
|
||||
pytest --cov=function --cov-report=term-missing
|
||||
|
||||
# When done, deactivate the virtual environment
|
||||
deactivate
|
||||
```
|
||||
|
||||
**Note**:
|
||||
- Python 3 typically comes with `venv` module built-in
|
||||
- If `python3` command is not found, try `python` instead
|
||||
- The `-m pip` syntax ensures you're using the pip from your virtual environment
|
||||
- Always activate your virtual environment before running tests or installing dependencies
|
||||
|
||||
#### Writing Tests for ASGI Functions
|
||||
|
||||
The test file demonstrates how to test ASGI functions by mocking the ASGI interface:
|
||||
|
||||
```python
|
||||
import pytest
|
||||
from function import new
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_function_handle():
|
||||
# Create function instance
|
||||
f = new()
|
||||
|
||||
# Mock ASGI scope (request details)
|
||||
scope = {
|
||||
'type': 'http',
|
||||
'method': 'POST',
|
||||
'path': '/',
|
||||
'headers': [(b'content-type', b'application/json')],
|
||||
}
|
||||
|
||||
# Mock receive callable (for request body)
|
||||
async def receive():
|
||||
return {
|
||||
'type': 'http.request',
|
||||
'body': b'{"test": "data"}',
|
||||
'more_body': False,
|
||||
}
|
||||
|
||||
# Track sent responses
|
||||
responses = []
|
||||
|
||||
# Mock send callable
|
||||
async def send(message):
|
||||
responses.append(message)
|
||||
|
||||
# Call the handler
|
||||
await f.handle(scope, receive, send)
|
||||
|
||||
# Assert responses
|
||||
assert len(responses) == 2
|
||||
assert responses[0]['type'] == 'http.response.start'
|
||||
assert responses[0]['status'] == 200
|
||||
assert responses[1]['type'] == 'http.response.body'
|
||||
```
|
||||
|
||||
#### Testing CloudEvent Functions
|
||||
|
||||
For CloudEvent functions, include CloudEvent headers in your test scope:
|
||||
|
||||
```python
|
||||
@pytest.mark.asyncio
|
||||
async def test_cloudevent_handler():
|
||||
f = new()
|
||||
|
||||
# CloudEvent headers
|
||||
scope = {
|
||||
'type': 'http',
|
||||
'method': 'POST',
|
||||
'path': '/',
|
||||
'headers': [
|
||||
(b'ce-specversion', b'1.0'),
|
||||
(b'ce-type', b'com.example.test'),
|
||||
(b'ce-source', b'test/unit'),
|
||||
(b'ce-id', b'test-123'),
|
||||
(b'content-type', b'application/json'),
|
||||
],
|
||||
}
|
||||
|
||||
# Test with CloudEvent data
|
||||
async def receive():
|
||||
return {
|
||||
'type': 'http.request',
|
||||
'body': b'{"message": "test event"}',
|
||||
'more_body': False,
|
||||
}
|
||||
|
||||
# ... rest of test
|
||||
```
|
||||
|
||||
#### Testing with Real HTTP Clients
|
||||
|
||||
For integration testing, you can use httpx with ASGI support:
|
||||
|
||||
```python
|
||||
import httpx
|
||||
import pytest
|
||||
from function import new
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_with_http_client():
|
||||
f = new()
|
||||
|
||||
# Create ASGI transport with your function
|
||||
transport = httpx.ASGITransport(app=f.handle)
|
||||
|
||||
# Make HTTP requests
|
||||
async with httpx.AsyncClient(transport=transport, base_url="http://test") as client:
|
||||
response = await client.get("/")
|
||||
assert response.status_code == 200
|
||||
|
||||
response = await client.post("/", json={"test": "data"})
|
||||
assert response.status_code == 200
|
||||
```
|
||||
|
||||
## Advanced Implementation Examples
|
||||
|
||||
### Processing Request Data
|
||||
|
||||
```python
|
||||
async def handle(self, scope, receive, send):
|
||||
"""Process POST requests with JSON data."""
|
||||
if scope['method'] == 'POST':
|
||||
# Receive request body
|
||||
body = b''
|
||||
while True:
|
||||
message = await receive()
|
||||
if message['type'] == 'http.request':
|
||||
body += message.get('body', b'')
|
||||
if not message.get('more_body', False):
|
||||
break
|
||||
|
||||
# Process JSON data
|
||||
import json
|
||||
data = json.loads(body)
|
||||
result = process_data(data)
|
||||
|
||||
# Send response
|
||||
response_body = json.dumps(result).encode()
|
||||
await send({
|
||||
'type': 'http.response.start',
|
||||
'status': 200,
|
||||
'headers': [[b'content-type', b'application/json']],
|
||||
})
|
||||
await send({
|
||||
'type': 'http.response.body',
|
||||
'body': response_body,
|
||||
})
|
||||
```
|
||||
|
||||
### Environment-Based Configuration
|
||||
|
||||
```python
|
||||
class Function:
|
||||
def start(self, cfg):
|
||||
"""Configure function from environment."""
|
||||
self.api_key = cfg.get('API_KEY')
|
||||
self.cache_ttl = int(cfg.get('CACHE_TTL', '300'))
|
||||
self.log_level = cfg.get('LOG_LEVEL', 'INFO')
|
||||
|
||||
logging.basicConfig(level=self.log_level)
|
||||
```
|
||||
|
||||
### CloudEvent Handling
|
||||
|
||||
For CloudEvent support, parse the headers and body accordingly:
|
||||
|
||||
```python
|
||||
async def handle(self, scope, receive, send):
|
||||
"""Handle CloudEvents."""
|
||||
headers = dict(scope['headers'])
|
||||
|
||||
# Check if this is a CloudEvent
|
||||
if b'ce-type' in headers:
|
||||
event_type = headers[b'ce-type'].decode()
|
||||
event_source = headers[b'ce-source'].decode()
|
||||
# Process CloudEvent...
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Basic Deployment
|
||||
|
||||
```bash
|
||||
# Deploy to a specific registry
|
||||
func deploy --builder=host --registry docker.io/myuser
|
||||
```
|
||||
|
||||
|
||||
For all deploy options, see `func deploy --help`
|
||||
|
|
|
@ -10,7 +10,7 @@ Project path: /home/developer/projects/fn
|
|||
Function name: fn
|
||||
Runtime: quarkus
|
||||
|
||||
❯ tree
|
||||
❯ tree
|
||||
fn
|
||||
├── func.yaml
|
||||
├── mvnw
|
||||
|
@ -56,7 +56,7 @@ After the function has been built, it can be run locally.
|
|||
❯ func run
|
||||
```
|
||||
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
You can test to see if the function is working by using your browser to visit
|
||||
http://localhost:8080.
|
||||
|
||||
|
@ -150,7 +150,7 @@ then the object you return will be sent in the `data` property of a binary encod
|
|||
|
||||
If the function received vanilla HTTP,
|
||||
then the object you return will be sent as the HTTP response body. In the example below, an invocation of this function
|
||||
through an incoming `CloudEvent`, will receive a response with a `CloudEvent` containing a list of purchases as its
|
||||
through an incoming `CloudEvent`, will receive a response with a `CloudEvent` containing a list of purchases as its
|
||||
`data` property. If the invocation was via an ordinary HTTP request, the response will contain the same list of purchases
|
||||
in the HTTP response body, but no `CloudEvent` headers will be included.
|
||||
|
||||
|
@ -197,14 +197,14 @@ Note that the type parameter of `CloudEvent<T>` must satisfy the conditions desc
|
|||
#### Example
|
||||
```java
|
||||
public class Functions {
|
||||
|
||||
|
||||
private boolean _processPurchase(Purchase purchase) {
|
||||
// do stuff
|
||||
}
|
||||
|
||||
|
||||
public CloudEvent<Void> processPurchase(CloudEvent<Purchase> purchaseEvent) {
|
||||
System.out.println("subject is: ", purchaseEvent.subject());
|
||||
|
||||
|
||||
if (!_processPurchase(purchaseEvent.data())) {
|
||||
return CloudEventBuilder.create()
|
||||
.type("purchase.error")
|
||||
|
|
|
@ -47,7 +47,7 @@ After the function has been built, it can be run locally.
|
|||
❯ func run
|
||||
```
|
||||
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
Functions can be invoked with a simple HTTP request.
|
||||
You can test to see if the function is working by using your browser to visit
|
||||
http://localhost:8080. You can also access liveness and readiness
|
||||
endpoints at http://localhost:8080/health/liveness and
|
||||
|
@ -136,7 +136,7 @@ function handle(context: Context, cloudevent?: CloudEvent): Record<string, strin
|
|||
// process customer and return custom headers
|
||||
// the response will be '204 No content'
|
||||
const customer = cloudevent.data;
|
||||
return { headers: { "customer-id": customer.id } };
|
||||
return { headers: { "customer-id": customer.id } };
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -147,10 +147,10 @@ Developers may set the response code returned to the caller by adding a
|
|||
#### Example
|
||||
```js
|
||||
function handle(context: Context, cloudevent?: CloudEvent): Record<string, string> {
|
||||
// process customer
|
||||
// process customer
|
||||
const customer = cloudevent.data;
|
||||
if (customer.restricted) {
|
||||
return {
|
||||
return {
|
||||
statusCode: 451
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ function handle(context: Context, cloudevent?: CloudEvent) Record<string, string
|
|||
const err = new Error(‘Unavailable for legal reasons’);
|
||||
err.statusCode = 451;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -204,7 +204,7 @@ Access the function via `curl` to invoke it.
|
|||
curl http://example.com
|
||||
```
|
||||
|
||||
The function will log
|
||||
The function will log
|
||||
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"Processing customer"}
|
||||
|
@ -230,7 +230,7 @@ Access the function via `curl` to invoke it.
|
|||
```sh
|
||||
curl "http://example.com?name=tiger"
|
||||
```
|
||||
The function will log
|
||||
The function will log
|
||||
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"tiger"}
|
||||
|
@ -256,7 +256,7 @@ Access the function via `curl` to invoke it.
|
|||
curl -X POST -d '{"hello": "world"}' -H'Content-type: application/json' http://example.com
|
||||
```
|
||||
|
||||
The function will log
|
||||
The function will log
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"world"}
|
||||
```
|
||||
|
@ -276,7 +276,7 @@ Access the function via `curl` to invoke it.
|
|||
```console
|
||||
curl -H'x-custom-header: some-value’' http://example.com
|
||||
```
|
||||
The function will log
|
||||
The function will log
|
||||
```console
|
||||
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"some-value"}
|
||||
```
|
||||
|
|
|
@ -21,7 +21,7 @@ var (
|
|||
fm = template.FuncMap{
|
||||
"indent": func(i int, c string, v string) string {
|
||||
indentation := strings.Repeat(c, i)
|
||||
return indentation + strings.Replace(v, "\n", "\n"+indentation, -1)
|
||||
return indentation + strings.ReplaceAll(v, "\n", "\n"+indentation)
|
||||
},
|
||||
"rootCmdUse": func() string {
|
||||
return rootName
|
||||
|
@ -96,6 +96,9 @@ func ignoreConfigEnv() (done func()) {
|
|||
// string to the file name, and recursively calls itself for each subcommand.
|
||||
func processSubCommands(c *cobra.Command, parent string, opts TemplateOptions) error {
|
||||
for _, cc := range c.Commands() {
|
||||
if cc.Hidden {
|
||||
continue
|
||||
}
|
||||
name := cc.Name()
|
||||
if name == "help" {
|
||||
continue
|
||||
|
|
|
@ -137,7 +137,7 @@ Built in to the Functions library are Language Packs for Go, Node.js, Python, Qu
|
|||
Language Packs are distributed as a set of templates for one or more languages via Git repositories, and installed by the developer locally using the `func` CLI.
|
||||
|
||||
```
|
||||
func repository add func https://github.com/knative-sandbox/func-tastic
|
||||
func repository add func https://github.com/knative-extensions/func-tastic
|
||||
func create -l go -t func/hello-world
|
||||
```
|
||||
|
||||
|
@ -190,7 +190,7 @@ When `func create` is used to generate a Function project, the Language Pack pro
|
|||
Using external Language Packs is made possible through the `func repository` command, which allows Function developers to add and remove Language Packs from their local development environment. For example:
|
||||
|
||||
```
|
||||
❯ func repository add https://github.com/knative-sandbox/func-tastic functastic # Add the func-tastic repo to the local environment
|
||||
❯ func repository add https://github.com/knative-extensions/func-tastic functastic # Add the func-tastic repo to the local environment
|
||||
❯ func repo list # list repos
|
||||
default
|
||||
functastic
|
||||
|
|
|
@ -8,11 +8,11 @@ To make use of more complex initial function implementions, or to define runtime
|
|||
|
||||
## External Git Repositories
|
||||
|
||||
When creating a new function, a Git repository can be specified as the source for the template files. For example, the the [knative-sandbox/func-tastic repository](https://github.com/knative-sandbox/func-tastic) contains a set of example functions which can be used during project creation.
|
||||
When creating a new function, a Git repository can be specified as the source for the template files. For example, the the [knative-extensions/func-tastic repository](https://github.com/knative-extensions/func-tastic) contains a set of example functions which can be used during project creation.
|
||||
|
||||
For example, the func-tastic repository contains an example ["metacontroller"](https://metacontroller.github.io/metacontroller) function implementation for Node.js. To use this template via the CLI, use the flags:
|
||||
|
||||
func create <name> --template metacontroller --repository https://github.com/knative-sandbox/func-tastic
|
||||
func create <name> --template metacontroller --repository https://github.com/knative-extensions/func-tastic
|
||||
|
||||
## Locally Installing Repositories
|
||||
|
||||
|
@ -21,7 +21,7 @@ Template repositories can also be installed locally by placing them in the funct
|
|||
To install the func-tastic templates locally, for example, use the `func repository add` command:
|
||||
|
||||
```
|
||||
func repository add https://github.com/knative-sandbox/func-tastic
|
||||
func repository add https://github.com/knative-extensions/func-tastic
|
||||
```
|
||||
|
||||
Once installed, the metacontroller template can be specified:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue