mirror of
				https://github.com/siderolabs/talos.git
				synced 2025-10-31 00:11:36 +01:00 
			
		
		
		
	feat: implement machine config documents for event and log streaming
Fixes #7228 Add some changes to make Talos accept partial machine configuration without main v1alpha1 config. With this change, it's possible to connect a machine already running with machine configuration (v1alpha1), the following patch will connect to a local SideroLink endpoint: ```yaml apiVersion: v1alpha1 kind: SideroLinkConfig apiUrl: grpc://172.20.0.1:4000/?jointoken=foo --- apiVersion: v1alpha1 kind: KmsgLogConfig name: apiSink url: tcp://[fdae:41e4:649b:9303::1]:4001/ --- apiVersion: v1alpha1 kind: EventSinkConfig endpoint: "[fdae:41e4:649b:9303::1]:8080" ``` Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
		
							parent
							
								
									e241be85ba
								
							
						
					
					
						commit
						6be5a13d5d
					
				
							
								
								
									
										11
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								go.sum
									
									
									
									
									
								
							| @ -235,7 +235,6 @@ github.com/Microsoft/hcsshim v0.9.9/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfy | |||||||
| github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= | github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= | ||||||
| github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= | github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= | ||||||
| github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= | ||||||
| github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= |  | ||||||
| github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= | ||||||
| github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= | github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= | ||||||
| github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek= | github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek= | ||||||
| @ -538,7 +537,6 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv | |||||||
| github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||||
| github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= | github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= | ||||||
| github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= | github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= | ||||||
| github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= |  | ||||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||||
| github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= | github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= | ||||||
| github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= | github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= | ||||||
| @ -577,7 +575,6 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb | |||||||
| github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | ||||||
| github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | ||||||
| github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= | ||||||
| github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= |  | ||||||
| github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= | ||||||
| github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= | github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= | ||||||
| github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | ||||||
| @ -795,7 +792,6 @@ github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhE | |||||||
| github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= | github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= | ||||||
| github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||||
| github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= | github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= | ||||||
| github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= |  | ||||||
| github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= | github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= | ||||||
| github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= | github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= | ||||||
| github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||||
| @ -810,7 +806,6 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq | |||||||
| github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= | github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= | ||||||
| github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | ||||||
| github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8= | github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8= | ||||||
| github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= |  | ||||||
| github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | ||||||
| github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | ||||||
| github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | ||||||
| @ -842,7 +837,6 @@ github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2C | |||||||
| github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= | github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= | ||||||
| github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= | github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= | ||||||
| github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= | github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= | ||||||
| github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= |  | ||||||
| github.com/jsimonetti/rtnetlink v1.3.3 h1:ycpm3z8XlAzmaacVRjdUT3x6MM1o3YBXsXc7DXSRNCE= | github.com/jsimonetti/rtnetlink v1.3.3 h1:ycpm3z8XlAzmaacVRjdUT3x6MM1o3YBXsXc7DXSRNCE= | ||||||
| github.com/jsimonetti/rtnetlink v1.3.3/go.mod h1:mW4xSP3wkiqWxHMlfG/gOufp3XnhAxu7EhfABmrWSh8= | github.com/jsimonetti/rtnetlink v1.3.3/go.mod h1:mW4xSP3wkiqWxHMlfG/gOufp3XnhAxu7EhfABmrWSh8= | ||||||
| github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | ||||||
| @ -854,7 +848,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 | |||||||
| github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= | ||||||
| github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | ||||||
| github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= | ||||||
| github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= |  | ||||||
| github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw= | github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw= | ||||||
| github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc= | github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc= | ||||||
| github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | ||||||
| @ -933,7 +926,6 @@ github.com/mdlayher/netx v0.0.0-20230430222610-7e21880baee8/go.mod h1:qhZhwMDNWw | |||||||
| github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU= | github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU= | ||||||
| github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY= | github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY= | ||||||
| github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4= | github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4= | ||||||
| github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= |  | ||||||
| github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E= | github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E= | ||||||
| github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= | github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= | ||||||
| github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= | github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= | ||||||
| @ -982,7 +974,6 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m | |||||||
| github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= | ||||||
| github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= | ||||||
| github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= | ||||||
| github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= |  | ||||||
| github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= | ||||||
| github.com/nberlee/go-netstat v0.1.2 h1:wgPV1YOUo+kDFypqiKgfxMtnSs1Wb42c7ahI4qyEUJc= | github.com/nberlee/go-netstat v0.1.2 h1:wgPV1YOUo+kDFypqiKgfxMtnSs1Wb42c7ahI4qyEUJc= | ||||||
| github.com/nberlee/go-netstat v0.1.2/go.mod h1:GvDCRLsUKMRN1wULkt7tpnDmjSIE6YGf5zeVq+mBO64= | github.com/nberlee/go-netstat v0.1.2/go.mod h1:GvDCRLsUKMRN1wULkt7tpnDmjSIE6YGf5zeVq+mBO64= | ||||||
| @ -1210,9 +1201,7 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0 | |||||||
| github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | ||||||
| github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | ||||||
| github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | ||||||
| github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= |  | ||||||
| github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= | ||||||
| github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= |  | ||||||
| github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= | ||||||
| github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= | ||||||
| github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= | ||||||
|  | |||||||
| @ -11,10 +11,12 @@ import ( | |||||||
| 	"github.com/cosi-project/runtime/pkg/controller" | 	"github.com/cosi-project/runtime/pkg/controller" | ||||||
| 	"github.com/cosi-project/runtime/pkg/safe" | 	"github.com/cosi-project/runtime/pkg/safe" | ||||||
| 	"github.com/cosi-project/runtime/pkg/state" | 	"github.com/cosi-project/runtime/pkg/state" | ||||||
|  | 	"github.com/siderolabs/go-pointer" | ||||||
| 	"github.com/siderolabs/go-procfs/procfs" | 	"github.com/siderolabs/go-procfs/procfs" | ||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| 
 | 
 | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/constants" | 	"github.com/siderolabs/talos/pkg/machinery/constants" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/resources/config" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -30,7 +32,14 @@ func (ctrl *EventsSinkConfigController) Name() string { | |||||||
| 
 | 
 | ||||||
| // Inputs implements controller.Controller interface. | // Inputs implements controller.Controller interface. | ||||||
| func (ctrl *EventsSinkConfigController) Inputs() []controller.Input { | func (ctrl *EventsSinkConfigController) Inputs() []controller.Input { | ||||||
| 	return nil | 	return []controller.Input{ | ||||||
|  | 		{ | ||||||
|  | 			Namespace: config.NamespaceName, | ||||||
|  | 			Type:      config.MachineConfigType, | ||||||
|  | 			ID:        pointer.To(config.V1Alpha1ID), | ||||||
|  | 			Kind:      controller.InputWeak, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Outputs implements controller.Controller interface. | // Outputs implements controller.Controller interface. | ||||||
| @ -62,6 +71,15 @@ func (ctrl *EventsSinkConfigController) Run(ctx context.Context, r controller.Ru | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		cfg, err := safe.ReaderGetByID[*config.MachineConfig](ctx, r, config.V1Alpha1ID) | ||||||
|  | 		if err != nil && !state.IsNotFoundError(err) { | ||||||
|  | 			return fmt.Errorf("error getting machine config: %w", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if cfg != nil && cfg.Config().Runtime().EventsEndpoint() != nil { | ||||||
|  | 			endpoint = *cfg.Config().Runtime().EventsEndpoint() | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if endpoint == "" { | 		if endpoint == "" { | ||||||
| 			if err := r.Destroy(ctx, runtime.NewEventSinkConfig().Metadata()); err != nil && !state.IsNotFoundError(err) { | 			if err := r.Destroy(ctx, runtime.NewEventSinkConfig().Metadata()); err != nil && !state.IsNotFoundError(err) { | ||||||
| 				return fmt.Errorf("error destroying event sink config: %w", err) | 				return fmt.Errorf("error destroying event sink config: %w", err) | ||||||
|  | |||||||
| @ -15,7 +15,10 @@ import ( | |||||||
| 
 | 
 | ||||||
| 	"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" | 	"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" | ||||||
| 	runtimectrls "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/runtime" | 	runtimectrls "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/runtime" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/container" | ||||||
|  | 	runtimecfg "github.com/siderolabs/talos/pkg/machinery/config/types/runtime" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/constants" | 	"github.com/siderolabs/talos/pkg/machinery/constants" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/resources/config" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -33,10 +36,36 @@ func (suite *EventsSinkConfigSuite) TestEventSinkConfigNone() { | |||||||
| 	rtestutils.AssertNoResource[*runtime.EventSinkConfig](suite.Ctx(), suite.T(), suite.State(), runtime.EventSinkConfigID) | 	rtestutils.AssertNoResource[*runtime.EventSinkConfig](suite.Ctx(), suite.T(), suite.State(), runtime.EventSinkConfigID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *EventsSinkConfigSuite) TestEventSinkConfigMachineConfig() { | ||||||
|  | 	suite.Require().NoError(suite.Runtime().RegisterController(&runtimectrls.EventsSinkConfigController{})) | ||||||
|  | 
 | ||||||
|  | 	eventSinkConfig := &runtimecfg.EventSinkV1Alpha1{ | ||||||
|  | 		Endpoint: "10.0.0.2:4444", | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cfg, err := container.New(eventSinkConfig) | ||||||
|  | 	suite.Require().NoError(err) | ||||||
|  | 
 | ||||||
|  | 	suite.Require().NoError(suite.State().Create(suite.Ctx(), config.NewMachineConfig(cfg))) | ||||||
|  | 
 | ||||||
|  | 	rtestutils.AssertResources[*runtime.EventSinkConfig](suite.Ctx(), suite.T(), suite.State(), []resource.ID{runtime.EventSinkConfigID}, | ||||||
|  | 		func(cfg *runtime.EventSinkConfig, asrt *assert.Assertions) { | ||||||
|  | 			asrt.Equal( | ||||||
|  | 				"10.0.0.2:4444", | ||||||
|  | 				cfg.TypedSpec().Endpoint, | ||||||
|  | 			) | ||||||
|  | 		}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (suite *EventsSinkConfigSuite) TestEventSinkConfigCmdline() { | func (suite *EventsSinkConfigSuite) TestEventSinkConfigCmdline() { | ||||||
| 	cmdline := procfs.NewCmdline("") | 	cmdline := procfs.NewCmdline("") | ||||||
| 	cmdline.Append(constants.KernelParamEventsSink, "10.0.0.1:3333") | 	cmdline.Append(constants.KernelParamEventsSink, "10.0.0.1:3333") | ||||||
| 
 | 
 | ||||||
|  | 	cfg, err := container.New() | ||||||
|  | 	suite.Require().NoError(err) | ||||||
|  | 
 | ||||||
|  | 	suite.Require().NoError(suite.State().Create(suite.Ctx(), config.NewMachineConfig(cfg))) | ||||||
|  | 
 | ||||||
| 	suite.Require().NoError(suite.Runtime().RegisterController(&runtimectrls.EventsSinkConfigController{ | 	suite.Require().NoError(suite.Runtime().RegisterController(&runtimectrls.EventsSinkConfigController{ | ||||||
| 		Cmdline: cmdline, | 		Cmdline: cmdline, | ||||||
| 	})) | 	})) | ||||||
|  | |||||||
| @ -12,10 +12,13 @@ import ( | |||||||
| 	"github.com/cosi-project/runtime/pkg/controller" | 	"github.com/cosi-project/runtime/pkg/controller" | ||||||
| 	"github.com/cosi-project/runtime/pkg/safe" | 	"github.com/cosi-project/runtime/pkg/safe" | ||||||
| 	"github.com/cosi-project/runtime/pkg/state" | 	"github.com/cosi-project/runtime/pkg/state" | ||||||
|  | 	"github.com/siderolabs/gen/slices" | ||||||
|  | 	"github.com/siderolabs/go-pointer" | ||||||
| 	"github.com/siderolabs/go-procfs/procfs" | 	"github.com/siderolabs/go-procfs/procfs" | ||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| 
 | 
 | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/constants" | 	"github.com/siderolabs/talos/pkg/machinery/constants" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/resources/config" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -31,7 +34,14 @@ func (ctrl *KmsgLogConfigController) Name() string { | |||||||
| 
 | 
 | ||||||
| // Inputs implements controller.Controller interface. | // Inputs implements controller.Controller interface. | ||||||
| func (ctrl *KmsgLogConfigController) Inputs() []controller.Input { | func (ctrl *KmsgLogConfigController) Inputs() []controller.Input { | ||||||
| 	return nil | 	return []controller.Input{ | ||||||
|  | 		{ | ||||||
|  | 			Namespace: config.NamespaceName, | ||||||
|  | 			Type:      config.MachineConfigType, | ||||||
|  | 			ID:        pointer.To(config.V1Alpha1ID), | ||||||
|  | 			Kind:      controller.InputWeak, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Outputs implements controller.Controller interface. | // Outputs implements controller.Controller interface. | ||||||
| @ -68,6 +78,21 @@ func (ctrl *KmsgLogConfigController) Run(ctx context.Context, r controller.Runti | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		cfg, err := safe.ReaderGetByID[*config.MachineConfig](ctx, r, config.V1Alpha1ID) | ||||||
|  | 		if err != nil && !state.IsNotFoundError(err) { | ||||||
|  | 			return fmt.Errorf("error getting machine config: %w", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if cfg != nil { | ||||||
|  | 			// remove duplicate URLs in case same destination is specified in both machine config and kernel args | ||||||
|  | 			destinations = append(destinations, slices.Filter(cfg.Config().Runtime().KmsgLogURLs(), | ||||||
|  | 				func(u *url.URL) bool { | ||||||
|  | 					return !slices.Contains(destinations, func(v *url.URL) bool { | ||||||
|  | 						return v.String() == u.String() | ||||||
|  | 					}) | ||||||
|  | 				})...) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if len(destinations) == 0 { | 		if len(destinations) == 0 { | ||||||
| 			if err := r.Destroy(ctx, runtime.NewKmsgLogConfig().Metadata()); err != nil && !state.IsNotFoundError(err) { | 			if err := r.Destroy(ctx, runtime.NewKmsgLogConfig().Metadata()); err != nil && !state.IsNotFoundError(err) { | ||||||
| 				return fmt.Errorf("error destroying kmsg log config: %w", err) | 				return fmt.Errorf("error destroying kmsg log config: %w", err) | ||||||
|  | |||||||
| @ -17,7 +17,11 @@ import ( | |||||||
| 
 | 
 | ||||||
| 	"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" | 	"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" | ||||||
| 	runtimectrls "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/runtime" | 	runtimectrls "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/runtime" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/container" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/types/meta" | ||||||
|  | 	runtimecfg "github.com/siderolabs/talos/pkg/machinery/config/types/runtime" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/constants" | 	"github.com/siderolabs/talos/pkg/machinery/constants" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/resources/config" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | 	"github.com/siderolabs/talos/pkg/machinery/resources/runtime" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -35,6 +39,45 @@ func (suite *KmsgLogConfigSuite) TestKmsgLogConfigNone() { | |||||||
| 	rtestutils.AssertNoResource[*runtime.KmsgLogConfig](suite.Ctx(), suite.T(), suite.State(), runtime.KmsgLogConfigID) | 	rtestutils.AssertNoResource[*runtime.KmsgLogConfig](suite.Ctx(), suite.T(), suite.State(), runtime.KmsgLogConfigID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *KmsgLogConfigSuite) TestKmsgLogConfigMachineConfig() { | ||||||
|  | 	cmdline := procfs.NewCmdline("") | ||||||
|  | 	cmdline.Append(constants.KernelParamLoggingKernel, "https://10.0.0.1:3333/logs") | ||||||
|  | 
 | ||||||
|  | 	suite.Require().NoError(suite.Runtime().RegisterController(&runtimectrls.KmsgLogConfigController{ | ||||||
|  | 		Cmdline: cmdline, | ||||||
|  | 	})) | ||||||
|  | 
 | ||||||
|  | 	kmsgLogConfig1 := &runtimecfg.KmsgLogV1Alpha1{ | ||||||
|  | 		MetaName: "1", | ||||||
|  | 		KmsgLogURL: meta.URL{ | ||||||
|  | 			URL: must(url.Parse("https://10.0.0.2:4444/logs")), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	kmsgLogConfig2 := &runtimecfg.KmsgLogV1Alpha1{ | ||||||
|  | 		MetaName: "2", | ||||||
|  | 		KmsgLogURL: meta.URL{ | ||||||
|  | 			URL: must(url.Parse("https://10.0.0.1:3333/logs")), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cfg, err := container.New(kmsgLogConfig1, kmsgLogConfig2) | ||||||
|  | 	suite.Require().NoError(err) | ||||||
|  | 
 | ||||||
|  | 	suite.Require().NoError(suite.State().Create(suite.Ctx(), config.NewMachineConfig(cfg))) | ||||||
|  | 
 | ||||||
|  | 	rtestutils.AssertResources[*runtime.KmsgLogConfig](suite.Ctx(), suite.T(), suite.State(), []resource.ID{runtime.KmsgLogConfigID}, | ||||||
|  | 		func(cfg *runtime.KmsgLogConfig, asrt *assert.Assertions) { | ||||||
|  | 			asrt.Equal( | ||||||
|  | 				[]string{ | ||||||
|  | 					"https://10.0.0.1:3333/logs", | ||||||
|  | 					"https://10.0.0.2:4444/logs", | ||||||
|  | 				}, | ||||||
|  | 				slices.Map(cfg.TypedSpec().Destinations, func(u *url.URL) string { return u.String() }), | ||||||
|  | 			) | ||||||
|  | 		}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (suite *KmsgLogConfigSuite) TestKmsgLogConfigCmdline() { | func (suite *KmsgLogConfigSuite) TestKmsgLogConfigCmdline() { | ||||||
| 	cmdline := procfs.NewCmdline("") | 	cmdline := procfs.NewCmdline("") | ||||||
| 	cmdline.Append(constants.KernelParamLoggingKernel, "https://10.0.0.1:3333/logs") | 	cmdline.Append(constants.KernelParamLoggingKernel, "https://10.0.0.1:3333/logs") | ||||||
| @ -51,3 +94,11 @@ func (suite *KmsgLogConfigSuite) TestKmsgLogConfigCmdline() { | |||||||
| 			) | 			) | ||||||
| 		}) | 		}) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func must[T any](t T, err error) T { | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | |||||||
| @ -12,4 +12,5 @@ type Config interface { | |||||||
| 	Machine() MachineConfig | 	Machine() MachineConfig | ||||||
| 	Cluster() ClusterConfig | 	Cluster() ClusterConfig | ||||||
| 	SideroLink() SideroLinkConfig | 	SideroLink() SideroLinkConfig | ||||||
|  | 	Runtime() RuntimeConfig | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										52
									
								
								pkg/machinery/config/config/runtime.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								pkg/machinery/config/config/runtime.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | package config | ||||||
|  | 
 | ||||||
|  | import "net/url" | ||||||
|  | 
 | ||||||
|  | // RuntimeConfig defines the interface to access Talos runtime configuration. | ||||||
|  | type RuntimeConfig interface { | ||||||
|  | 	EventsEndpoint() *string | ||||||
|  | 	KmsgLogURLs() []*url.URL | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // WrapRuntimeConfigList wraps a list of RuntimeConfig into a single RuntimeConfig aggregating the results. | ||||||
|  | func WrapRuntimeConfigList(configs ...RuntimeConfig) RuntimeConfig { | ||||||
|  | 	return runtimeConfigWrapper(configs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type runtimeConfigWrapper []RuntimeConfig | ||||||
|  | 
 | ||||||
|  | func (w runtimeConfigWrapper) EventsEndpoint() *string { | ||||||
|  | 	return findFirstValue(w, func(c RuntimeConfig) *string { | ||||||
|  | 		return c.EventsEndpoint() | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (w runtimeConfigWrapper) KmsgLogURLs() []*url.URL { | ||||||
|  | 	return aggregateValues(w, func(c RuntimeConfig) []*url.URL { | ||||||
|  | 		return c.KmsgLogURLs() | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func findFirstValue[T any, R any](documents []T, getter func(T) *R) *R { | ||||||
|  | 	for _, document := range documents { | ||||||
|  | 		if value := getter(document); value != nil { | ||||||
|  | 			return value | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func aggregateValues[T any, R any](documents []T, getter func(T) []R) []R { | ||||||
|  | 	var result []R | ||||||
|  | 
 | ||||||
|  | 	for _, document := range documents { | ||||||
|  | 		result = append(result, getter(document)...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return result | ||||||
|  | } | ||||||
| @ -31,6 +31,6 @@ func FuzzConfigLoader(f *testing.F) { | |||||||
| 	f.Fuzz(func(t *testing.T, b []byte) { | 	f.Fuzz(func(t *testing.T, b []byte) { | ||||||
| 		t.Parallel() | 		t.Parallel() | ||||||
| 
 | 
 | ||||||
| 		testConfigLoaderBytes(t, b) | 		testConfigLoaderBytes(t, b, false) | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  | |||||||
| @ -16,6 +16,8 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // callMethods calls obj's "getter" methods recursively and fails on panic. | // callMethods calls obj's "getter" methods recursively and fails on panic. | ||||||
|  | // | ||||||
|  | //nolint:gocyclo | ||||||
| func callMethods(t testing.TB, obj reflect.Value, chain ...string) { | func callMethods(t testing.TB, obj reflect.Value, chain ...string) { | ||||||
| 	t.Helper() | 	t.Helper() | ||||||
| 
 | 
 | ||||||
| @ -44,6 +46,8 @@ func callMethods(t testing.TB, obj reflect.Value, chain ...string) { | |||||||
| 			fallthrough | 			fallthrough | ||||||
| 		case "MarshalYAML": | 		case "MarshalYAML": | ||||||
| 			fallthrough | 			fallthrough | ||||||
|  | 		case "Doc": | ||||||
|  | 			fallthrough | ||||||
| 		case "Endpoint": | 		case "Endpoint": | ||||||
| 			// t.Logf("Skipping %v", nextChain) | 			// t.Logf("Skipping %v", nextChain) | ||||||
| 			continue | 			continue | ||||||
| @ -69,13 +73,17 @@ func callMethods(t testing.TB, obj reflect.Value, chain ...string) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func testConfigLoaderBytes(t testing.TB, b []byte) { | func testConfigLoaderBytes(t testing.TB, b []byte, failOnError bool) { | ||||||
| 	t.Helper() | 	t.Helper() | ||||||
| 
 | 
 | ||||||
| 	p, err := configloader.NewFromBytes(b) | 	p, err := configloader.NewFromBytes(b) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | 		if failOnError { | ||||||
|  | 			t.Fatalf("Failed to load: %s.", err) | ||||||
|  | 		} else { | ||||||
| 			t.Skipf("Failed to load, skipping: %s.", err) | 			t.Skipf("Failed to load, skipping: %s.", err) | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	callMethods(t, reflect.ValueOf(p)) | 	callMethods(t, reflect.ValueOf(p)) | ||||||
| } | } | ||||||
| @ -95,7 +103,7 @@ func TestConfigLoader(t *testing.T) { | |||||||
| 			b, err := os.ReadFile(file) | 			b, err := os.ReadFile(file) | ||||||
| 			require.NoError(t, err) | 			require.NoError(t, err) | ||||||
| 
 | 
 | ||||||
| 			testConfigLoaderBytes(t, b) | 			testConfigLoaderBytes(t, b, true) | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								pkg/machinery/config/configloader/testdata/multidoc1.test
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								pkg/machinery/config/configloader/testdata/multidoc1.test
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | apiVersion: v1alpha1 | ||||||
|  | kind: SideroLinkConfig | ||||||
|  | apiUrl: grpc://172.20.0.1:4000/?jointoken=foo | ||||||
|  | --- | ||||||
|  | apiVersion: v1alpha1 | ||||||
|  | kind: KmsgLogConfig | ||||||
|  | name: apiSink | ||||||
|  | url: tcp://[fdae:41e4:649b:9303::1]:4001/ | ||||||
|  | --- | ||||||
|  | apiVersion: v1alpha1 | ||||||
|  | kind: EventSinkConfig | ||||||
|  | endpoint: "[fdae:41e4:649b:9303::1]:8080" | ||||||
| @ -112,7 +112,7 @@ func (container *Container) Debug() bool { | |||||||
| // Persist implements config.Config interface. | // Persist implements config.Config interface. | ||||||
| func (container *Container) Persist() bool { | func (container *Container) Persist() bool { | ||||||
| 	if container.v1alpha1Config == nil { | 	if container.v1alpha1Config == nil { | ||||||
| 		return false | 		return true | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return container.v1alpha1Config.Persist() | 	return container.v1alpha1Config.Persist() | ||||||
| @ -136,15 +136,31 @@ func (container *Container) Cluster() config.ClusterConfig { | |||||||
| 	return container.v1alpha1Config.Cluster() | 	return container.v1alpha1Config.Cluster() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SideroLink implements config.Config interface. | func findMatchingDocs[T any](documents []config.Document) []T { | ||||||
| func (container *Container) SideroLink() config.SideroLinkConfig { | 	var result []T | ||||||
| 	for _, doc := range container.documents { | 
 | ||||||
| 		if c, ok := doc.(config.SideroLinkConfig); ok { | 	for _, doc := range documents { | ||||||
| 			return c | 		if c, ok := doc.(T); ok { | ||||||
|  | 			result = append(result, c) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	return result | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SideroLink implements config.Config interface. | ||||||
|  | func (container *Container) SideroLink() config.SideroLinkConfig { | ||||||
|  | 	matching := findMatchingDocs[config.SideroLinkConfig](container.documents) | ||||||
|  | 	if len(matching) == 0 { | ||||||
| 		return nil | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return matching[0] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Runtime implements config.Config interface. | ||||||
|  | func (container *Container) Runtime() config.RuntimeConfig { | ||||||
|  | 	return config.WrapRuntimeConfigList(findMatchingDocs[config.RuntimeConfig](container.documents)...) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Bytes returns source YAML representation (if available) or does default encoding. | // Bytes returns source YAML representation (if available) or does default encoding. | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								pkg/machinery/config/types/runtime/deep_copy.generated.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								pkg/machinery/config/types/runtime/deep_copy.generated.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | // Code generated by "deep-copy -type EventSinkV1Alpha1 -type KmsgLogV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT. | ||||||
|  | 
 | ||||||
|  | package runtime | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/url" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // DeepCopy generates a deep copy of *EventSinkV1Alpha1. | ||||||
|  | func (o *EventSinkV1Alpha1) DeepCopy() *EventSinkV1Alpha1 { | ||||||
|  | 	var cp EventSinkV1Alpha1 = *o | ||||||
|  | 	return &cp | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeepCopy generates a deep copy of *KmsgLogV1Alpha1. | ||||||
|  | func (o *KmsgLogV1Alpha1) DeepCopy() *KmsgLogV1Alpha1 { | ||||||
|  | 	var cp KmsgLogV1Alpha1 = *o | ||||||
|  | 	if o.KmsgLogURL.URL != nil { | ||||||
|  | 		cp.KmsgLogURL.URL = new(url.URL) | ||||||
|  | 		*cp.KmsgLogURL.URL = *o.KmsgLogURL.URL | ||||||
|  | 		if o.KmsgLogURL.URL.User != nil { | ||||||
|  | 			cp.KmsgLogURL.URL.User = new(url.Userinfo) | ||||||
|  | 			*cp.KmsgLogURL.URL.User = *o.KmsgLogURL.URL.User | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return &cp | ||||||
|  | } | ||||||
							
								
								
									
										84
									
								
								pkg/machinery/config/types/runtime/event_sink.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								pkg/machinery/config/types/runtime/event_sink.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | package runtime | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"net" | ||||||
|  | 	"net/url" | ||||||
|  | 
 | ||||||
|  | 	"github.com/siderolabs/go-pointer" | ||||||
|  | 
 | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/config" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/internal/registry" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/types/meta" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/validation" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // EventSinkKind is a event sink config document kind. | ||||||
|  | const EventSinkKind = "EventSinkConfig" | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	registry.Register(EventSinkKind, func(version string) config.Document { | ||||||
|  | 		switch version { | ||||||
|  | 		case "v1alpha1": | ||||||
|  | 			return &EventSinkV1Alpha1{} | ||||||
|  | 		default: | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Check interfaces. | ||||||
|  | var ( | ||||||
|  | 	_ config.RuntimeConfig = &EventSinkV1Alpha1{} | ||||||
|  | 	_ config.Validator     = &EventSinkV1Alpha1{} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // EventSinkV1Alpha1 is a event sink config document. | ||||||
|  | type EventSinkV1Alpha1 struct { | ||||||
|  | 	meta.Meta `yaml:",inline"` | ||||||
|  | 	Endpoint  string `yaml:"endpoint"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewEventSinkV1Alpha1 creates a new eventsink config document. | ||||||
|  | func NewEventSinkV1Alpha1() *EventSinkV1Alpha1 { | ||||||
|  | 	return &EventSinkV1Alpha1{ | ||||||
|  | 		Meta: meta.Meta{ | ||||||
|  | 			MetaKind:       EventSinkKind, | ||||||
|  | 			MetaAPIVersion: "v1alpha1", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Clone implements config.Document interface. | ||||||
|  | func (s *EventSinkV1Alpha1) Clone() config.Document { | ||||||
|  | 	return s.DeepCopy() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Runtime implements config.Config interface. | ||||||
|  | func (s *EventSinkV1Alpha1) Runtime() config.RuntimeConfig { | ||||||
|  | 	return s | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // EventsEndpoint implements config.RuntimeConfig interface. | ||||||
|  | func (s *EventSinkV1Alpha1) EventsEndpoint() *string { | ||||||
|  | 	return pointer.To(s.Endpoint) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // KmsgLogURLs implements config.RuntimeConfig interface. | ||||||
|  | func (s *EventSinkV1Alpha1) KmsgLogURLs() []*url.URL { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Validate implements config.Validator interface. | ||||||
|  | func (s *EventSinkV1Alpha1) Validate(validation.RuntimeMode, ...validation.Option) ([]string, error) { | ||||||
|  | 	_, _, err := net.SplitHostPort(s.Endpoint) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("event sink endpoint: %w", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil, nil | ||||||
|  | } | ||||||
							
								
								
									
										104
									
								
								pkg/machinery/config/types/runtime/event_sink_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								pkg/machinery/config/types/runtime/event_sink_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | package runtime_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	_ "embed" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | 
 | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/encoder" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/types/runtime" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | //go:embed testdata/eventsink.yaml | ||||||
|  | var expectedEventSinkDocument []byte | ||||||
|  | 
 | ||||||
|  | func TestEventSinkMarshalStability(t *testing.T) { | ||||||
|  | 	cfg := runtime.NewEventSinkV1Alpha1() | ||||||
|  | 	cfg.Endpoint = "10.0.0.1:3333" | ||||||
|  | 
 | ||||||
|  | 	marshaled, err := encoder.NewEncoder(cfg).Encode() | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 	t.Log(string(marshaled)) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, expectedEventSinkDocument, marshaled) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestEventSinkValidate(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
|  | 	for _, test := range []struct { | ||||||
|  | 		name string | ||||||
|  | 		cfg  func() *runtime.EventSinkV1Alpha1 | ||||||
|  | 
 | ||||||
|  | 		expectedError    string | ||||||
|  | 		expectedWarnings []string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "empty", | ||||||
|  | 			cfg:  runtime.NewEventSinkV1Alpha1, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "event sink endpoint: missing port in address", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "just IP", | ||||||
|  | 			cfg: func() *runtime.EventSinkV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewEventSinkV1Alpha1() | ||||||
|  | 				cfg.Endpoint = "10.0.0.1" | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "event sink endpoint: address 10.0.0.1: missing port in address", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "valid", | ||||||
|  | 			cfg: func() *runtime.EventSinkV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewEventSinkV1Alpha1() | ||||||
|  | 				cfg.Endpoint = "[ff:80::01]:334" | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		test := test | ||||||
|  | 
 | ||||||
|  | 		t.Run(test.name, func(t *testing.T) { | ||||||
|  | 			t.Parallel() | ||||||
|  | 
 | ||||||
|  | 			warnings, err := test.cfg().Validate(validationMode{}) | ||||||
|  | 
 | ||||||
|  | 			assert.Equal(t, test.expectedWarnings, warnings) | ||||||
|  | 
 | ||||||
|  | 			if test.expectedError != "" { | ||||||
|  | 				assert.EqualError(t, err, test.expectedError) | ||||||
|  | 			} else { | ||||||
|  | 				assert.NoError(t, err) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func must[T any](t T, err error) T { | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type validationMode struct{} | ||||||
|  | 
 | ||||||
|  | func (validationMode) String() string { | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (validationMode) RequiresInstall() bool { | ||||||
|  | 	return false | ||||||
|  | } | ||||||
							
								
								
									
										109
									
								
								pkg/machinery/config/types/runtime/kmsg_log.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								pkg/machinery/config/types/runtime/kmsg_log.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | package runtime | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"net/url" | ||||||
|  | 
 | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/config" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/internal/registry" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/types/meta" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/validation" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // KmsgLogKind is a kmsg log config document kind. | ||||||
|  | const KmsgLogKind = "KmsgLogConfig" | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	registry.Register(KmsgLogKind, func(version string) config.Document { | ||||||
|  | 		switch version { | ||||||
|  | 		case "v1alpha1": | ||||||
|  | 			return &KmsgLogV1Alpha1{} | ||||||
|  | 		default: | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Check interfaces. | ||||||
|  | var ( | ||||||
|  | 	_ config.RuntimeConfig = &KmsgLogV1Alpha1{} | ||||||
|  | 	_ config.NamedDocument = &KmsgLogV1Alpha1{} | ||||||
|  | 	_ config.Validator     = &KmsgLogV1Alpha1{} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // KmsgLogV1Alpha1 is a event sink config document. | ||||||
|  | type KmsgLogV1Alpha1 struct { | ||||||
|  | 	meta.Meta  `yaml:",inline"` | ||||||
|  | 	MetaName   string   `yaml:"name"` | ||||||
|  | 	KmsgLogURL meta.URL `yaml:"url"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewKmsgLogV1Alpha1 creates a new eventsink config document. | ||||||
|  | func NewKmsgLogV1Alpha1() *KmsgLogV1Alpha1 { | ||||||
|  | 	return &KmsgLogV1Alpha1{ | ||||||
|  | 		Meta: meta.Meta{ | ||||||
|  | 			MetaKind:       KmsgLogKind, | ||||||
|  | 			MetaAPIVersion: "v1alpha1", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Name implements config.NamedDocument interface. | ||||||
|  | func (s *KmsgLogV1Alpha1) Name() string { | ||||||
|  | 	return s.MetaName | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Clone implements config.Document interface. | ||||||
|  | func (s *KmsgLogV1Alpha1) Clone() config.Document { | ||||||
|  | 	return s.DeepCopy() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Runtime implements config.Config interface. | ||||||
|  | func (s *KmsgLogV1Alpha1) Runtime() config.RuntimeConfig { | ||||||
|  | 	return s | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // EventsEndpoint implements config.RuntimeConfig interface. | ||||||
|  | func (s *KmsgLogV1Alpha1) EventsEndpoint() *string { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // KmsgLogURLs implements config.RuntimeConfig interface. | ||||||
|  | func (s *KmsgLogV1Alpha1) KmsgLogURLs() []*url.URL { | ||||||
|  | 	return []*url.URL{s.KmsgLogURL.URL} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Validate implements config.Validator interface. | ||||||
|  | func (s *KmsgLogV1Alpha1) Validate(validation.RuntimeMode, ...validation.Option) ([]string, error) { | ||||||
|  | 	if s.MetaName == "" { | ||||||
|  | 		return nil, fmt.Errorf("name is required") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if s.KmsgLogURL.URL == nil { | ||||||
|  | 		return nil, fmt.Errorf("url is required") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch s.KmsgLogURL.URL.Scheme { | ||||||
|  | 	case "tcp": | ||||||
|  | 	case "udp": | ||||||
|  | 	default: | ||||||
|  | 		return nil, fmt.Errorf("url scheme must be tcp:// or udp://") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch s.KmsgLogURL.URL.Path { | ||||||
|  | 	case "/": | ||||||
|  | 	case "": | ||||||
|  | 	default: | ||||||
|  | 		return nil, fmt.Errorf("url path must be empty") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if s.KmsgLogURL.URL.Port() == "" { | ||||||
|  | 		return nil, fmt.Errorf("url port is required") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil, nil | ||||||
|  | } | ||||||
							
								
								
									
										135
									
								
								pkg/machinery/config/types/runtime/kmsg_log_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								pkg/machinery/config/types/runtime/kmsg_log_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,135 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | package runtime_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	_ "embed" | ||||||
|  | 	"net/url" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | 
 | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/encoder" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/types/runtime" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | //go:embed testdata/kmsglog.yaml | ||||||
|  | var expectedKmsgLogDocument []byte | ||||||
|  | 
 | ||||||
|  | func TestKmsgLogMarshalStability(t *testing.T) { | ||||||
|  | 	cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 	cfg.MetaName = "apiSink" | ||||||
|  | 	cfg.KmsgLogURL.URL = must(url.Parse("https://kmsglog.api/logs")) | ||||||
|  | 
 | ||||||
|  | 	marshaled, err := encoder.NewEncoder(cfg).Encode() | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 	t.Log(string(marshaled)) | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, expectedKmsgLogDocument, marshaled) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestKmsgLogValidate(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
|  | 	for _, test := range []struct { | ||||||
|  | 		name string | ||||||
|  | 		cfg  func() *runtime.KmsgLogV1Alpha1 | ||||||
|  | 
 | ||||||
|  | 		expectedError    string | ||||||
|  | 		expectedWarnings []string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "empty", | ||||||
|  | 			cfg:  runtime.NewKmsgLogV1Alpha1, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "name is required", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "no URL", | ||||||
|  | 			cfg: func() *runtime.KmsgLogV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 				cfg.MetaName = "name1" | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "url is required", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "wrong scheme", | ||||||
|  | 			cfg: func() *runtime.KmsgLogV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 				cfg.MetaName = "name2" | ||||||
|  | 				cfg.KmsgLogURL.URL = must(url.Parse("https://some.destination/path")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "url scheme must be tcp:// or udp://", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "extra path", | ||||||
|  | 			cfg: func() *runtime.KmsgLogV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 				cfg.MetaName = "name5" | ||||||
|  | 				cfg.KmsgLogURL.URL = must(url.Parse("tcp://some.destination:34/path")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "url path must be empty", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "no port", | ||||||
|  | 			cfg: func() *runtime.KmsgLogV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 				cfg.MetaName = "name6" | ||||||
|  | 				cfg.KmsgLogURL.URL = must(url.Parse("tcp://some.destination/")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "url port is required", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "valid TCP", | ||||||
|  | 			cfg: func() *runtime.KmsgLogV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 				cfg.MetaName = "name3" | ||||||
|  | 				cfg.KmsgLogURL.URL = must(url.Parse("tcp://10.2.3.4:5000/")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "valid UDP", | ||||||
|  | 			cfg: func() *runtime.KmsgLogV1Alpha1 { | ||||||
|  | 				cfg := runtime.NewKmsgLogV1Alpha1() | ||||||
|  | 				cfg.MetaName = "name4" | ||||||
|  | 				cfg.KmsgLogURL.URL = must(url.Parse("udp://10.2.3.4:5000/")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		test := test | ||||||
|  | 
 | ||||||
|  | 		t.Run(test.name, func(t *testing.T) { | ||||||
|  | 			t.Parallel() | ||||||
|  | 
 | ||||||
|  | 			warnings, err := test.cfg().Validate(validationMode{}) | ||||||
|  | 
 | ||||||
|  | 			assert.Equal(t, test.expectedWarnings, warnings) | ||||||
|  | 
 | ||||||
|  | 			if test.expectedError != "" { | ||||||
|  | 				assert.EqualError(t, err, test.expectedError) | ||||||
|  | 			} else { | ||||||
|  | 				assert.NoError(t, err) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								pkg/machinery/config/types/runtime/runtime.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								pkg/machinery/config/types/runtime/runtime.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  | 
 | ||||||
|  | // Package runtime provides Talos runtime config documents. | ||||||
|  | package runtime | ||||||
|  | 
 | ||||||
|  | //go:generate deep-copy -type EventSinkV1Alpha1 -type KmsgLogV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go . | ||||||
							
								
								
									
										3
									
								
								pkg/machinery/config/types/runtime/testdata/eventsink.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								pkg/machinery/config/types/runtime/testdata/eventsink.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | apiVersion: v1alpha1 | ||||||
|  | kind: EventSinkConfig | ||||||
|  | endpoint: 10.0.0.1:3333 | ||||||
							
								
								
									
										4
									
								
								pkg/machinery/config/types/runtime/testdata/kmsglog.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								pkg/machinery/config/types/runtime/testdata/kmsglog.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | apiVersion: v1alpha1 | ||||||
|  | kind: KmsgLogConfig | ||||||
|  | name: apiSink | ||||||
|  | url: https://kmsglog.api/logs | ||||||
| @ -6,11 +6,13 @@ | |||||||
| package siderolink | package siderolink | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 
 | 
 | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/config/config" | 	"github.com/siderolabs/talos/pkg/machinery/config/config" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/config/internal/registry" | 	"github.com/siderolabs/talos/pkg/machinery/config/internal/registry" | ||||||
| 	"github.com/siderolabs/talos/pkg/machinery/config/types/meta" | 	"github.com/siderolabs/talos/pkg/machinery/config/types/meta" | ||||||
|  | 	"github.com/siderolabs/talos/pkg/machinery/config/validation" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| //go:generate deep-copy -type ConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go . | //go:generate deep-copy -type ConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go . | ||||||
| @ -30,7 +32,11 @@ func init() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Check interfaces. | // Check interfaces. | ||||||
| var _ config.SecretDocument = &ConfigV1Alpha1{} | var ( | ||||||
|  | 	_ config.SecretDocument   = &ConfigV1Alpha1{} | ||||||
|  | 	_ config.SideroLinkConfig = &ConfigV1Alpha1{} | ||||||
|  | 	_ config.Validator        = &ConfigV1Alpha1{} | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // ConfigV1Alpha1 is a siderolink config document. | // ConfigV1Alpha1 is a siderolink config document. | ||||||
| type ConfigV1Alpha1 struct { | type ConfigV1Alpha1 struct { | ||||||
| @ -78,3 +84,26 @@ func (s *ConfigV1Alpha1) APIUrl() *url.URL { | |||||||
| 
 | 
 | ||||||
| 	return s.APIUrlConfig.URL | 	return s.APIUrlConfig.URL | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Validate implements config.Validator interface. | ||||||
|  | func (s *ConfigV1Alpha1) Validate(validation.RuntimeMode, ...validation.Option) ([]string, error) { | ||||||
|  | 	if s.APIUrlConfig.URL == nil { | ||||||
|  | 		return nil, fmt.Errorf("apiUrl is required") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch s.APIUrlConfig.URL.Scheme { | ||||||
|  | 	case "https": | ||||||
|  | 	case "grpc": | ||||||
|  | 	default: | ||||||
|  | 		return nil, fmt.Errorf("apiUrl scheme must be https:// or grpc://") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch s.APIUrlConfig.URL.Path { | ||||||
|  | 	case "/": | ||||||
|  | 	case "": | ||||||
|  | 	default: | ||||||
|  | 		return nil, fmt.Errorf("apiUrl path must be empty") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil, nil | ||||||
|  | } | ||||||
|  | |||||||
| @ -17,6 +17,8 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestRedact(t *testing.T) { | func TestRedact(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
| 	cfg := siderolink.NewConfigV1Alpha1() | 	cfg := siderolink.NewConfigV1Alpha1() | ||||||
| 	cfg.APIUrlConfig.URL = must(url.Parse("https://siderolink.api/join?jointoken=secret&user=alice")) | 	cfg.APIUrlConfig.URL = must(url.Parse("https://siderolink.api/join?jointoken=secret&user=alice")) | ||||||
| 
 | 
 | ||||||
| @ -31,6 +33,8 @@ func TestRedact(t *testing.T) { | |||||||
| var expectedDocument []byte | var expectedDocument []byte | ||||||
| 
 | 
 | ||||||
| func TestMarshalStability(t *testing.T) { | func TestMarshalStability(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
| 	cfg := siderolink.NewConfigV1Alpha1() | 	cfg := siderolink.NewConfigV1Alpha1() | ||||||
| 	cfg.APIUrlConfig.URL = must(url.Parse("https://siderolink.api/join?jointoken=secret&user=alice")) | 	cfg.APIUrlConfig.URL = must(url.Parse("https://siderolink.api/join?jointoken=secret&user=alice")) | ||||||
| 
 | 
 | ||||||
| @ -40,6 +44,72 @@ func TestMarshalStability(t *testing.T) { | |||||||
| 	assert.Equal(t, expectedDocument, marshaled) | 	assert.Equal(t, expectedDocument, marshaled) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestValidate(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
|  | 	for _, test := range []struct { | ||||||
|  | 		name string | ||||||
|  | 		cfg  func() *siderolink.ConfigV1Alpha1 | ||||||
|  | 
 | ||||||
|  | 		expectedError    string | ||||||
|  | 		expectedWarnings []string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "empty", | ||||||
|  | 			cfg:  siderolink.NewConfigV1Alpha1, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "apiUrl is required", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "wrong scheme", | ||||||
|  | 			cfg: func() *siderolink.ConfigV1Alpha1 { | ||||||
|  | 				cfg := siderolink.NewConfigV1Alpha1() | ||||||
|  | 				cfg.APIUrlConfig.URL = must(url.Parse("http://siderolink.api/")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "apiUrl scheme must be https:// or grpc://", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "extra path", | ||||||
|  | 			cfg: func() *siderolink.ConfigV1Alpha1 { | ||||||
|  | 				cfg := siderolink.NewConfigV1Alpha1() | ||||||
|  | 				cfg.APIUrlConfig.URL = must(url.Parse("grpc://siderolink.api/path?jointoken=foo")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			expectedError: "apiUrl path must be empty", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "valid", | ||||||
|  | 			cfg: func() *siderolink.ConfigV1Alpha1 { | ||||||
|  | 				cfg := siderolink.NewConfigV1Alpha1() | ||||||
|  | 				cfg.APIUrlConfig.URL = must(url.Parse("https://siderolink.api:434/?jointoken=foo")) | ||||||
|  | 
 | ||||||
|  | 				return cfg | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		test := test | ||||||
|  | 
 | ||||||
|  | 		t.Run(test.name, func(t *testing.T) { | ||||||
|  | 			t.Parallel() | ||||||
|  | 
 | ||||||
|  | 			warnings, err := test.cfg().Validate(validationMode{}) | ||||||
|  | 
 | ||||||
|  | 			assert.Equal(t, test.expectedWarnings, warnings) | ||||||
|  | 
 | ||||||
|  | 			if test.expectedError != "" { | ||||||
|  | 				assert.EqualError(t, err, test.expectedError) | ||||||
|  | 			} else { | ||||||
|  | 				assert.NoError(t, err) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func must[T any](t T, err error) T { | func must[T any](t T, err error) T { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		panic(err) | 		panic(err) | ||||||
| @ -47,3 +117,13 @@ func must[T any](t T, err error) T { | |||||||
| 
 | 
 | ||||||
| 	return t | 	return t | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type validationMode struct{} | ||||||
|  | 
 | ||||||
|  | func (validationMode) String() string { | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (validationMode) RequiresInstall() bool { | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| package types | package types | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	_ "github.com/siderolabs/talos/pkg/machinery/config/types/siderolink" //nolint:revive | 	_ "github.com/siderolabs/talos/pkg/machinery/config/types/runtime" //nolint:revive | ||||||
|  | 	_ "github.com/siderolabs/talos/pkg/machinery/config/types/siderolink" | ||||||
| 	_ "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" | 	_ "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -52,17 +52,25 @@ func (c *Config) APIVersion() string { | |||||||
| 
 | 
 | ||||||
| // Debug implements the config.Provider interface. | // Debug implements the config.Provider interface. | ||||||
| func (c *Config) Debug() bool { | func (c *Config) Debug() bool { | ||||||
|  | 	if c == nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return pointer.SafeDeref(c.ConfigDebug) | 	return pointer.SafeDeref(c.ConfigDebug) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Persist implements the config.Provider interface. | // Persist implements the config.Provider interface. | ||||||
| func (c *Config) Persist() bool { | func (c *Config) Persist() bool { | ||||||
|  | 	if c == nil { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return pointer.SafeDeref(c.ConfigPersist) | 	return pointer.SafeDeref(c.ConfigPersist) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Machine implements the config.Provider interface. | // Machine implements the config.Provider interface. | ||||||
| func (c *Config) Machine() config.MachineConfig { | func (c *Config) Machine() config.MachineConfig { | ||||||
| 	if c.MachineConfig == nil { | 	if c == nil || c.MachineConfig == nil { | ||||||
| 		return &MachineConfig{} | 		return &MachineConfig{} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -91,7 +99,7 @@ func (m *MachineConfig) NodeLabels() config.NodeLabels { | |||||||
| 
 | 
 | ||||||
| // Cluster implements the config.Provider interface. | // Cluster implements the config.Provider interface. | ||||||
| func (c *Config) Cluster() config.ClusterConfig { | func (c *Config) Cluster() config.ClusterConfig { | ||||||
| 	if c.ClusterConfig == nil { | 	if c == nil || c.ClusterConfig == nil { | ||||||
| 		return &ClusterConfig{} | 		return &ClusterConfig{} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user