33import com .freenow .sauron .model .DataSet ;
44import com .freenow .sauron .properties .PluginsConfigurationProperties ;
55import io .kubernetes .client .openapi .ApiClient ;
6+ import io .kubernetes .client .util .ClientBuilder ;
67import io .kubernetes .client .util .Config ;
8+ import io .kubernetes .client .util .KubeConfig ;
9+ import java .io .File ;
10+ import java .io .FileReader ;
711import java .util .HashMap ;
812import java .util .Map ;
913import java .util .Optional ;
1014import lombok .NoArgsConstructor ;
1115import lombok .extern .slf4j .Slf4j ;
1216
1317import static com .freenow .sauron .plugins .KubernetesApiReport .API_CLIENT_CONFIG_PROPERTY ;
18+ import static com .freenow .sauron .plugins .KubernetesApiReport .KUBE_CONFIG_FILE_PROPERTY ;
1419import static com .freenow .sauron .plugins .KubernetesApiReport .PLUGIN_ID ;
20+ import static io .kubernetes .client .util .KubeConfig .ENV_HOME ;
21+ import static io .kubernetes .client .util .KubeConfig .KUBECONFIG ;
22+ import static io .kubernetes .client .util .KubeConfig .KUBEDIR ;
1523import static org .apache .commons .lang3 .StringUtils .EMPTY ;
1624
1725@ Slf4j
@@ -31,28 +39,41 @@ public APIClientFactory(final Map<String, ApiClient> apiClients)
3139 }
3240
3341
42+ /**
43+ * Creates the Kubernetes API client for an environment.
44+ * It reads the environment from the field "environment" in the DataSet.
45+ * If no client for the environment can be found, then it falls back to a default client.
46+ * <p>
47+ * The configuration of this plugin supports multiple ways to create an API client:
48+ * <pre>
49+ * kubernetesapi-report:
50+ * # ...
51+ * apiClientConfig:
52+ * default: default # Use the default client
53+ * clusterOne: "https://clusterOne.local" # Use a URL
54+ * clusterTwo: clusterTwo # Use the context "clusterTwo" from the kube config file at $HOME/.kube/config
55+ * # ...
56+ * </pre>
57+ *
58+ * @param input The current DataSet.
59+ * @param properties Plugin configuration.
60+ * @return Kubernetes API client.
61+ */
3462 public ApiClient get (final DataSet input , final PluginsConfigurationProperties properties )
3563 {
3664 if (apiClients .isEmpty ())
3765 {
66+ String kubeConfigFile ;
67+ if (properties .getPluginConfigurationProperty (PLUGIN_ID , KUBE_CONFIG_FILE_PROPERTY ).isPresent ())
68+ {
69+ kubeConfigFile = (String ) properties .getPluginConfigurationProperty (PLUGIN_ID , KUBE_CONFIG_FILE_PROPERTY ).get ();
70+ } else {
71+ kubeConfigFile = "" ;
72+ }
73+
3874 properties .getPluginConfigurationProperty (PLUGIN_ID , API_CLIENT_CONFIG_PROPERTY )
3975 .ifPresent (config -> ((Map <String , String >) config ).forEach ((k , v ) -> {
40- if (DEFAULT_CLIENT_CONFIG .equalsIgnoreCase (k ))
41- {
42- try
43- {
44- apiClients .put (DEFAULT_CLIENT_CONFIG , Config .defaultClient ());
45- }
46- catch (Exception e )
47- {
48- log .error ("API Client not initialized. Error: {}" , e .getMessage (), e );
49- throw new RuntimeException (e );
50- }
51- }
52- else
53- {
54- apiClients .put (k , Config .fromUrl (v ));
55- }
76+ apiClients .put (k , createClient (k , v , kubeConfigFile ));
5677 }));
5778
5879 if (apiClients .isEmpty ())
@@ -70,4 +91,44 @@ public ApiClient get(final DataSet input, final PluginsConfigurationProperties p
7091 }
7192 return Optional .ofNullable (apiClients .get (input .getStringAdditionalInformation (ENVIRONMENT ).orElse (EMPTY ))).orElse (apiClients .get (DEFAULT_CLIENT_CONFIG ));
7293 }
94+
95+ private ApiClient createClient (String cluster , String value , String kubeConfigFile )
96+ {
97+ try
98+ {
99+ if (DEFAULT_CLIENT_CONFIG .equalsIgnoreCase (cluster ))
100+ {
101+ log .debug ("Creating default Kubernetes client for cluster {}" , cluster );
102+ return Config .defaultClient ();
103+ }
104+
105+ if (value .startsWith ("https://" ))
106+ {
107+ log .debug ("Creating Kubernetes client from URL {} for cluster {}" , value , cluster );
108+ return Config .fromUrl (value );
109+ }
110+
111+ log .debug ("Creating Kubernetes client from config for cluster {}" , cluster );
112+ // Create KubeConfig here because it allows setting the context.
113+ File configFile = getKubeConfig (kubeConfigFile );
114+ KubeConfig kubeConfig = KubeConfig .loadKubeConfig (new FileReader (configFile ));
115+ kubeConfig .setContext (value );
116+ return ClientBuilder .kubeconfig (kubeConfig ).build ();
117+ }
118+ catch (Exception e )
119+ {
120+ log .error ("API Client for {} not initialized. Error: {}" , cluster , e .getMessage (), e );
121+ throw new RuntimeException (e );
122+ }
123+ }
124+
125+ private File getKubeConfig (String path )
126+ {
127+ if (path == null || path .isEmpty ())
128+ {
129+ return new File (new File (System .getenv (ENV_HOME ), KUBEDIR ), KUBECONFIG );
130+ }
131+
132+ return new File (path );
133+ }
73134}
0 commit comments