diff --git a/go/helm_sdkpy/_lib/linux-amd64/libhelm_sdkpy.h b/go/helm_sdkpy/_lib/linux-amd64/libhelm_sdkpy.h index c88fc9c..c3abe70 100644 --- a/go/helm_sdkpy/_lib/linux-amd64/libhelm_sdkpy.h +++ b/go/helm_sdkpy/_lib/linux-amd64/libhelm_sdkpy.h @@ -1,6 +1,6 @@ /* Code generated by cmd/cgo; DO NOT EDIT. */ -/* package command-line-arguments */ +/* package github.com/vantagecompute/helm-sdkpy/shim */ #line 1 "cgo-builtin-export-prolog" @@ -12,6 +12,8 @@ #ifndef GO_CGO_GOSTRING_TYPEDEF typedef struct { const char *p; ptrdiff_t n; } _GoString_; +extern size_t _GoStringLen(_GoString_ s); +extern const char *_GoStringPtr(_GoString_ s); #endif #endif @@ -53,10 +55,16 @@ typedef size_t GoUintptr; typedef float GoFloat32; typedef double GoFloat64; #ifdef _MSC_VER +#if !defined(__cplusplus) || _MSVC_LANG <= 201402L #include typedef _Fcomplex GoComplex64; typedef _Dcomplex GoComplex128; #else +#include +typedef std::complex GoComplex64; +typedef std::complex GoComplex128; +#endif +#else typedef float _Complex GoComplex64; typedef double _Complex GoComplex128; #endif @@ -83,11 +91,11 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; extern "C" { #endif -extern char* helm_sdkpy_last_error(); +extern char* helm_sdkpy_last_error(void); extern void helm_sdkpy_free(void* ptr); -extern char* helm_sdkpy_version_string(); -extern int helm_sdkpy_version_number(); -extern int helm_sdkpy_config_create(char* namespace, char* kubeconfig, char* kubecontext, helm_sdkpy_handle* handle_out); +extern char* helm_sdkpy_version_string(void); +extern int helm_sdkpy_version_number(void); +extern int helm_sdkpy_config_create(char* namespace, char* kubeconfig, char* kubecontext, char* options_json, helm_sdkpy_handle* handle_out); extern void helm_sdkpy_config_destroy(helm_sdkpy_handle handle); extern int helm_sdkpy_install(helm_sdkpy_handle handle, char* release_name, char* chart_path, char* values_json, char* version, int create_namespace, int wait, int timeout_seconds, char** result_json); extern int helm_sdkpy_upgrade(helm_sdkpy_handle handle, char* release_name, char* chart_path, char* values_json, char* version, char** result_json); @@ -97,7 +105,7 @@ extern int helm_sdkpy_status(helm_sdkpy_handle handle, char* release_name, char* extern int helm_sdkpy_rollback(helm_sdkpy_handle handle, char* release_name, int revision, char** result_json); extern int helm_sdkpy_get_values(helm_sdkpy_handle handle, char* release_name, int all_values, char** result_json); extern int helm_sdkpy_history(helm_sdkpy_handle handle, char* release_name, char** result_json); -extern int helm_sdkpy_pull(helm_sdkpy_handle handle, char* chart_ref, char* dest_dir); +extern int helm_sdkpy_pull(helm_sdkpy_handle handle, char* chart_ref, char* dest_dir, char* version); extern int helm_sdkpy_show_chart(helm_sdkpy_handle handle, char* chart_path, char** result_json); extern int helm_sdkpy_show_values(helm_sdkpy_handle handle, char* chart_path, char** result_json); extern int helm_sdkpy_test(helm_sdkpy_handle handle, char* release_name, char** result_json); @@ -107,6 +115,9 @@ extern int helm_sdkpy_repo_add(helm_sdkpy_handle handle, char* name, char* url, extern int helm_sdkpy_repo_remove(helm_sdkpy_handle handle, char* name); extern int helm_sdkpy_repo_list(helm_sdkpy_handle handle, char** result_json); extern int helm_sdkpy_repo_update(helm_sdkpy_handle handle, char* name); +extern int helm_sdkpy_registry_login(helm_sdkpy_handle handle, char* hostname, char* username, char* password, char* options_json); +extern int helm_sdkpy_registry_logout(helm_sdkpy_handle handle, char* hostname); +extern int helm_sdkpy_push(helm_sdkpy_handle handle, char* chart_ref, char* remote, char* options_json); #ifdef __cplusplus } diff --git a/go/shim/main.go b/go/shim/main.go index f600d27..707101d 100644 --- a/go/shim/main.go +++ b/go/shim/main.go @@ -321,10 +321,22 @@ func loadChartFromRepo(chartRef string, version string, envs *cli.EnvSettings) ( // Configuration management //export helm_sdkpy_config_create -func helm_sdkpy_config_create(namespace *C.char, kubeconfig *C.char, kubecontext *C.char, handle_out *C.helm_sdkpy_handle) C.int { +func helm_sdkpy_config_create(namespace *C.char, kubeconfig *C.char, kubecontext *C.char, options_json *C.char, handle_out *C.helm_sdkpy_handle) C.int { ns := C.GoString(namespace) kc := C.GoString(kubeconfig) kctx := C.GoString(kubecontext) + optsJSON := C.GoString(options_json) + + // Parse config options + var configOpts struct { + PlainHTTP bool `json:"plain_http"` + InsecureSkipTLSVerify bool `json:"insecure_skip_tls_verify"` + } + if optsJSON != "" { + if err := json.Unmarshal([]byte(optsJSON), &configOpts); err != nil { + return setError(fmt.Errorf("failed to parse config options: %w", err)) + } + } var restClientGetter genericclioptions.RESTClientGetter var envs *cli.EnvSettings @@ -383,14 +395,21 @@ if cfg.KubeClient != nil { } // Initialize registry client for OCI operations -registryClient, err := registry.NewClient( -registry.ClientOptDebug(false), -registry.ClientOptEnableCache(true), -registry.ClientOptWriter(os.Stdout), -registry.ClientOptCredentialsFile(envs.RegistryConfig), -) +registryOpts := []registry.ClientOption{ + registry.ClientOptDebug(false), + registry.ClientOptEnableCache(true), + registry.ClientOptWriter(os.Stdout), + registry.ClientOptCredentialsFile(envs.RegistryConfig), +} + +// Add PlainHTTP option for HTTP registries (e.g., local registries without TLS) +if configOpts.PlainHTTP { + registryOpts = append(registryOpts, registry.ClientOptPlainHTTP()) +} + +registryClient, err := registry.NewClient(registryOpts...) if err != nil { -return setError(fmt.Errorf("failed to initialize registry client: %w", err)) + return setError(fmt.Errorf("failed to initialize registry client: %w", err)) } cfg.RegistryClient = registryClient diff --git a/helm_sdkpy/_ffi.py b/helm_sdkpy/_ffi.py index f50541e..2b8bbef 100644 --- a/helm_sdkpy/_ffi.py +++ b/helm_sdkpy/_ffi.py @@ -30,7 +30,7 @@ typedef unsigned long long helm_sdkpy_handle; // Configuration management - int helm_sdkpy_config_create(const char *namespace, const char *kubeconfig, const char *kubecontext, helm_sdkpy_handle *handle_out); + int helm_sdkpy_config_create(const char *namespace, const char *kubeconfig, const char *kubecontext, const char *options_json, helm_sdkpy_handle *handle_out); void helm_sdkpy_config_destroy(helm_sdkpy_handle handle); // Install action diff --git a/helm_sdkpy/actions.py b/helm_sdkpy/actions.py index 3788a17..a65ba3d 100644 --- a/helm_sdkpy/actions.py +++ b/helm_sdkpy/actions.py @@ -43,6 +43,9 @@ class Configuration: - File path: Path to a kubeconfig file (e.g., "/path/to/config.yaml") - YAML string: Kubeconfig content as a YAML string (auto-detected) kubecontext: Kubernetes context to use (default: current context) + plain_http: Use HTTP instead of HTTPS for OCI registries (default: False). + Enable this when using local registries without TLS (e.g., MicroK8s registry). + insecure_skip_tls_verify: Skip TLS certificate verification (default: False) Example: >>> import asyncio @@ -64,6 +67,12 @@ class Configuration: >>> >>> install = Install(config) >>> result = asyncio.run(install.run("my-release", "/path/to/chart")) + >>> + >>> # Using a local HTTP registry (no TLS) + >>> config = Configuration( + ... namespace="default", + ... plain_http=True # For registries without TLS (e.g., local registries) + ... ) """ def __init__( @@ -71,6 +80,8 @@ def __init__( namespace: str = "default", kubeconfig: str | None = None, kubecontext: str | None = None, + plain_http: bool = False, + insecure_skip_tls_verify: bool = False, ): self._lib = get_library() self._handle = ffi.new("helm_sdkpy_handle *") @@ -79,7 +90,16 @@ def __init__( kc_cstr = ffi.new("char[]", kubeconfig.encode("utf-8")) if kubeconfig else ffi.NULL kctx_cstr = ffi.new("char[]", kubecontext.encode("utf-8")) if kubecontext else ffi.NULL - result = self._lib.helm_sdkpy_config_create(ns_cstr, kc_cstr, kctx_cstr, self._handle) + # Build options JSON + options = {} + if plain_http: + options["plain_http"] = plain_http + if insecure_skip_tls_verify: + options["insecure_skip_tls_verify"] = insecure_skip_tls_verify + options_json = json.dumps(options) + options_cstr = ffi.new("char[]", options_json.encode("utf-8")) + + result = self._lib.helm_sdkpy_config_create(ns_cstr, kc_cstr, kctx_cstr, options_cstr, self._handle) check_error(result) self._handle_value = self._handle[0] @@ -99,7 +119,12 @@ def __exit__(self, exc_type, exc_val, exc_tb): return False @classmethod - def from_service_account(cls, namespace: str = "default") -> Configuration: + def from_service_account( + cls, + namespace: str = "default", + plain_http: bool = False, + insecure_skip_tls_verify: bool = False, + ) -> Configuration: """Create configuration using in-cluster ServiceAccount. This is for running inside a Kubernetes pod with a ServiceAccount. @@ -112,6 +137,8 @@ def from_service_account(cls, namespace: str = "default") -> Configuration: Args: namespace: Kubernetes namespace to operate in (default: "default") + plain_http: Use HTTP instead of HTTPS for OCI registries (default: False) + insecure_skip_tls_verify: Skip TLS certificate verification (default: False) Returns: Configuration instance using ServiceAccount authentication @@ -121,8 +148,20 @@ def from_service_account(cls, namespace: str = "default") -> Configuration: >>> config = Configuration.from_service_account(namespace="my-namespace") >>> install = Install(config) >>> result = asyncio.run(install.run("my-release", "oci://ghcr.io/org/chart")) + >>> + >>> # Using a local HTTP registry + >>> config = Configuration.from_service_account( + ... namespace="my-namespace", + ... plain_http=True + ... ) """ - return cls(namespace=namespace, kubeconfig=None, kubecontext=None) + return cls( + namespace=namespace, + kubeconfig=None, + kubecontext=None, + plain_http=plain_http, + insecure_skip_tls_verify=insecure_skip_tls_verify, + ) class Install: