diff --git a/oks_cli/cluster.py b/oks_cli/cluster.py index 75b15ff..9e7ef5b 100644 --- a/oks_cli/cluster.py +++ b/oks_cli/cluster.py @@ -381,7 +381,7 @@ def _create_cluster(project_name, cluster_config, output): @click.option('--cp-multi-az', '-m', is_flag=True, help="Enable control plane multi AZ") @click.option('--dry-run', is_flag=True, help="Client dry-run, only print the object that would be sent, without sending it") @click.option('--output', '-o', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json") -@click.option('--filename', '-f', type=click.File("r"), help="Path to file to use to create the cluster ") +@click.option('--filename', '-f', type=click.File("rb"), help="Path to file to use to create the cluster ") @click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer) @click.option('--set', 'set_fields', multiple=True, help="Set arbitrary nested fields, e.g. auth.oidc.issuer-url=value") @click.pass_context @@ -479,7 +479,7 @@ def cluster_create_command(ctx, project_name, cluster_name, description, admin, @click.option('--control-plane', shell_complete=shell_completions, help="Controlplane plan") @click.option('--dry-run', is_flag=True, help="Client dry-run, only print the object that would be sent, without sending it") @click.option('--output', '-o', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json") -@click.option('--filename', '-f', type=click.File("r"), help="Path to file to use to update the cluster ") +@click.option('--filename', '-f', type=click.File("rb"), help="Path to file to use to update the cluster ") @click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer) @click.option('--set', 'set_fields', multiple=True, help="Set arbitrary nested fields, e.g. auth.oidc.issuer-url=value") @click.pass_context @@ -822,7 +822,7 @@ def nodepool_list(ctx): @click.option('--zone', '-z', multiple=True, help="Provide zone(s)") @click.option('--output', '-o', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json") @click.option('--dry-run', is_flag=True, help="Run without any action") -@click.option('--filename', '-f', type=click.File("r"), help="Path to file to use to create the Nodepool") +@click.option('--filename', '-f', type=click.File("rb"), help="Path to file to use to create the Nodepool") @click.pass_context def setup_worker_pool(ctx, nodepool_name, count, vmtype, zone, output, dry_run, filename): """Create a new nodepool in the cluster, optionally from a file or parameters.""" diff --git a/oks_cli/project.py b/oks_cli/project.py index 95f21d1..80e62e6 100644 --- a/oks_cli/project.py +++ b/oks_cli/project.py @@ -193,7 +193,7 @@ def project_list(ctx, project_name, deleted, plain, msword, uuid, watch, output, @click.option('--disable-api-termination', type=click.BOOL, help="Disable delete action by API") @click.option('--dry-run', is_flag=True, help="Client dry-run, only print the object that would be sent, without sending it") @click.option('--output', '-o', type=click.Choice(["json", "yaml", "silent"]), help="Specify output format, by default is json") -@click.option('--filename', '-f', type=click.File("r"), help="Path to file to use to create the project") +@click.option('--filename', '-f', type=click.File("rb"), help="Path to file to use to create the project") @click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer) @click.option('--set', 'set_fields', multiple=True, help="Set arbitrary nested fields, e.g. auth.oidc.issuer-url=value") @click.pass_context diff --git a/oks_cli/utils.py b/oks_cli/utils.py index 432b8db..f237a3b 100644 --- a/oks_cli/utils.py +++ b/oks_cli/utils.py @@ -1,4 +1,5 @@ import click +import codecs import os import subprocess import logging @@ -753,6 +754,15 @@ def remove_jwt_token(token_type): def detect_and_parse_input(input_data): """Parse input as JSON or YAML; raise error if invalid.""" + if isinstance(input_data, bytes): + try: + if input_data.startswith((codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE)): + input_data = input_data.decode("utf-16") + else: + input_data = input_data.decode("utf-8-sig") + except UnicodeDecodeError: + raise click.BadParameter("Input file is neither valid JSON nor YAML.") + try: return json.loads(input_data) except json.JSONDecodeError: