@metaplay/metaplay-auth 1.9.3-next.851 → 1.9.3-next.852

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -187,7 +187,7 @@ ${p}: ${f}`),d3(d,new Error(`Authentication failed: ${p}: ${f}`)),o.close(),proc
187
187
  ${s}
188
188
  `),(0,Ebe.default)(s)}async function Nbe(t,e){let i=new URLSearchParams;i.set("grant_type","client_credentials"),i.set("client_id",t),i.set("client_secret",e),i.set("scope","openid email profile offline_access");let a=await fetch(MI,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()}),r;if(!a.ok){let s;try{let d=await a.json();s=d&&(d.error_description||d.error||d.message)}catch{try{s=await a.text()}catch{s=void 0}}throw new Error(`Machine login failed: ${s||`HTTP ${a.status}`}`)}try{r=await a.json()}catch(s){throw new Error("Invalid response from authentication server. Please check your network connection and credentials and try again.",{cause:s})}we.debug("Received machine authentication tokens, saving them for future use..."),await lj({access_token:r.access_token});let n=await fetch(`${VA}/api/external/userinfo`,{headers:{Authorization:`Bearer ${r.access_token}`}}),o;if(!n.ok){let s;try{let d=await n.json();s=d&&(d.error_description||d.error||d.message)}catch{try{s=await n.text()}catch{s=void 0}}throw new Error(`Failed to fetch user info: ${s||`HTTP ${n.status}`}`)}try{o=await n.json()}catch(s){throw new Error("Invalid response from user info endpoint. Please check your network connection and try again.",{cause:s})}console.log(`You are now logged in with machine user ${o.given_name} ${o.family_name} (clientId=${t}) and can execute the other commands.`)}async function cs(){try{let t=await WT();if(we.debug("Check if access token still valid..."),tpt(t.access_token)){we.debug("Access token is valid, no need to refresh.");return}if(!t.refresh_token)throw new Error("Cannot refresh an access_token without a refresh_token. With machine users, should just login again instead.");we.debug("Access token is no longer valid, trying to extend the current session with a refresh token.");let e=await Zut(t.refresh_token);await lj({access_token:e.access_token,id_token:e.id_token,refresh_token:e.refresh_token})}catch(t){t instanceof Error&&console.error(t.message),process.exit(1)}}async function Zut(t){let e=new URLSearchParams({grant_type:"refresh_token",refresh_token:t,scope:"openid offline_access",client_id:dj});we.debug("Refreshing tokens...");let i;try{i=await fetch(MI,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:e.toString()})}catch(a){throw we.error(`Failed to refresh tokens via endpoint ${MI}`),we.error("Fetch error details:",a),a.cause?.code==="UNABLE_TO_VERIFY_LEAF_SIGNATURE"?new Error(`Failed to refresh tokens: SSL certificate validation failed for ${MI}. Is someone trying to tamper with your internet connection?`,{cause:a}):new Error(`Failed to refresh tokens via ${MI}: ${a}`,{cause:a})}if(!i.ok){let a=await i.json();throw we.error("Failed to refresh tokens."),we.error(`Error Type: ${a.error}`),we.error(`Error Description: ${a.error_description}`),we.debug("Attempt to clear local state and remove any dangling tokens..."),await cj(),we.debug("Local state cleared and tokens removed."),new Error("Failed extending current session, exiting. Please log in again.")}return await i.json()}async function ept(t,e,i,a){try{return await(await fetch(MI,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`grant_type=authorization_code&code=${a}&redirect_uri=${encodeURIComponent(e)}&client_id=${dj}&code_verifier=${i}&state=${encodeURIComponent(t)}`})).json()}catch(r){throw r instanceof Error&&we.error(`Error exchanging code for tokens: ${r.message}`),r}}async function WT(){try{let t=await Pbe("tokens");if(!t)throw new Error("Unable to load tokens. You need to login first.");return t}catch(t){throw t instanceof Error?new Error(`Error loading tokens: ${t.message}`,{cause:t}):t}}async function lj(t){try{if(we.debug("Received new tokens, verifying..."),!t.access_token)throw new Error("Metaplay token has no access_token. Please log in again and make sure all checkboxes of permissions are selected before proceeding.");we.debug("Token verification completed, storing tokens..."),await Abe("tokens",t),we.debug("Tokens successfully stored."),ipt(t.access_token)}catch(e){throw e instanceof Error?new Error(`Failed to save tokens: ${e.message}`,{cause:e}):e}}async function cj(){try{await Ibe("tokens"),we.debug("Removed tokens.")}catch(t){throw t instanceof Error?new Error(`Error removing tokens: ${t.message}`,{cause:t}):t}}function tpt(t){let e=oj.default.decode(t,{complete:!0});if(!e)throw new Error("Invalid token: unable to decode JWT");let i=e.payload;if(!i.exp)throw new Error("Invalid token: missing expiration time (exp)");if(!i.iss)throw new Error("Invalid token: missing issuer (iss)");let a=Math.floor(Date.now()/1e3);return!(i.exp<a)}function ipt(t){we.debug("Showing access token info...");let e=oj.default.decode(t,{complete:!0});if(!e)throw new Error("Token is corrupted");we.debug(JSON.stringify(e))}var Qc=require("node:fs"),hj=ee(require("node:path"),1),Cr=require("node:process"),Dbe=ee(NH(),1);var Rbe=require("node:child_process");var xI=ee(require("node:path"),1),tl=ee(NH(),1);var kbe=require("node:os"),Hbe=require("node:crypto"),Q3=require("node:fs/promises");function zbe(t){return/^(?=.{1,253}$)(([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,})$/.test(t)}async function Uc(t,e,i){return await new Promise((a,r)=>{let n=(0,Rbe.spawn)(t,e,{stdio:i?.inheritStdio?"inherit":void 0,env:i?.env}),o=[],s=[];n.stdout?.on("data",d=>{o.push(d)}),n.stderr?.on("data",d=>{s.push(d)}),n.on("close",d=>{a({exitCode:d,stdout:o,stderr:s})}),n.on("error",d=>{r(new Error(`Failed to execute command '${t} ${e.join(" ")}': ${d.message}`))})})}function Vbe(){let t=(i,a)=>xI.default.basename(i,xI.default.extname(i))===a;return!!(t(process.argv[0],"npx")||process.argv[1]?.includes(`${xI.default.sep}_npx${xI.default.sep}`)||process.env.npm_execpath&&t(process.env.npm_execpath,"npx")||process.env._&&t(process.env._,"npx"))}function qT(...t){return xI.default.join(...t).replaceAll("\\","/")}function _be(t){return t.replace(/\/+$/,"")}async function Obe(t,e){we.debug(`Fetching Helm chart versions from '${t}'...`);let a=await(await fetch(`${t}/index.yaml`)).text();return Dx.load(a).entries[e].map(o=>o.version).filter(o=>tl.gte(o,"0.5.0"))}function Bbe(t,e){let i=e?t.filter(r=>tl.satisfies(r,e)):t;return we.debug(`Satisfying versions: ${i.join(", ")}`),i.length===0?null:i.sort(tl.rcompare)[0]}async function uj(){try{let t=await Uc("helm",["version","--short"]);if(t.exitCode!==0)throw new Error(`Helm version command failed with exit code ${t.exitCode}: ${t.stderr.join("")}`);let e=t.stdout.join("").trim(),a=/v(\d+\.\d+\.\d+)/.exec(e);if(!a)throw new Error(`Could not parse Helm version from output: ${e}`);let r=a[1];we.debug(`Detected Helm version: ${r}`);let n="3.18.0",o="3.18.4";if(!tl.gte(r,n))throw new Error(`Locally installed Helm version ${r} is too old. Use Helm v${o} which is the latest compatible version`);if(!tl.lte(r,o))throw new Error(`Locally installed Helm version ${r} is too new. Use Helm v${o} which is the latest compatible version`);we.debug(`Helm version ${r} is compatible`)}catch(t){throw t instanceof Error&&t.message.includes("ENOENT")?new Error("Helm is not installed or not found in PATH. Please install Helm version >= 3.18.0 and < 3.18.5",{cause:t}):t}}async function F3(t,e){let i=qT((0,kbe.tmpdir)(),(0,Hbe.randomBytes)(20).toString("hex"));we.debug(`Write temporary kubeconfig in ${i}`),await(0,Q3.writeFile)(i,t,{mode:384}),e=e.concat(["--kubeconfig",i]);try{let a;try{a=await Uc("helm",e)}catch(r){let n=r instanceof Error?r.message:String(r);throw new Error(`Failed to execute 'helm': ${n}. You need to have Helm v3 installed to deploy a game server with metaplay-auth.`,{cause:r})}if(a.exitCode!==0)throw new Error(`Helm invocation failed with exit code ${a.exitCode}: ${String(a.stderr)}`);return a}finally{await(0,Q3.unlink)(i)}}async function pj(t){let e=await F3(t,["ls","-o=json"]),a=JSON.parse(e.stdout.join("")).filter(r=>r.chart.startsWith("metaplay-gameserver-"));if(a.length===0)return null;if(a.length===1)return a[0];throw new Error(`Multiple game server Helm charts installed: ${JSON.stringify(a,void 0,2)}`)}function apt(t){let e=["buildx","buildkit"];if(!t)return process.env.BITBUCKET_PIPELINE_UUID?"buildkit":"buildx";if(!e.includes(t))throw new Error(`Invalid Docker build engine '${t}', must be one of: ${e.join(", ")}`);return t}function rpt(t){let e=(0,Qc.readFileSync)(t,"utf8"),i=/LABEL\s+io\.metaplay\.sdk_version\s*=\s*([\d.]+(?:-[\w.]+)?)(?:[\s\\]*)/.exec(e);if(!i)throw Error("Unable to parse SDK version from Dockerfile.server");return i[1]}function Wbe(t){t.command("build-image [extraArgs...]").description("build the game server docker image").option("-t, --image-tag <image-tag>",'tag for the output image, eg, "myserver:d08747679d"',"gameserver:<timestamp>").option("--sdk-root <directory>","relative path to the MetaplaySDK directory","MetaplaySDK").option("--project-root <directory>","relative path to the project root (where Backend/ directory is located)",".").option("--backend-dir <directory>","[for legacy projects] name of the Backend/ directory","Backend").option("--shared-code-dir <directory>","path to the shared code directory of the project, relative to --project-root","Assets/SharedCode").option("--engine <engine>","docker build engine to use (buildx or buildkit), auto-detected if not specified","buildx").option("--architecture <architecture>","target platform architecture (amd64 or arm64)","amd64").option("--build-number <build-number>","number of this build (eg, 153)").option("--commit-id <commit-id>","commit id of this build (eg, d08747679d1e7fc9c1c685b396636da689ae476d)").action(async(e,i)=>{let a=i.imageTag;a=a.replace("<timestamp>",Math.floor(+new Date/1e3).toString()),console.log(`Building docker image '${a}'..`),a.endsWith(":latest")&&(console.error(`Building docker image with "latest" tag is not allowed as it won't update the cloud environments reliably. Use commit id like git sha or timestamp instead.`),(0,Cr.exit)(1)),e.length!==0&&console.log(`Extra args to docker: ${JSON.stringify(e)}`);let r=i.sdkRoot.replaceAll("\\","/");hj.default.isAbsolute(r)&&(console.error(`The --sdk-root (${r}) is an absolute path, please specify a relative path instead`),(0,Cr.exit)(2)),r.startsWith("..")&&(console.error(`The --sdk-root (${r}) path cannot point outside the current directory (i.e., cannot start with '..')`),(0,Cr.exit)(2)),(0,Qc.existsSync)(r)||(console.error(`The Metaplay SDK directory '${r}' does not exist, specify correct directory with --sdk-root!`),(0,Cr.exit)(2));let n=qT(r,"Dockerfile.server");(0,Qc.existsSync)(n)||(console.error(`Cannot locate Dockerfile.server at ${n} -- check that the --sdk-root path points to the MetaplaySDK directory!`),(0,Cr.exit)(2));let o=rpt(n);console.log(`Metaplay SDK version: ${o}`),Dbe.gte(o,"32.0.0")&&(console.error("ERROR: metaplay-auth is not compatible with Metaplay SDK Release 32 and above."),console.error("See the Release 32 migration guide for more details:"),console.error(" https://docs.metaplay.io/miscellaneous/sdk-updates/release-notes/release-32.html#"),(0,Cr.exit)(2));let s=i.projectRoot.replaceAll("\\","/");hj.default.isAbsolute(r)&&(console.error(`The --project-root (${s}) is an absolute path, please specify a relative path instead`),(0,Cr.exit)(2)),s.startsWith("..")&&(console.error(`The --project-root (${s}) path cannot point outside the current directory (i.e., cannot start with '..')`),(0,Cr.exit)(2)),(0,Qc.existsSync)(s)||(console.error(`The project root directory '${s}' does not exist, specify correct directory with --project-root`),(0,Cr.exit)(2));let d=qT(s,i.backendDir);(0,Qc.existsSync)(d)||(console.error(`Unable to find project backend in '${d}', check that --project-root is correct!`),(0,Cr.exit)(2));let l=qT(s,i.sharedCodeDir);(0,Qc.existsSync)(l)||(console.error(`The shared code directory (${l}) does not exist, make sure the --shared-code-dir points to the directory where shared source code is located!`),(0,Cr.exit)(2));let c=["amd64","arm64"];c.includes(i.architecture)||(console.error(`Invalid architecture '${i.architecture}' specified, must be one of ${JSON.stringify(c)}`),(0,Cr.exit)(2));let u=`linux/${i.architecture}`,p=i.commitId;p||(p=process.env.GIT_COMMIT??process.env.GITHUB_SHA??process.env.CI_COMMIT_SHA??process.env.CIRCLE_SHA1??process.env.TRAVIS_COMMIT??process.env.BUILD_SOURCEVERSION??process.env.BITBUCKET_COMMIT??process.env.BUILD_VCS_NUMBER??process.env.BUILDKITE_COMMIT??process.env.DRONE_COMMIT_SHA??process.env.SEMAPHORE_GIT_SHA,p?console.log(`Using auto-detected commit id: ${p}`):console.warn('Warning: Failed to auto-detect commit id, please specify with "--commit-id <git-sha>"'));let f=i.buildNumber;f||(f=process.env.BUILD_NUMBER??process.env.GITHUB_RUN_NUMBER??process.env.CI_PIPELINE_IID??process.env.CIRCLE_BUILD_NUM??process.env.TRAVIS_BUILD_NUMBER??process.env.BUILD_BUILDNUMBER??process.env.BITBUCKET_BUILD_NUMBER??process.env.BUILD_NUMBER??process.env.BUILDKITE_BUILD_NUMBER??process.env.DRONE_BUILD_NUMBER??process.env.SEMAPHORE_BUILD_NUMBER,f?console.log(`Using auto-detected build number: ${f}`):console.warn('Warning: Failed to auto-detect build number, please specify with "--build-number <build-number>"')),console.log("Resolve docker build engine...");let m=apt(i.engine);console.log(`Using docker build engine: ${m}`);let y=await Uc("docker",["info"],{inheritStdio:!1});y.exitCode!==0&&(console.error(`Failed to invoke docker, please make sure that docker is installed and running (exit code = ${y.exitCode})`),(0,Cr.exit)(1)),m==="buildx"&&(await Uc("docker",["buildx","version"],{inheritStdio:!1})).exitCode!==0&&(console.warn("Warning: Docker buildx is not supported on this machine, falling back to --engine=buildkit"),m="buildkit");let g=m==="buildkit"?{DOCKER_BUILDKIT:"1"}:{},S=(m==="buildx"?["buildx","build","--load"]:["build"]).concat(["--pull"]).concat(["-t",a]).concat(["-f",n]).concat(["--platform",u]).concat(f?["--build-arg",`BUILD_NUMBER=${f}`]:[]).concat(p?["--build-arg",`COMMIT_ID=${p}`]:[]).concat(["--build-arg",`SDK_ROOT=${r}`]).concat(["--build-arg",`PROJECT_ROOT=${s}`]).concat(["--build-arg",`SHARED_CODE_DIR=${i.sharedCodeDir.replaceAll("\\","/")}`]).concat(["--build-arg",`BACKEND_DIR=${i.backendDir.replaceAll("\\","/")}`]).concat(e).concat(["."]);console.log(`Execute: docker ${S.join(" ")}`);let v;try{v=await Uc("docker",S,{inheritStdio:!0,env:{...process.env,...g,DOCKER_CLI_HINTS:"false"}}),v.exitCode!==0&&(console.error(`Docker build failed with exit code ${v.exitCode}`),(0,Cr.exit)(v.exitCode)),console.log(`Successfully built docker image '${a}'!`)}catch(E){console.error(`Failed to invoke docker build: ${E instanceof Error?E.message:String(E)}`),(0,Cr.exit)(1)}})}var LT=require("node:fs/promises"),qbe=ee(require("node:os"),1),Lbe=ee(require("node:path"),1),$3=require("node:process"),Ube=require("node:dns"),Qbe=ee(require("node:tls"),1);async function Fbe(t,e){we.debug(`Fetching game server pods from Kubernetes: namespace=${e}`);let i={namespace:e,labelSelector:"app=metaplay-server"};try{return(await t.listNamespacedPod(i)).items}catch(a){throw console.error("Failed to fetch pods from Kubernetes:",a),new Error("Failed to fetch pods from Kubernetes",{cause:a})}}function npt(t){let e=t.status?.containerStatuses;if(!e||e.length===0)return{phase:"Unknown",message:"Unable to determine pod container statuses: pod.status.containerStatuses is empty"};let i=e.find(d=>d.name==="shard-server");if(!i)return{phase:"Unknown",message:"Unable to find container shard-server from the pod"};we.debug(`Container status for pod ${t.metadata?.name??"<unnamed>"}: ${JSON.stringify(i,void 0,2)}`);let a=i.state;if(!a)return{phase:"Unknown",message:"Unable to get container state"};let r=i.name;if(a.running)return i.ready?{phase:"Ready",message:`Container ${r} is in ready phase`,details:a.running}:{phase:"Running",message:`Container ${r} is in running phase`,details:a.running};let n=["CrashLoopBackOff","Error","ImagePullBackOff","CreateContainerConfigError","OOMKilled","ContainerCannotRun","BackOff","InvalidImageName"],o=["Init","Pending","PodInitializing"],s=i.lastState;if(s&&s.terminated){if(a.waiting){let d=a.waiting.reason;return d&&n.includes(d)?{phase:"Failed",message:`Container ${r} is in waiting state, reason=${d}`,details:a.waiting}:d&&o.includes(d)?{phase:"Pending",message:`Container ${r} is in waiting state, reason=${d}`,details:a.waiting}:{phase:"Unknown",message:`Container ${r} is in waiting state, reason=${d}`,details:a.waiting}}else{if(a.running)return{phase:"Pending",message:`Container ${r} is in running state`,details:a.running};if(a.terminated)return{phase:"Failed",message:`Container ${r} is in terminated state`,details:a.terminated}}return{phase:"Failed",message:`Container ${r} previous launch failed with exitCode=${s.terminated.exitCode} and reason=${s.terminated.reason}`,details:s.terminated}}return we.debug("Game server pod container in unknown state:",a),{phase:"Unknown",message:"Container in unknown state",details:a}}function opt(t){let e=t.status?.conditions;if(!e||e.length===0)return{phase:"Unknown",message:"Unable to determine pod status: pod.status.conditions is empty",details:t.status};let i=e.find(o=>o.type==="PodScheduled");if(i?.status!=="True")return{phase:"Pending",message:`Pod has not yet been scheduled on a node: ${i?.message}`,details:i};let a=e.find(o=>o.type==="Initialized");if(a?.status!=="True")return{phase:"Pending",message:`Pod has not yet been initialized: ${a?.message}`,details:a};let r=e.find(o=>o.type==="ContainersReady");if(r?.status!=="True")return r?.reason==="ContainersNotReady"?npt(t):{phase:"Pending",message:`Pod containers are not yet ready: ${r?.message}`,details:r};let n=e.find(o=>o.type==="Ready");return n?.status!=="True"?{phase:"Pending",message:`Pod is not yet ready: ${n?.message}`,details:n}:{phase:"Ready",message:"Pod is ready to serve traffic"}}function spt(t){let e=t.status?.conditions?.find(i=>i.type==="PodScheduled");return e?.status!=="False"?null:e?.reason??null}function dpt(t){let e=spt(t);return e?{phase:"Pending",message:`Pod is still in Pending phase. Reason: ${e}`}:{phase:"Pending",message:"Pod is still in Pending phase"}}function lpt(t){let e=t.spec?.containers?.find(r=>r.name==="shard-server");if(!e||!e.image)return null;let[i,a]=e.image.split(":");return a}function cpt(t,e){if(!t)return{phase:"Unknown",message:"Received empty pod from Kubernetes"};if(!t.status)return{phase:"Unknown",message:"Unable to access pod.status from Kubernetes"};if(e!==null){let a=lpt(t);if(a!==e)return{phase:"Pending",message:`Pod has old image tag ${a??"unknown"}, expecting ${e}.`}}let i=t.status?.phase;switch(i){case"Pending":return dpt(t);case"Running":return opt(t);case"Succeeded":return{phase:"Unknown",message:"Pod has unexpectedly terminated (with a clean exit status)"};case"Failed":return{phase:"Unknown",message:"Pod has unexpectedly terminated (with a failure exit status)"};case"Unknown":default:return{phase:"Unknown",message:`Invalid pod.status.phase: ${i}`}}}async function upt(t,e){let i=e.metadata?.name;we.debug(`Fetching logs for pod '${i}'..`);let a=e.metadata?.namespace,r=e.spec?.containers[0].name;if(!i||!a||!r)throw new Error("Unable to determine pod and container metadata");let n={name:i,namespace:a,container:r,pretty:"true",previous:!1,tailLines:100,timestamps:!0};try{return await t.readNamespacedPodLog(n)}catch(o){throw console.log("Failed to fetch pod logs from Kubernetes:",o),new Error("Failed to fetch pod logs from Kubernetes",{cause:o})}}async function ppt(t,e,i){let a=cpt(e,i),r=e.metadata?.name??"<unable to resolve name>";if(a.phase==="Failed"){let n=await upt(t,e);console.log(`Logs from pod '${r}':
189
189
  ${n}`)}return we.debug(`Pod ${r} status: ${JSON.stringify(a,void 0,2)}`),a}async function fj(t){await new Promise(e=>{setTimeout(e,t)})}function j3(t,e){return t.some(i=>i.phase===e)}function hpt(t,e){return t.every(i=>i.phase===e)}async function fpt(t,e,i){let a=Date.now()+18e4,r=e.makeApiClient(j2);for(;;){let n=await Fbe(r,t);if(we.debug(`Found ${n?.length} pod(s) deployed in Kubernetes`),n.length>0){let o=await Promise.all(n.map(async s=>await ppt(r,s,i)));if(we.debug(`Pod phases: ${o.map(s=>s.phase).toString()}`),j3(o,"Failed")){we.error(`Game server start failed with pod statuses: ${JSON.stringify(o,void 0,2)}`),console.log("Game server failed to start due to the pods not starting properly! See above for details.");for(let s=0;s<n.length;s+=1){let d=o[s],l=d.phase!=="Ready"?` -- ${d.message}`:"";console.log(` ${n[s].metadata?.name}: ${d.phase}${l}`)}return}else if(j3(o,"Unknown")||j3(o,"Pending")||j3(o,"Running")){console.log("Waiting for pod(s) to be ready...");for(let s=0;s<n.length;s+=1){let d=o[s],l=d.phase!=="Ready"?` -- ${d.message}`:"";console.log(` ${n[s].metadata?.name}: ${d.phase}${l}`)}}else if(hpt(o,"Ready")){console.log("Game server pod(s) are up and ready to serve!");return}else{console.log("Deployment in inconsistent state, waiting...");for(let s=0;s<n.length;s+=1){let d=o[s],l=d.phase!=="Ready"?` -- ${d.message}`:"";console.log(` ${n[s].metadata?.name}: ${d.phase}${l}`)}}}if(Date.now()>=a)throw new Error("Timeout while waiting for the server pods be get ready");await fj(2e3)}}async function mpt(t){let e=Date.now()+9e5;for(;;)try{let i=await Ube.promises.lookup(t);console.log(`Successfully resolved domain ${t} to:`,i);return}catch(i){if(Date.now()>e)throw new Error(`Could not resolve domain ${t} before timeout.`,{cause:i});i instanceof Error&&i.code==="ENOTFOUND"?console.log(`Waiting for domain name ${t} to propagate... This can take up to 15 minutes on the first deploy.`):console.log(`Failed to resolve ${t}: ${String(i)}. Retrying...`),await fj(5e3)}}async function ypt(t,e){let i=Date.now()+3e5;for(;Date.now()<i;){try{await new Promise((a,r)=>{let n=Qbe.default.connect({host:t,port:e},()=>{n.authorized?(console.log("TLS handshake completed, waiting to receive data from the server..."),n.once("data",o=>{let s=Array.from(o).map(d=>d.toString(16).padStart(2,"0"));console.log(`Received ${o.length} bytes from server: ${s.join(" ")}`),n.end(),a()})):(n.end(),r(new Error(`TLS handshake failed: ${String(n.authorizationError)}`)))});n.on("error",r),n.setTimeout(5e3,()=>{n.end(),r(new Error("Timeout while waiting for data after handshake"))})}),console.log(`Successfully connected to the target environment ${t}:${e}`);return}catch(a){console.log(`Attempt failed, retrying: ${String(a)}`)}await fj(1e3)}throw new Error(`Timeout reached while waiting to establish connection to ${t}:${e}`)}async function mj(t,e,i){console.log("Waiting for game server pods to be ready..."),await fpt(t.deployment.kubernetes_namespace,e,i),console.log(`Resolving the domain name '${t.deployment.server_hostname}' of the server...`),await mpt(t.deployment.server_hostname);let a=9339;console.log(`Connecting to the server at ${t.deployment.server_hostname}:${a}...`),await ypt(t.deployment.server_hostname,a)}async function jbe(t,e){we.debug("Get kubeconfig");let i,a=new Hc;try{i=await t.getKubeConfigWithEmbeddedCredentials(),a.loadFromString(i)}catch(l){let c=l instanceof Error?l.message:String(l);console.error(`Failed to fetch kubeconfig for environment: ${c}`),(0,$3.exit)(1)}we.debug("Get environment details");let n=(await t.getEnvironmentDetails()).deployment.kubernetes_namespace;we.debug("Get running game server pods");let o=a.makeApiClient(j2),s=await Fbe(o,n);if(!e)if(s.length===1){let l=s[0].metadata;if(!l?.name)throw new Error("Unable to resolve name for the Kubernetes pod!");e=l.name}else{let l=s.map(c=>c.metadata?.name).join(", ");console.error(`Multiple game server pods running: ${l}
190
- Please specify which you want to debug.`),(0,$3.exit)(1)}let d=Lbe.default.join(qbe.default.tmpdir(),`temp-kubeconfig-${Date.now()}`);try{we.debug(`Write temporary kubeconfig to ${d}`),await(0,LT.writeFile)(d,i);let l=[`--kubeconfig=${d}`,`--namespace=${n}`,"debug",e,"-it","--profile=general","--image=metaplay/diagnostics:latest","--target=shard-server"];console.log(`Execute: kubectl ${l.join(" ")}`);let c=await Uc("kubectl",l,{inheritStdio:!0});we.debug("Delete temporary kubeconfig"),await(0,LT.unlink)(d),c?.exitCode!==0&&(console.error(`kubectl failed failed with exit code ${c.exitCode}`),(0,$3.exit)(c.exitCode))}catch(l){let c=l instanceof Error?l.message:String(l);console.error(`Failed to execute 'kubectl': ${c}. You need to have kubectl installed to debug a game server with metaplay-auth.`),we.debug("Delete temporary kubeconfig"),await(0,LT.unlink)(d)}}var r_=ee(z6e(),1);var a_=class extends Error{response;constructor(e,i,a){super(`Failed to fetch ${e} ${i}: ${a.statusText}, response code=${a.status}`),this.response=a}},bE=class{accessToken;humanId;stackApiBaseUrl;constructor(e,i,a){this.accessToken=e,this.humanId=i,this.stackApiBaseUrl=a}async fetchJson(e,i){let a=await fetch(e,{method:i,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}});if(a.status!==200)throw new a_(i,e,a);return await a.json()}async fetchText(e,i){let a;try{a=await fetch(e,{method:i,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}})}catch(r){throw we.error(`Failed to fetch ${i} ${e}:`,r),r.cause?.code==="UNABLE_TO_VERIFY_LEAF_SIGNATURE"?new Error(`Failed to to fetch ${e}: SSL certificate validation failed. Is someone trying to tamper with your internet connection?`,{cause:r}):new Error(`Failed to fetch ${e}: ${r}`,{cause:r})}if(a.status!==200)throw new Error(`Failed to fetch ${i} ${e}: ${a.statusText}`);return await a.text()}async getAwsCredentials(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/aws`;return we.debug(`Fetching AWS credentials from ${e}...`),await this.fetchJson(e,"POST")}async getKubeConfigWithEmbeddedCredentials(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/k8s`;return we.debug(`Getting KubeConfig from ${e}...`),await this.fetchText(e,"POST")}async getKubeConfigWithExecCredential(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/k8s?type=execcredential`;we.debug(`Getting Kubernetes KubeConfig from ${e}...`);let i;try{i=await this.fetchJson(e,"POST")}catch(c){if(c instanceof a_){if(c.response.status===404)throw new Error(`Environment ${this.humanId} does not exist.`,{cause:c});if(c.response.status===403)throw new Error(`Your account does not have permissions to access environment ${this.humanId}.`,{cause:c})}let u=c instanceof Error?c.message:String(c);throw new Error(`Failed to fetch Kubernetes KubeConfig: ${u}`,{cause:c})}if(!i.spec.cluster)throw new Error("Received kubeExecCredential with missing spec.cluster");let r=(await this.getEnvironmentDetails()).deployment?.kubernetes_namespace;if(!r)throw new Error("Environment details did not contain a valid Kubernetes namespace");let o=(await xbe(this.accessToken)).email,s="metaplay-auth",d=["get-kubernetes-execcredential"].concat(["--stack-api",this.stackApiBaseUrl]).concat([this.humanId]);Vbe()&&(s="npx",d=["--yes","@metaplay/metaplay-auth@latest",...d]);let l={apiVersion:"v1",kind:"Config","current-context":this.humanId,clusters:[{cluster:{"certificate-authority-data":i.spec.cluster.certificateAuthorityData,server:i.spec.cluster.server},name:i.spec.cluster.server}],contexts:[{context:{cluster:i.spec.cluster.server,namespace:r,user:o},name:this.humanId}],users:[{name:o,user:{exec:{apiVersion:"client.authentication.k8s.io/v1beta1",command:s,args:d,interactiveMode:"Never"}}}]};return xL(l)}async getKubeExecCredential(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/k8s?type=execcredential`;return we.debug(`Getting Kubernetes ExecCredential from ${e}...`),await this.fetchText(e,"POST")}async getEnvironmentDetails(){let e=`${this.stackApiBaseUrl}/v0/deployments/${this.humanId}`;return we.debug(`Getting environment details from ${e}...`),await this.fetchJson(e,"GET")}async getDockerCredentials(){we.debug("Get environment info");let e=await this.getEnvironmentDetails();we.debug("Get AWS credentials from Metaplay");let i=await this.getAwsCredentials();we.debug("Create ECR client");let a=new r_.ECRClient({credentials:{accessKeyId:i.AccessKeyId,secretAccessKey:i.SecretAccessKey,sessionToken:i.SessionToken},region:e.deployment.aws_region});we.debug("Fetch ECR login credentials from AWS");let r=new r_.GetAuthorizationTokenCommand({}),n=await a.send(r);if(!n.authorizationData||n.authorizationData.length===0||!n.authorizationData[0].authorizationToken||!n.authorizationData[0].proxyEndpoint)throw new Error("Received an empty authorization token response for ECR repository");we.debug("Parse ECR response");let o=n.authorizationData[0].proxyEndpoint,s=n.authorizationData[0].authorizationToken,d=Buffer.from(s,"base64").toString(),[l,c]=d.split(":");return we.debug(`ECR: username=${l}, proxyEndpoint=${o}`),{username:l,password:c,registryUrl:o}}};var V6e="1.9.3-next.851";var D6e;function vMt(t,e){let i="https://infra.p1.metaplay.io/stackapi",a=e.split(".")[0];return new bE(t.access_token,a,i)}async function CMt(t,e,i,a){let r=`${VA}/api/v1/environments/with-slugs?organization_slug=${e}&project_slug=${i}&environment_slug=${a}`;we.debug(`Getting environment information from portal: ${r}...`);let n=await fetch(r,{method:"GET",headers:{Authorization:`Bearer ${t.access_token}`,"Content-Type":"application/json"}});await W6e(n);let o=await n.json();return we.debug(`Portal returned environment info: ${JSON.stringify(o,void 0,2)}`),o}async function AMt(t,e){let i=`${VA}/api/v1/environments?human_id=${e}`;we.debug(`Getting environment information from portal: ${i}...`);let a=await fetch(i,{method:"GET",headers:{Authorization:`Bearer ${t.access_token}`,"Content-Type":"application/json"}});await W6e(a);let r=await a.json();if(we.debug(`Portal returned environment infos: ${JSON.stringify(r,void 0,2)}`),r.length===0)throw new Error(`Environment ${e} does not exist or your account does not have permissions to access this environment`);return r[0]}async function W6e(t){if(!t.ok){let e=await t.json();throw typeof e=="object"&&e!==null&&"message"in e&&typeof e.message=="string"?new Error(e.message):new Error(`Failed to fetch environment details with error ${t.status}: ${JSON.stringify(e)}`)}}async function _6e(t,e,i,a){let r=await CMt(t,e,i,a),n=r.stack_domain;if(!n)throw new Error(`The environment ${r.human_id} has not been provisioned to any infra stack (environment.stack_domain is empty).`);return new bE(t.access_token,r.human_id,`https://infra.${n}/stackapi`)}async function PMt(t,e){let i=D6e;if(!i){let a=await AMt(t,e);if(!a.stack_domain)throw new Error(`The environment ${a.human_id} has not been provisioned to any infra stack (environment.stack_domain is empty).`);i=`https://infra.${a.stack_domain}/stackapi`}return new bE(t.access_token,e,i)}async function xl(t,e){let i=await WT();if(t){if(zbe(t))return console.warn('Using the FQDN to specify target environment is deprecated. Use the "<organization>-<project>-<environment>" slugs instead.'),vMt(i,t);{let a=t.split("-");if(a.length===2||a.length===4)return await PMt(i,t);if(a.length===3)return await _6e(i,a[0],a[1],a[2]);throw new Error(`Invalid environment address syntax '${t}'. Specify either the environment's id (eg, "delicious-elephant") or its slug tripled (eg, "<organization>-<project>-<environment>")`)}}else{if(e.organization&&e.project&&e.environment)return console.warn(`Warning: Specifying the target environment with -o (--organization), -p (--project), and -e (--environment) is deprecated! Use the '${e.organization}-${e.project}-${e.environment}' syntax instead.`),await _6e(i,e.organization,e.project,e.environment);throw new Error("Could not determine target environment from arguments: You need to specify either an environment FQDN or an organization, project, and environment. Run this command with --help flag for more information.")}}var Nr=new QY;Nr.name("metaplay-auth").description("Authenticate with Metaplay and get AWS and Kubernetes credentials for game servers.").version(V6e).option("-d, --debug","enable debug output").option("--portal-base-url <portal-base-url>","override the default portal base URL (e.g. http://localhost:3000)").option("--stack-api <stack-api-base-url>","override the default stack API base URL (e.g. https://infra.p1.metaplay.io/stackapi/)").hook("preAction",t=>{let e=t.opts();e.debug?rj(0):rj(10),console.warn("Warning: The metaplay-auth CLI is deprecated and will only receive critical updates."),console.warn(" Please upgrade to Metaplay SDK release 32 or newer and the new Metaplay CLI (https://github.com/metaplay/cli).");let i=e.portalBaseUrl??process.env.AUTHCLI_PORTAL_BASEURL;i&&(we.debug(`Using portal URL override: ${i}`),lbe(i)),e.stackApi&&(D6e=e.stackApi)});Nr.command("login").description("login to your Metaplay account").action(async()=>{await Tbe()});Nr.command("machine-login").description("login to the Metaplay cloud using a machine account (using credentials in environment variable METAPLAY_CREDENTIALS)").option("--dev-credentials","machine user credentials to use, only for dev purposes, use METAPLAY_CREDENTIALS env variable for better safety!").action(async t=>{try{let e;if(t.devCredentials)e=t.devCredentials;else if(e=process.env.METAPLAY_CREDENTIALS,!e||e==="")throw new Error("Unable to find the credentials, the environment variable METAPLAY_CREDENTIALS is not defined!");let i=e.indexOf("+");if(i===-1)throw new Error("Invalid format for credentials, you should copy-paste the value from the developer portal verbatim");let a=e.substring(0,i),r=e.substring(i+1);await Nbe(a,r)}catch(e){console.error(`Error during machine login: ${e instanceof Error?e.message:String(e)}`),(0,Yr.exit)(1)}});Nr.command("logout").description("log out of your Metaplay account").action(async()=>{console.log("Logging out by removing locally stored tokens...");try{await cj(),console.log("Done! You are now logged out.")}catch(t){we.debug("Invocation failed with error:",t),t instanceof Error&&console.error(`Error logging out: ${t.message}`),(0,Yr.exit)(1)}});Nr.command("show-tokens").description("show loaded tokens").hook("preAction",async()=>{await cs()}).action(async()=>{try{let t=await WT();console.log(JSON.stringify(t,void 0,2))}catch(t){we.debug("Invocation failed with error:",t),t instanceof Error&&console.error(`Error showing tokens: ${t.message}`),(0,Yr.exit)(1)}});Nr.command("get-kubeconfig").description("get kubeconfig for target environment").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").option("-t, --type <credentials-type>","type of credentials handling in kubeconfig (static or dynamic)").option("--output <kubeconfig-path>","path of the output file where to write kubeconfig (written to stdout if not specified)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let i=await xl(t,e),r=!!(await WT()).refresh_token,n=e.type??(r?"dynamic":"static"),o;if(n==="dynamic")we.debug("Fetching kubeconfig with execcredential"),o=await i.getKubeConfigWithExecCredential();else if(n==="static")we.debug("Fetching kubeconfig with embedded secret"),o=await i.getKubeConfigWithEmbeddedCredentials();else throw new Error('Invalid credentials type; must be either "static" or "dynamic"');e.output?(we.debug(`Writing kubeconfig to file ${e.output}`),await(0,O6e.writeFile)(e.output,o,{mode:384}),console.log(`Wrote kubeconfig to ${e.output}`)):console.log(o)}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error("Error getting KubeConfig:",i.message),(0,Yr.exit)(1)}});Nr.command("get-kubernetes-execcredential").description("[internal] get kubernetes credentials in execcredential format (used from the generated kubeconfigs)").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let a=await(await xl(t,e)).getKubeExecCredential();console.log(a)}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error(`Error getting Kubernetes ExecCredential: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("get-aws-credentials").description("get AWS credentials for target environment").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").option("-f, --format <format>","output format (json or env)","json").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{if(e.format!=="json"&&e.format!=="env")throw new Error("Invalid format; must be one of json or env");let a=await(await xl(t,e)).getAwsCredentials();e.format==="env"?(console.log(`export AWS_ACCESS_KEY_ID=${a.AccessKeyId}`),console.log(`export AWS_SECRET_ACCESS_KEY=${a.SecretAccessKey}`),console.log(`export AWS_SESSION_TOKEN=${a.SessionToken}`)):console.log(JSON.stringify({...a,Version:1}))}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error(`Error getting AWS credentials: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("get-environment").description("get details of an environment").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let a=await(await xl(t,e)).getEnvironmentDetails();console.log(JSON.stringify(a,void 0,2))}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error(`Error getting environment details: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("push-docker-image").description("push docker image into the target environment image registry").argument("environment","target environment (e.g. metaplay-idler-develop or tiny-squids)").argument("image-name","full name of the docker image to push (eg, the gameserver:<sha>)").hook("preAction",async()=>{await cs()}).action(async(t,e,i)=>{try{console.log(`Pushing docker image ${e} to target environment ${t}...`);let a=await xl(t,i);we.debug("Get environment info");let r=await a.getEnvironmentDetails();we.debug("Get docker credentials");let n=await a.getDockerCredentials();if(!e)throw new Error("Must specify a valid docker image name as the image-name argument");let o=e.split(":");if(o.length!==2||o[0].length===0||o[1].length===0)throw new Error(`Invalid docker image name '${e}', expecting the name in format 'name:tag'`);let s=o[1],d=e,l=r.deployment.ecr_repo,c=`${l}:${s}`,u=new EY.default,p=u.getImage(d);d!==c&&(we.debug(`Tagging image ${d} as ${c}`),await p.tag({repo:l,tag:s})),we.debug(`Push image ${c}`);let f=u.getImage(c),m={username:n.username,password:n.password,serveraddress:n.registryUrl},y=await f.push({authconfig:m,tag:i.imageTag});we.debug("Following image push stream..."),await new Promise((g,w)=>{u.modem.followProgress(y,(S,v)=>{S?(we.debug("Failed to push docker image to target repository:",S),w(S)):(we.debug("Successfully finished pushing docker image"),g(v))},()=>{})}),console.log(`Successfully pushed docker image to ${c}!`)}catch(a){we.debug("Invocation failed with error:",a),a instanceof Error&&console.error(`Failed to push docker image: ${a.message}`),(0,Yr.exit)(1)}});Nr.command("deploy-server").description("deploy a game server image to target environment").argument("environment","target environment (e.g. metaplay-idler-develop or tiny-squids)").argument("image-tag","docker image tag to deploy (usually the SHA of the build)").requiredOption("-f, --values <path-to-values-file>","path to Helm values file to use for this deployment").option("--local-chart-path <path-to-chart-directory>","path to local Helm chart directory (to use a chart from local disk)").option("--helm-chart-repo <url>","override the URL of the Helm chart repository (eg, https://customchartrepo.domain.com)").option("--helm-chart-version <version>","the Helm chart version to use (eg, 0.6.0)").option("--deployment-name","Helm deployment name to use","gameserver").hook("preAction",async()=>{await cs()}).action(async(t,e,i)=>{try{console.log(`Deploying server to ${t} with image tag ${e}...`);let a=await xl(t,i),r=await a.getEnvironmentDetails();if(!e)throw new Error("Must specify a valid docker image tag as the image-tag argument, usually the SHA of the build");if(e.includes(":"))throw new Error("Invalid image tag: only specify the tag, not the repository name.");if(!i.deploymentName)throw new Error(`Invalid Helm deployment name '${i.deploymentName}'; specify one with --deployment-name or use the default`);let n=await a.getDockerCredentials(),o=new EY.default,d=`${r.deployment.ecr_repo}:${e}`;we.debug(`Fetch docker image labels for ${d}`);let l;try{l=(await o.getImage(d).inspect()).Config.Labels||{}}catch(E){let A=E instanceof Error?E.message:String(E);we.debug(`Failed to resolve docker image metadata from local image ${d}: ${A}`)}if(l===void 0){try{console.log(`Image ${d} not found locally -- pulling docker image from target environment registry...`);let E={username:n.username,password:n.password,serveraddress:n.registryUrl},A=await o.pull(d,{authconfig:E});we.debug("Following image pull stream..."),await new Promise((H,V)=>{o.modem.followProgress(A,(N,z)=>{N?(we.debug("Failed to pull image:",N),V(N)):(we.debug("Successfully finished pulling image"),H(z))},N=>{})})}catch(E){let A=E instanceof Error?E.message:String(E);throw new Error(`Failed to fetch docker image ${d} from target environment registry: ${A}`,{cause:E})}try{we.debug("Get docker labels again (with pulled image)"),l=(await o.getImage(d).inspect()).Config.Labels||{}}catch(E){let A=E instanceof Error?E.message:String(E);throw new Error(`Failed to resolve docker image metadata from pulled image ${d}: ${A}`,{cause:E})}}we.debug("Docker image labels: ",JSON.stringify(l));let c=l["io.metaplay.sdk_version"],u=_be(i.helmChartRepo??l["io.metaplay.default_helm_repo"]??"https://charts.metaplay.dev");!i.helmChartVersion&&!i.localChartPath&&console.warn("Warning: You should specify the Helm chart version explicitly with --helm-chart-version=<version>!");let p=i.helmChartVersion??l["io.metaplay.default_server_chart_version"];if(!p)throw new Error("No Helm chart version defined. With pre-R28 SDK versions, you must specify the Helm chart version explicitly with --helm-chart-version=<version>.");let f=null;if(p!=="latest-prerelease")try{f=new B6e.Range(p)}catch(E){throw new Error(`Helm chart version '${p}' is not a valid SemVer range: ${String(E)}`,{cause:E})}if(!i.values)throw new Error("Path to a Helm values file must be specified with --values");let m=await Obe(u,"metaplay-gameserver");we.debug(`Available Helm chart versions: ${m.join(", ")}`);let y=Bbe(m,f);if(!y)throw new Error(`No Helm chart version found that satisfies '${p}' in repository '${u}'`);we.debug("Resolved Helm chart version: ",y),await uj();let g=await a.getKubeConfigWithEmbeddedCredentials(),w=i.localChartPath??"metaplay-gameserver",S=["upgrade","--install","--wait"].concat(["-n",r.deployment.kubernetes_namespace]).concat(["--values",i.values]).concat(["--set-string",`image.tag=${e}`]).concat(c?["--set-string",`sdk.version=${c}`]:[]).concat(i.localChartPath?[]:["--repo",u,"--version",y]).concat([i.deploymentName]).concat([w]);we.info(`Execute: helm ${S.join(" ")}`),await F3(g,S);let v=!i.localChartPath&&u!=="https://charts.metaplay.dev"?` from repo ${u}`:"";console.log(`Game server deployed to ${t} with tag ${e} using chart version ${y}${v}`);try{let E=new Hc;E.loadFromString(g),console.log("Validating game server deployment..."),await mj(r,E,e)}catch(E){we.debug("Invocation failed with error:",E);let A=E instanceof Error?E.message:String(E);console.error(`Failed to resolve game server deployment status: ${A}`),(0,Yr.exit)(2)}}catch(a){we.debug("Invocation failed with error:",a),a instanceof Error&&console.error(`Error deploying game server into target environment: ${a.message}`),(0,Yr.exit)(1)}});Nr.command("uninstall-server").description("remove the deployed game server from the target environment").argument("environment","target environment (e.g. metaplay-idler-develop or tiny-squids)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let i=await xl(t,e);console.log(`Removing server from ${t}...`);let a=await i.getEnvironmentDetails(),r=await i.getKubeConfigWithEmbeddedCredentials(),n=await pj(r);n===null&&(console.log("No server deployed, nothing to do"),(0,Yr.exit)(0)),await uj();let o=n.name,s=["uninstall","--wait"].concat(["-n",a.deployment.kubernetes_namespace]).concat([o]);we.info(`Execute: helm ${s.join(" ")}`),await F3(r,s),console.log(`Server uninstalled from ${t}`)}catch(i){we.debug("Uninstalling server failed with error:",i),i instanceof Error&&console.error(`Error uninstalling server: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("check-server-status").description("check the status of a deployed server and print out information that is helpful in debugging failed deployments").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{let i=await xl(t,e);try{we.debug("Get environment info");let a=await i.getEnvironmentDetails();we.debug("Get kubeconfig");let r,n=new Hc;try{r=await i.getKubeConfigWithEmbeddedCredentials(),n.loadFromString(r)}catch(s){let d=s instanceof Error?s.message:String(s);throw new Error(`Failed to load or validate kubeconfig. ${d}`,{cause:s})}await pj(r)===null&&(console.log("No game server deployed in target environment"),(0,Yr.exit)(1)),console.log("Validating game server deployment"),await mj(a,n,null)}catch(a){we.debug("Invocation failed with error:",a),console.error(`Failed to check deployment status: ${a.message}`),(0,Yr.exit)(1)}});Nr.command("debug-server").description("run an ephemeral debug container against a game server pod running in the cloud").argument("environment","target environment (e.g., metaplay-idler-develop or tiny-squids)").argument("[pod-name]","name of the pod to debug (must be specified if deployment has multiple pods)").hook("preAction",async()=>{await cs()}).action(async(t,e,i)=>{let a=await xl(t,i);await jbe(a,e)});Wbe(Nr);Nr.parseAsync();
190
+ Please specify which you want to debug.`),(0,$3.exit)(1)}let d=Lbe.default.join(qbe.default.tmpdir(),`temp-kubeconfig-${Date.now()}`);try{we.debug(`Write temporary kubeconfig to ${d}`),await(0,LT.writeFile)(d,i);let l=[`--kubeconfig=${d}`,`--namespace=${n}`,"debug",e,"-it","--profile=general","--image=metaplay/diagnostics:latest","--target=shard-server"];console.log(`Execute: kubectl ${l.join(" ")}`);let c=await Uc("kubectl",l,{inheritStdio:!0});we.debug("Delete temporary kubeconfig"),await(0,LT.unlink)(d),c?.exitCode!==0&&(console.error(`kubectl failed failed with exit code ${c.exitCode}`),(0,$3.exit)(c.exitCode))}catch(l){let c=l instanceof Error?l.message:String(l);console.error(`Failed to execute 'kubectl': ${c}. You need to have kubectl installed to debug a game server with metaplay-auth.`),we.debug("Delete temporary kubeconfig"),await(0,LT.unlink)(d)}}var r_=ee(z6e(),1);var a_=class extends Error{response;constructor(e,i,a){super(`Failed to fetch ${e} ${i}: ${a.statusText}, response code=${a.status}`),this.response=a}},bE=class{accessToken;humanId;stackApiBaseUrl;constructor(e,i,a){this.accessToken=e,this.humanId=i,this.stackApiBaseUrl=a}async fetchJson(e,i){let a=await fetch(e,{method:i,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}});if(a.status!==200)throw new a_(i,e,a);return await a.json()}async fetchText(e,i){let a;try{a=await fetch(e,{method:i,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}})}catch(r){throw we.error(`Failed to fetch ${i} ${e}:`,r),r.cause?.code==="UNABLE_TO_VERIFY_LEAF_SIGNATURE"?new Error(`Failed to to fetch ${e}: SSL certificate validation failed. Is someone trying to tamper with your internet connection?`,{cause:r}):new Error(`Failed to fetch ${e}: ${r}`,{cause:r})}if(a.status!==200)throw new Error(`Failed to fetch ${i} ${e}: ${a.statusText}`);return await a.text()}async getAwsCredentials(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/aws`;return we.debug(`Fetching AWS credentials from ${e}...`),await this.fetchJson(e,"POST")}async getKubeConfigWithEmbeddedCredentials(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/k8s`;return we.debug(`Getting KubeConfig from ${e}...`),await this.fetchText(e,"POST")}async getKubeConfigWithExecCredential(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/k8s?type=execcredential`;we.debug(`Getting Kubernetes KubeConfig from ${e}...`);let i;try{i=await this.fetchJson(e,"POST")}catch(c){if(c instanceof a_){if(c.response.status===404)throw new Error(`Environment ${this.humanId} does not exist.`,{cause:c});if(c.response.status===403)throw new Error(`Your account does not have permissions to access environment ${this.humanId}.`,{cause:c})}let u=c instanceof Error?c.message:String(c);throw new Error(`Failed to fetch Kubernetes KubeConfig: ${u}`,{cause:c})}if(!i.spec.cluster)throw new Error("Received kubeExecCredential with missing spec.cluster");let r=(await this.getEnvironmentDetails()).deployment?.kubernetes_namespace;if(!r)throw new Error("Environment details did not contain a valid Kubernetes namespace");let o=(await xbe(this.accessToken)).email,s="metaplay-auth",d=["get-kubernetes-execcredential"].concat(["--stack-api",this.stackApiBaseUrl]).concat([this.humanId]);Vbe()&&(s="npx",d=["--yes","@metaplay/metaplay-auth@latest",...d]);let l={apiVersion:"v1",kind:"Config","current-context":this.humanId,clusters:[{cluster:{"certificate-authority-data":i.spec.cluster.certificateAuthorityData,server:i.spec.cluster.server},name:i.spec.cluster.server}],contexts:[{context:{cluster:i.spec.cluster.server,namespace:r,user:o},name:this.humanId}],users:[{name:o,user:{exec:{apiVersion:"client.authentication.k8s.io/v1beta1",command:s,args:d,interactiveMode:"Never"}}}]};return xL(l)}async getKubeExecCredential(){let e=`${this.stackApiBaseUrl}/v0/credentials/${this.humanId}/k8s?type=execcredential`;return we.debug(`Getting Kubernetes ExecCredential from ${e}...`),await this.fetchText(e,"POST")}async getEnvironmentDetails(){let e=`${this.stackApiBaseUrl}/v0/deployments/${this.humanId}`;return we.debug(`Getting environment details from ${e}...`),await this.fetchJson(e,"GET")}async getDockerCredentials(){we.debug("Get environment info");let e=await this.getEnvironmentDetails();we.debug("Get AWS credentials from Metaplay");let i=await this.getAwsCredentials();we.debug("Create ECR client");let a=new r_.ECRClient({credentials:{accessKeyId:i.AccessKeyId,secretAccessKey:i.SecretAccessKey,sessionToken:i.SessionToken},region:e.deployment.aws_region});we.debug("Fetch ECR login credentials from AWS");let r=new r_.GetAuthorizationTokenCommand({}),n=await a.send(r);if(!n.authorizationData||n.authorizationData.length===0||!n.authorizationData[0].authorizationToken||!n.authorizationData[0].proxyEndpoint)throw new Error("Received an empty authorization token response for ECR repository");we.debug("Parse ECR response");let o=n.authorizationData[0].proxyEndpoint,s=n.authorizationData[0].authorizationToken,d=Buffer.from(s,"base64").toString(),[l,c]=d.split(":");return we.debug(`ECR: username=${l}, proxyEndpoint=${o}`),{username:l,password:c,registryUrl:o}}};var V6e="1.9.3-next.852";var D6e;function vMt(t,e){let i="https://infra.p1.metaplay.io/stackapi",a=e.split(".")[0];return new bE(t.access_token,a,i)}async function CMt(t,e,i,a){let r=`${VA}/api/v1/environments/with-slugs?organization_slug=${e}&project_slug=${i}&environment_slug=${a}`;we.debug(`Getting environment information from portal: ${r}...`);let n=await fetch(r,{method:"GET",headers:{Authorization:`Bearer ${t.access_token}`,"Content-Type":"application/json"}});await W6e(n);let o=await n.json();return we.debug(`Portal returned environment info: ${JSON.stringify(o,void 0,2)}`),o}async function AMt(t,e){let i=`${VA}/api/v1/environments?human_id=${e}`;we.debug(`Getting environment information from portal: ${i}...`);let a=await fetch(i,{method:"GET",headers:{Authorization:`Bearer ${t.access_token}`,"Content-Type":"application/json"}});await W6e(a);let r=await a.json();if(we.debug(`Portal returned environment infos: ${JSON.stringify(r,void 0,2)}`),r.length===0)throw new Error(`Environment ${e} does not exist or your account does not have permissions to access this environment`);return r[0]}async function W6e(t){if(!t.ok){let e=await t.json();throw typeof e=="object"&&e!==null&&"message"in e&&typeof e.message=="string"?new Error(e.message):new Error(`Failed to fetch environment details with error ${t.status}: ${JSON.stringify(e)}`)}}async function _6e(t,e,i,a){let r=await CMt(t,e,i,a),n=r.stack_domain;if(!n)throw new Error(`The environment ${r.human_id} has not been provisioned to any infra stack (environment.stack_domain is empty).`);return new bE(t.access_token,r.human_id,`https://infra.${n}/stackapi`)}async function PMt(t,e){let i=D6e;if(!i){let a=await AMt(t,e);if(!a.stack_domain)throw new Error(`The environment ${a.human_id} has not been provisioned to any infra stack (environment.stack_domain is empty).`);i=`https://infra.${a.stack_domain}/stackapi`}return new bE(t.access_token,e,i)}async function xl(t,e){let i=await WT();if(t){if(zbe(t))return console.warn('Using the FQDN to specify target environment is deprecated. Use the "<organization>-<project>-<environment>" slugs instead.'),vMt(i,t);{let a=t.split("-");if(a.length===2||a.length===4)return await PMt(i,t);if(a.length===3)return await _6e(i,a[0],a[1],a[2]);throw new Error(`Invalid environment address syntax '${t}'. Specify either the environment's id (eg, "delicious-elephant") or its slug tripled (eg, "<organization>-<project>-<environment>")`)}}else{if(e.organization&&e.project&&e.environment)return console.warn(`Warning: Specifying the target environment with -o (--organization), -p (--project), and -e (--environment) is deprecated! Use the '${e.organization}-${e.project}-${e.environment}' syntax instead.`),await _6e(i,e.organization,e.project,e.environment);throw new Error("Could not determine target environment from arguments: You need to specify either an environment FQDN or an organization, project, and environment. Run this command with --help flag for more information.")}}var Nr=new QY;Nr.name("metaplay-auth").description("Authenticate with Metaplay and get AWS and Kubernetes credentials for game servers.").version(V6e).option("-d, --debug","enable debug output").option("--portal-base-url <portal-base-url>","override the default portal base URL (e.g. http://localhost:3000)").option("--stack-api <stack-api-base-url>","override the default stack API base URL (e.g. https://infra.p1.metaplay.io/stackapi/)").hook("preAction",t=>{let e=t.opts();e.debug?rj(0):rj(10),console.warn("Warning: The metaplay-auth CLI is deprecated and will only receive critical updates."),console.warn(" Please upgrade to Metaplay SDK release 32 or newer and the new Metaplay CLI (https://github.com/metaplay/cli).");let i=e.portalBaseUrl??process.env.AUTHCLI_PORTAL_BASEURL;i&&(we.debug(`Using portal URL override: ${i}`),lbe(i)),e.stackApi&&(D6e=e.stackApi)});Nr.command("login").description("login to your Metaplay account").action(async()=>{await Tbe()});Nr.command("machine-login").description("login to the Metaplay cloud using a machine account (using credentials in environment variable METAPLAY_CREDENTIALS)").option("--dev-credentials","machine user credentials to use, only for dev purposes, use METAPLAY_CREDENTIALS env variable for better safety!").action(async t=>{try{let e;if(t.devCredentials)e=t.devCredentials;else if(e=process.env.METAPLAY_CREDENTIALS,!e||e==="")throw new Error("Unable to find the credentials, the environment variable METAPLAY_CREDENTIALS is not defined!");let i=e.indexOf("+");if(i===-1)throw new Error("Invalid format for credentials, you should copy-paste the value from the developer portal verbatim");let a=e.substring(0,i),r=e.substring(i+1);await Nbe(a,r)}catch(e){console.error(`Error during machine login: ${e instanceof Error?e.message:String(e)}`),(0,Yr.exit)(1)}});Nr.command("logout").description("log out of your Metaplay account").action(async()=>{console.log("Logging out by removing locally stored tokens...");try{await cj(),console.log("Done! You are now logged out.")}catch(t){we.debug("Invocation failed with error:",t),t instanceof Error&&console.error(`Error logging out: ${t.message}`),(0,Yr.exit)(1)}});Nr.command("show-tokens").description("show loaded tokens").hook("preAction",async()=>{await cs()}).action(async()=>{try{let t=await WT();console.log(JSON.stringify(t,void 0,2))}catch(t){we.debug("Invocation failed with error:",t),t instanceof Error&&console.error(`Error showing tokens: ${t.message}`),(0,Yr.exit)(1)}});Nr.command("get-kubeconfig").description("get kubeconfig for target environment").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").option("-t, --type <credentials-type>","type of credentials handling in kubeconfig (static or dynamic)").option("--output <kubeconfig-path>","path of the output file where to write kubeconfig (written to stdout if not specified)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let i=await xl(t,e),r=!!(await WT()).refresh_token,n=e.type??(r?"dynamic":"static"),o;if(n==="dynamic")we.debug("Fetching kubeconfig with execcredential"),o=await i.getKubeConfigWithExecCredential();else if(n==="static")we.debug("Fetching kubeconfig with embedded secret"),o=await i.getKubeConfigWithEmbeddedCredentials();else throw new Error('Invalid credentials type; must be either "static" or "dynamic"');e.output?(we.debug(`Writing kubeconfig to file ${e.output}`),await(0,O6e.writeFile)(e.output,o,{mode:384}),console.log(`Wrote kubeconfig to ${e.output}`)):console.log(o)}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error("Error getting KubeConfig:",i.message),(0,Yr.exit)(1)}});Nr.command("get-kubernetes-execcredential").description("[internal] get kubernetes credentials in execcredential format (used from the generated kubeconfigs)").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let a=await(await xl(t,e)).getKubeExecCredential();console.log(a)}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error(`Error getting Kubernetes ExecCredential: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("get-aws-credentials").description("get AWS credentials for target environment").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").option("-f, --format <format>","output format (json or env)","json").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{if(e.format!=="json"&&e.format!=="env")throw new Error("Invalid format; must be one of json or env");let a=await(await xl(t,e)).getAwsCredentials();e.format==="env"?(console.log(`export AWS_ACCESS_KEY_ID=${a.AccessKeyId}`),console.log(`export AWS_SECRET_ACCESS_KEY=${a.SecretAccessKey}`),console.log(`export AWS_SESSION_TOKEN=${a.SessionToken}`)):console.log(JSON.stringify({...a,Version:1}))}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error(`Error getting AWS credentials: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("get-environment").description("get details of an environment").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").option("-o, --organization <organization>","[deprecated] organization name (e.g. metaplay)").option("-p, --project <project>","[deprecated] project name (e.g. idler)").option("-e, --environment <environment>","[deprecated] environment name (e.g. develop)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let a=await(await xl(t,e)).getEnvironmentDetails();console.log(JSON.stringify(a,void 0,2))}catch(i){we.debug("Invocation failed with error:",i),i instanceof Error&&console.error(`Error getting environment details: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("push-docker-image").description("push docker image into the target environment image registry").argument("environment","target environment (e.g. metaplay-idler-develop or tiny-squids)").argument("image-name","full name of the docker image to push (eg, the gameserver:<sha>)").hook("preAction",async()=>{await cs()}).action(async(t,e,i)=>{try{console.log(`Pushing docker image ${e} to target environment ${t}...`);let a=await xl(t,i);we.debug("Get environment info");let r=await a.getEnvironmentDetails();we.debug("Get docker credentials");let n=await a.getDockerCredentials();if(!e)throw new Error("Must specify a valid docker image name as the image-name argument");let o=e.split(":");if(o.length!==2||o[0].length===0||o[1].length===0)throw new Error(`Invalid docker image name '${e}', expecting the name in format 'name:tag'`);let s=o[1],d=e,l=r.deployment.ecr_repo,c=`${l}:${s}`,u=new EY.default,p=u.getImage(d);d!==c&&(we.debug(`Tagging image ${d} as ${c}`),await p.tag({repo:l,tag:s})),we.debug(`Push image ${c}`);let f=u.getImage(c),m={username:n.username,password:n.password,serveraddress:n.registryUrl},y=await f.push({authconfig:m,tag:i.imageTag});we.debug("Following image push stream..."),await new Promise((g,w)=>{u.modem.followProgress(y,(S,v)=>{S?(we.debug("Failed to push docker image to target repository:",S),w(S)):(we.debug("Successfully finished pushing docker image"),g(v))},()=>{})}),console.log(`Successfully pushed docker image to ${c}!`)}catch(a){we.debug("Invocation failed with error:",a),a instanceof Error&&console.error(`Failed to push docker image: ${a.message}`),(0,Yr.exit)(1)}});Nr.command("deploy-server").description("deploy a game server image to target environment").argument("environment","target environment (e.g. metaplay-idler-develop or tiny-squids)").argument("image-tag","docker image tag to deploy (usually the SHA of the build)").requiredOption("-f, --values <path-to-values-file>","path to Helm values file to use for this deployment").option("--local-chart-path <path-to-chart-directory>","path to local Helm chart directory (to use a chart from local disk)").option("--helm-chart-repo <url>","override the URL of the Helm chart repository (eg, https://customchartrepo.domain.com)").option("--helm-chart-version <version>","the Helm chart version to use (eg, 0.6.0)").option("--deployment-name","Helm deployment name to use","gameserver").hook("preAction",async()=>{await cs()}).action(async(t,e,i)=>{try{console.log(`Deploying server to ${t} with image tag ${e}...`);let a=await xl(t,i),r=await a.getEnvironmentDetails();if(!e)throw new Error("Must specify a valid docker image tag as the image-tag argument, usually the SHA of the build");if(e.includes(":"))throw new Error("Invalid image tag: only specify the tag, not the repository name.");if(!i.deploymentName)throw new Error(`Invalid Helm deployment name '${i.deploymentName}'; specify one with --deployment-name or use the default`);let n=await a.getDockerCredentials(),o=new EY.default,d=`${r.deployment.ecr_repo}:${e}`;we.debug(`Fetch docker image labels for ${d}`);let l;try{l=(await o.getImage(d).inspect()).Config.Labels||{}}catch(E){let A=E instanceof Error?E.message:String(E);we.debug(`Failed to resolve docker image metadata from local image ${d}: ${A}`)}if(l===void 0){try{console.log(`Image ${d} not found locally -- pulling docker image from target environment registry...`);let E={username:n.username,password:n.password,serveraddress:n.registryUrl},A=await o.pull(d,{authconfig:E});we.debug("Following image pull stream..."),await new Promise((H,V)=>{o.modem.followProgress(A,(N,z)=>{N?(we.debug("Failed to pull image:",N),V(N)):(we.debug("Successfully finished pulling image"),H(z))},N=>{})})}catch(E){let A=E instanceof Error?E.message:String(E);throw new Error(`Failed to fetch docker image ${d} from target environment registry: ${A}`,{cause:E})}try{we.debug("Get docker labels again (with pulled image)"),l=(await o.getImage(d).inspect()).Config.Labels||{}}catch(E){let A=E instanceof Error?E.message:String(E);throw new Error(`Failed to resolve docker image metadata from pulled image ${d}: ${A}`,{cause:E})}}we.debug("Docker image labels: ",JSON.stringify(l));let c=l["io.metaplay.sdk_version"],u=_be(i.helmChartRepo??l["io.metaplay.default_helm_repo"]??"https://charts.metaplay.dev");!i.helmChartVersion&&!i.localChartPath&&console.warn("Warning: You should specify the Helm chart version explicitly with --helm-chart-version=<version>!");let p=i.helmChartVersion??l["io.metaplay.default_server_chart_version"];if(!p)throw new Error("No Helm chart version defined. With pre-R28 SDK versions, you must specify the Helm chart version explicitly with --helm-chart-version=<version>.");let f=null;if(p!=="latest-prerelease")try{f=new B6e.Range(p)}catch(E){throw new Error(`Helm chart version '${p}' is not a valid SemVer range: ${String(E)}`,{cause:E})}if(!i.values)throw new Error("Path to a Helm values file must be specified with --values");let m=await Obe(u,"metaplay-gameserver");we.debug(`Available Helm chart versions: ${m.join(", ")}`);let y=Bbe(m,f);if(!y)throw new Error(`No Helm chart version found that satisfies '${p}' in repository '${u}'`);we.debug("Resolved Helm chart version: ",y),await uj();let g=await a.getKubeConfigWithEmbeddedCredentials(),w=i.localChartPath??"metaplay-gameserver",S=["upgrade","--install","--wait"].concat(["-n",r.deployment.kubernetes_namespace]).concat(["--values",i.values]).concat(["--set-string",`image.tag=${e}`]).concat(c?["--set-string",`sdk.version=${c}`]:[]).concat(i.localChartPath?[]:["--repo",u,"--version",y]).concat([i.deploymentName]).concat([w]);we.info(`Execute: helm ${S.join(" ")}`),await F3(g,S);let v=!i.localChartPath&&u!=="https://charts.metaplay.dev"?` from repo ${u}`:"";console.log(`Game server deployed to ${t} with tag ${e} using chart version ${y}${v}`);try{let E=new Hc;E.loadFromString(g),console.log("Validating game server deployment..."),await mj(r,E,e)}catch(E){we.debug("Invocation failed with error:",E);let A=E instanceof Error?E.message:String(E);console.error(`Failed to resolve game server deployment status: ${A}`),(0,Yr.exit)(2)}}catch(a){we.debug("Invocation failed with error:",a),a instanceof Error&&console.error(`Error deploying game server into target environment: ${a.message}`),(0,Yr.exit)(1)}});Nr.command("uninstall-server").description("remove the deployed game server from the target environment").argument("environment","target environment (e.g. metaplay-idler-develop or tiny-squids)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{try{let i=await xl(t,e);console.log(`Removing server from ${t}...`);let a=await i.getEnvironmentDetails(),r=await i.getKubeConfigWithEmbeddedCredentials(),n=await pj(r);n===null&&(console.log("No server deployed, nothing to do"),(0,Yr.exit)(0)),await uj();let o=n.name,s=["uninstall","--wait"].concat(["-n",a.deployment.kubernetes_namespace]).concat([o]);we.info(`Execute: helm ${s.join(" ")}`),await F3(r,s),console.log(`Server uninstalled from ${t}`)}catch(i){we.debug("Uninstalling server failed with error:",i),i instanceof Error&&console.error(`Error uninstalling server: ${i.message}`),(0,Yr.exit)(1)}});Nr.command("check-server-status").description("check the status of a deployed server and print out information that is helpful in debugging failed deployments").argument("[environment]","target environment (e.g. metaplay-idler-develop or tiny-squids)").hook("preAction",async()=>{await cs()}).action(async(t,e)=>{let i=await xl(t,e);try{we.debug("Get environment info");let a=await i.getEnvironmentDetails();we.debug("Get kubeconfig");let r,n=new Hc;try{r=await i.getKubeConfigWithEmbeddedCredentials(),n.loadFromString(r)}catch(s){let d=s instanceof Error?s.message:String(s);throw new Error(`Failed to load or validate kubeconfig. ${d}`,{cause:s})}await pj(r)===null&&(console.log("No game server deployed in target environment"),(0,Yr.exit)(1)),console.log("Validating game server deployment"),await mj(a,n,null)}catch(a){we.debug("Invocation failed with error:",a),console.error(`Failed to check deployment status: ${a.message}`),(0,Yr.exit)(1)}});Nr.command("debug-server").description("run an ephemeral debug container against a game server pod running in the cloud").argument("environment","target environment (e.g., metaplay-idler-develop or tiny-squids)").argument("[pod-name]","name of the pod to debug (must be specified if deployment has multiple pods)").hook("preAction",async()=>{await cs()}).action(async(t,e,i)=>{let a=await xl(t,i);await jbe(a,e)});Wbe(Nr);Nr.parseAsync();
191
191
  /*! Bundled license information:
192
192
 
193
193
  safe-buffer/index.js:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@metaplay/metaplay-auth",
3
3
  "description": "Utility CLI for authenticating with the Metaplay Auth and making authenticated calls to infrastructure endpoints.",
4
- "version": "1.9.3-next.851",
4
+ "version": "1.9.3-next.852",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "homepage": "https://metaplay.io",
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = "1.9.3-next.851"
1
+ export const PACKAGE_VERSION = "1.9.3-next.852"