Create basic api client

This commit is contained in:
Guilherme Werner 2025-04-13 11:10:45 -03:00
parent 3f80ace7b8
commit 6d584cc063
29 changed files with 1008 additions and 1 deletions

View file

@ -0,0 +1,27 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: UNLICENSED
using dotenv.net;
namespace Tribufu.Proxmox.Tests
{
public static class Program
{
public static async Task Main(string[] args)
{
DotEnv.Load(new DotEnvOptions(ignoreExceptions: true, envFilePaths: [".env", "../../.env"]));
var clusterUrl = Environment.GetEnvironmentVariable("PROXMOX_CLUSTER_URL");
var tokenId = Environment.GetEnvironmentVariable("PROXMOX_TOKEN_ID");
var tokenSecret = Environment.GetEnvironmentVariable("PROXMOX_TOKEN_SECRET");
var proxmox = new ProxmoxClient(clusterUrl, tokenId, tokenSecret);
var nodes = await proxmox.ListNodesAsync();
foreach (var node in nodes)
{
Console.WriteLine($"- {node.Name}");
}
}
}
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="dotenv.net" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu.Proxmox\Tribufu.Proxmox.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,38 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using System.Collections.Generic;
using System.Threading.Tasks;
using Tribufu.Proxmox.Models;
namespace Tribufu.Proxmox.Interfaces
{
public interface IProxmoxClient
{
Task<bool> LoginAsync(string username, string password);
Task<List<ProxmoxNode>> ListNodesAsync();
Task<ProxmoxNodeStatus> GetNodeStatusAsync(string node);
Task<List<ProxmoxVirtualMachine>> ListVirtualMachinesAsync(string node);
Task<ProxmoxVirtualMachineStatus> GetVirtualMachineStatusAsync(string node, int vmid);
Task<bool> StartVirtualMachineAsync(string node, int vmid);
Task<bool> RebootVirtualMachineAsync(string node, int vmid);
Task<bool> ResetVirtualMachineAsync(string node, int vmid);
Task<bool> SuspendVirtualMachineAsync(string node, int vmid);
Task<bool> ResumeVirtualMachineAsync(string node, int vmid);
Task<bool> ShutdownVirtualMachineAsync(string node, int vmid);
Task<bool> StopVirtualMachineAsync(string node, int vmid);
Task<List<ProxmoxContainer>> ListContainersAsync(string node);
}
}

View file

@ -0,0 +1,37 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxBalloonInfo
{
[JsonProperty("major_page_faults")]
public long MajorPageFaults { get; set; }
[JsonProperty("total_mem")]
public long TotalMem { get; set; }
[JsonProperty("mem_swapped_out")]
public long MemSwappedOut { get; set; }
[JsonProperty("minor_page_faults")]
public long MinorPageFaults { get; set; }
[JsonProperty("mem_swapped_in")]
public long MemSwappedIn { get; set; }
[JsonProperty("max_mem")]
public long MaxMem { get; set; }
[JsonProperty("last_update")]
public long LastUpdate { get; set; }
[JsonProperty("actual")]
public long Actual { get; set; }
[JsonProperty("free_mem")]
public long FreeMem { get; set; }
}
}

View file

@ -0,0 +1,107 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using System.Collections.Generic;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxBlockStats
{
[JsonProperty("rd_operations")]
public long RdOperations { get; set; }
[JsonProperty("wr_total_time_ns")]
public long WrTotalTimeNs { get; set; }
[JsonProperty("wr_highest_offset")]
public long WrHighestOffset { get; set; }
[JsonProperty("flush_operations")]
public long FlushOperations { get; set; }
[JsonProperty("failed_zone_append_operations")]
public long FailedZoneAppendOperations { get; set; }
[JsonProperty("invalid_wr_operations")]
public long InvalidWrOperations { get; set; }
[JsonProperty("invalid_rd_operations")]
public long InvalidRdOperations { get; set; }
[JsonProperty("rd_bytes")]
public long RdBytes { get; set; }
[JsonProperty("invalid_zone_append_operations")]
public long InvalidZoneAppendOperations { get; set; }
[JsonProperty("account_invalid")]
public bool AccountInvalid { get; set; }
[JsonProperty("failed_rd_operations")]
public long FailedRdOperations { get; set; }
[JsonProperty("timed_stats")]
public List<object> TimedStats { get; set; }
[JsonProperty("zone_append_operations")]
public long ZoneAppendOperations { get; set; }
[JsonProperty("failed_flush_operations")]
public long FailedFlushOperations { get; set; }
[JsonProperty("zone_append_merged")]
public long ZoneAppendMerged { get; set; }
[JsonProperty("flush_total_time_ns")]
public long FlushTotalTimeNs { get; set; }
[JsonProperty("invalid_unmap_operations")]
public long InvalidUnmapOperations { get; set; }
[JsonProperty("invalid_flush_operations")]
public long InvalidFlushOperations { get; set; }
[JsonProperty("rd_merged")]
public long RdMerged { get; set; }
[JsonProperty("unmap_bytes")]
public long UnmapBytes { get; set; }
[JsonProperty("unmap_operations")]
public long UnmapOperations { get; set; }
[JsonProperty("zone_append_bytes")]
public long ZoneAppendBytes { get; set; }
[JsonProperty("wr_operations")]
public long WrOperations { get; set; }
[JsonProperty("rd_total_time_ns")]
public long RdTotalTimeNs { get; set; }
[JsonProperty("wr_bytes")]
public long WrBytes { get; set; }
[JsonProperty("zone_append_total_time_ns")]
public long ZoneAppendTotalTimeNs { get; set; }
[JsonProperty("account_failed")]
public bool AccountFailed { get; set; }
[JsonProperty("failed_unmap_operations")]
public long FailedUnmapOperations { get; set; }
[JsonProperty("unmap_merged")]
public long UnmapMerged { get; set; }
[JsonProperty("unmap_total_time_ns")]
public long UnmapTotalTimeNs { get; set; }
[JsonProperty("wr_merged")]
public long WrMerged { get; set; }
[JsonProperty("idle_time_ns")]
public long? IdleTimeNs { get; set; }
}
}

View file

@ -0,0 +1,16 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxBootInfo
{
[JsonProperty("secureboot")]
public int SecureBoot { get; set; }
[JsonProperty("mode")]
public string Mode { get; set; }
}
}

View file

@ -0,0 +1,61 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxContainer
{
[JsonProperty("vmid")]
public int VmId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("uptime")]
public long Uptime { get; set; }
[JsonProperty("cpu")]
public double Cpu { get; set; }
[JsonProperty("cpus")]
public int CpuCount { get; set; }
[JsonProperty("mem")]
public long MemoryUsed { get; set; }
[JsonProperty("maxmem")]
public long MemoryTotal { get; set; }
[JsonProperty("swap")]
public long SwapUsed { get; set; }
[JsonProperty("maxswap")]
public long SwapTotal { get; set; }
[JsonProperty("disk")]
public long DiskUsed { get; set; }
[JsonProperty("maxdisk")]
public long DiskTotal { get; set; }
[JsonProperty("diskread")]
public long DiskRead { get; set; }
[JsonProperty("diskwrite")]
public long DiskWrite { get; set; }
[JsonProperty("netin")]
public long NetworkIn { get; set; }
[JsonProperty("netout")]
public long NetworkOut { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
}
}

View file

@ -0,0 +1,34 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxCpuInfo
{
[JsonProperty("cores")]
public int Cores { get; set; }
[JsonProperty("mhz")]
public string MHz { get; set; }
[JsonProperty("cpus")]
public int Cpus { get; set; }
[JsonProperty("sockets")]
public int Sockets { get; set; }
[JsonProperty("model")]
public string Model { get; set; }
[JsonProperty("flags")]
public string Flags { get; set; }
[JsonProperty("user_hz")]
public int UserHz { get; set; }
[JsonProperty("hvm")]
public string Hvm { get; set; }
}
}

View file

@ -0,0 +1,13 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxHighAvailability
{
[JsonProperty("managed")]
public int Managed { get; set; }
}
}

View file

@ -0,0 +1,22 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxKernelInfo
{
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("sysname")]
public string SysName { get; set; }
[JsonProperty("release")]
public string Release { get; set; }
[JsonProperty("machine")]
public string Machine { get; set; }
}
}

View file

@ -0,0 +1,13 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxKsmInfo
{
[JsonProperty("shared")]
public long Shared { get; set; }
}
}

View file

@ -0,0 +1,19 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxMemoryStats
{
[JsonProperty("total")]
public long Total { get; set; }
[JsonProperty("used")]
public long Used { get; set; }
[JsonProperty("free")]
public long Free { get; set; }
}
}

View file

@ -0,0 +1,16 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxNicStats
{
[JsonProperty("netin")]
public long NetIn { get; set; }
[JsonProperty("netout")]
public long NetOut { get; set; }
}
}

View file

@ -0,0 +1,49 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxNode
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("node")]
public string Name { get; set; }
[JsonProperty("uptime")]
public long Uptime { get; set; }
[JsonProperty("ssl_fingerprint")]
public string SslFingerprint { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("cpu")]
public double Cpu { get; set; }
[JsonProperty("maxcpu")]
public int MaxCpu { get; set; }
[JsonProperty("disk")]
public long Disk { get; set; }
[JsonProperty("maxmem")]
public long MaxMemory { get; set; }
[JsonProperty("mem")]
public long Memory { get; set; }
[JsonProperty("maxdisk")]
public long MaxDisk { get; set; }
[JsonProperty("level")]
public string Level { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
}
}

View file

@ -0,0 +1,52 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxNodeStatus
{
[JsonProperty("boot-info")]
public ProxmoxBootInfo BootInfo { get; set; }
[JsonProperty("swap")]
public ProxmoxMemoryStats Swap { get; set; }
[JsonProperty("rootfs")]
public ProxmoxStorageStats RootFs { get; set; }
[JsonProperty("pveversion")]
public string PveVersion { get; set; }
[JsonProperty("cpuinfo")]
public ProxmoxCpuInfo CpuInfo { get; set; }
[JsonProperty("memory")]
public ProxmoxMemoryStats Memory { get; set; }
[JsonProperty("ksm")]
public ProxmoxKsmInfo Ksm { get; set; }
[JsonProperty("idle")]
public double Idle { get; set; }
[JsonProperty("cpu")]
public double Cpu { get; set; }
[JsonProperty("loadavg")]
public string[] LoadAverage { get; set; }
[JsonProperty("current-kernel")]
public ProxmoxKernelInfo CurrentKernel { get; set; }
[JsonProperty("kversion")]
public string KernelVersion { get; set; }
[JsonProperty("wait")]
public double Wait { get; set; }
[JsonProperty("uptime")]
public long Uptime { get; set; }
}
}

View file

@ -0,0 +1,22 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxStorageStats
{
[JsonProperty("total")]
public long Total { get; set; }
[JsonProperty("avail")]
public long Available { get; set; }
[JsonProperty("used")]
public long Used { get; set; }
[JsonProperty("free")]
public long Free { get; set; }
}
}

View file

@ -0,0 +1,34 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxSupportInfo
{
[JsonProperty("backup-max-workers")]
public bool BackupMaxWorkers { get; set; }
[JsonProperty("pbs-library-version")]
public string PbsLibraryVersion { get; set; }
[JsonProperty("pbs-masterkey")]
public bool PbsMasterkey { get; set; }
[JsonProperty("backup-fleecing")]
public bool BackupFleecing { get; set; }
[JsonProperty("query-bitmap-info")]
public bool QueryBitmapInfo { get; set; }
[JsonProperty("pbs-dirty-bitmap")]
public bool PbsDirtyBitmap { get; set; }
[JsonProperty("pbs-dirty-bitmap-savevm")]
public bool PbsDirtyBitmapSaveVm { get; set; }
[JsonProperty("pbs-dirty-bitmap-migration")]
public bool PbsDirtyBitmapMigration { get; set; }
}
}

View file

@ -0,0 +1,55 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxVirtualMachine
{
[JsonProperty("vmid")]
public int VmId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("uptime")]
public long Uptime { get; set; }
[JsonProperty("cpu")]
public double Cpu { get; set; }
[JsonProperty("cpus")]
public int CpuCount { get; set; }
[JsonProperty("mem")]
public long MemoryUsed { get; set; }
[JsonProperty("maxmem")]
public long MemoryTotal { get; set; }
[JsonProperty("disk")]
public long DiskUsed { get; set; }
[JsonProperty("maxdisk")]
public long DiskTotal { get; set; }
[JsonProperty("diskread")]
public long DiskRead { get; set; }
[JsonProperty("diskwrite")]
public long DiskWrite { get; set; }
[JsonProperty("netin")]
public long NetworkIn { get; set; }
[JsonProperty("netout")]
public long NetworkOut { get; set; }
[JsonProperty("pid")]
public int Pid { get; set; }
}
}

View file

@ -0,0 +1,89 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using System.Collections.Generic;
namespace Tribufu.Proxmox.Models
{
public class ProxmoxVirtualMachineStatus
{
[JsonProperty("vmid")]
public int VmId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("nics")]
public Dictionary<string, ProxmoxNicStats> Nics { get; set; }
[JsonProperty("blockstat")]
public Dictionary<string, ProxmoxBlockStats> BlockStat { get; set; }
[JsonProperty("maxdisk")]
public long MaxDisk { get; set; }
[JsonProperty("cpu")]
public double Cpu { get; set; }
[JsonProperty("mem")]
public long Mem { get; set; }
[JsonProperty("netin")]
public long NetIn { get; set; }
[JsonProperty("pid")]
public int Pid { get; set; }
[JsonProperty("qmpstatus")]
public string QmpStatus { get; set; }
[JsonProperty("uptime")]
public long Uptime { get; set; }
[JsonProperty("agent")]
public int Agent { get; set; }
[JsonProperty("running-qemu")]
public string RunningQemu { get; set; }
[JsonProperty("proxmox-support")]
public ProxmoxSupportInfo ProxmoxSupport { get; set; }
[JsonProperty("maxmem")]
public long MaxMem { get; set; }
[JsonProperty("disk")]
public double Disk { get; set; }
[JsonProperty("ballooninfo")]
public ProxmoxBalloonInfo BalloonInfo { get; set; }
[JsonProperty("netout")]
public long NetOut { get; set; }
[JsonProperty("freemem")]
public long FreeMem { get; set; }
[JsonProperty("diskread")]
public long DiskRead { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("diskwrite")]
public long DiskWrite { get; set; }
[JsonProperty("running-machine")]
public string RunningMachine { get; set; }
[JsonProperty("balloon")]
public long Balloon { get; set; }
[JsonProperty("ha")]
public ProxmoxHighAvailability Ha { get; set; }
[JsonProperty("cpus")]
public int Cpus { get; set; }
}
}

View file

@ -0,0 +1,177 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Tribufu.Proxmox.Interfaces;
using Tribufu.Proxmox.Models;
namespace Tribufu.Proxmox
{
public class ProxmoxClient : IProxmoxClient
{
private readonly RestClient _client;
private string _ticket;
private string _csrfToken;
public ProxmoxClient(string baseUrl, string tokenId, string secret)
{
var options = new RestClientOptions(baseUrl.TrimEnd('/') + "/api2/json/")
{
RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
};
_client = new RestClient(options);
if (!string.IsNullOrEmpty(tokenId) && !string.IsNullOrEmpty(secret))
{
_client.AddDefaultHeader("Authorization", $"PVEAPIToken={tokenId}={secret}");
}
}
public async Task<bool> LoginAsync(string username, string password)
{
var request = new RestRequest("access/ticket", Method.Post);
request.AddParameter("username", username);
request.AddParameter("password", password);
var response = await _client.ExecuteAsync(request);
if (response.IsSuccessful)
{
var json = JObject.Parse(response.Content);
var data = json["data"];
_ticket = data["ticket"].ToString();
_csrfToken = data["CSRFPreventionToken"].ToString();
_client.AddDefaultHeader("Cookie", $"PVEAuthCookie={_ticket}");
_client.AddDefaultHeader("CSRFPreventionToken", _csrfToken);
}
return response.IsSuccessful;
}
public async Task<List<ProxmoxNode>> ListNodesAsync()
{
var request = new RestRequest($"nodes", Method.Get);
var response = await _client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
throw new Exception($"Failed to list nodes: {response.StatusCode}");
}
var json = JObject.Parse(response.Content);
return json["data"].ToObject<List<ProxmoxNode>>();
}
public async Task<ProxmoxNodeStatus> GetNodeStatusAsync(string node)
{
var request = new RestRequest($"nodes/{node}/status", Method.Get);
var response = await _client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
throw new Exception($"Failed to get node {node}: {response.StatusCode}");
}
var json = JObject.Parse(response.Content);
return json["data"].ToObject<ProxmoxNodeStatus>();
}
public async Task<List<ProxmoxVirtualMachine>> ListVirtualMachinesAsync(string node)
{
var request = new RestRequest($"nodes/{node}/qemu", Method.Get);
var response = await _client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
throw new Exception($"Failed to list VMs: {response.StatusCode}");
}
var json = JObject.Parse(response.Content);
return json["data"].ToObject<List<ProxmoxVirtualMachine>>();
}
public async Task<ProxmoxVirtualMachineStatus> GetVirtualMachineStatusAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/current", Method.Get);
var response = await _client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
throw new Exception($"Failed to start VM {vmid}: {response.StatusCode}");
}
var json = JObject.Parse(response.Content);
return json["data"].ToObject<ProxmoxVirtualMachineStatus>();
}
public async Task<bool> StartVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/start", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<bool> RebootVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/reboot", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<bool> ResetVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/reset", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<bool> SuspendVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/suspend", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<bool> ResumeVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/resume", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<bool> ShutdownVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/shutdown", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<bool> StopVirtualMachineAsync(string node, int vmid)
{
var request = new RestRequest($"nodes/{node}/qemu/{vmid}/status/stop", Method.Post);
var response = await _client.ExecuteAsync(request);
return response.IsSuccessful;
}
public async Task<List<ProxmoxContainer>> ListContainersAsync(string node)
{
var request = new RestRequest($"nodes/{node}/lxc", Method.Get);
var response = await _client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
throw new Exception($"Failed to list LXC containers: {response.StatusCode}");
}
var json = JObject.Parse(response.Content);
return json["data"].ToObject<List<ProxmoxContainer>>();
}
}
}

View file

@ -0,0 +1 @@
../../README.md

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.Proxmox</PackageId>
<Description>Proxmox API Client</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<OutputType>Library</OutputType>
<TargetFrameworks>netstandard2.0;net471;net6.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="RestSharp" />
</ItemGroup>
</Project>