First steps to pangolin provider

This commit is contained in:
2026-03-14 00:21:47 -04:00
commit ab8778ed4d
13 changed files with 1968 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
/proto/googleapis

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "googleapis"]
path = googleapis
url = https://github.com/googleapis/googleapis

1752
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

15
Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "terraform-provider-pangolin"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.102"
async-trait = "0.1.89"
serde = { version = "1.0.228", features = ["serde_derive"] }
serde_json = "1.0.149"
tf-provider = "0.2.2"
tokio = { version = "1.50.0", features = ["full"] }
# [patch.crates-io]
# tf-provider = { path = "../../tf-provider" }

1
src/data.rs Normal file
View File

@@ -0,0 +1 @@

3
src/lib.rs Normal file
View File

@@ -0,0 +1,3 @@
pub mod data;
pub mod provider;
pub mod resource;

8
src/main.rs Normal file
View File

@@ -0,0 +1,8 @@
use anyhow::Result;
use terraform_provider_pangolin::provider::PangolinProvider;
use tf_provider::Provider;
#[tokio::main]
async fn main() -> Result<()> {
tf_provider::serve("pangolin", PangolinProvider).await
}

56
src/provider.rs Normal file
View File

@@ -0,0 +1,56 @@
use std::collections::HashMap;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tf_provider::{
Diagnostics, DynamicDataSource, DynamicFunction, DynamicResource, Provider, map,
schema::{Attribute, AttributeConstraint, AttributeType, Block, Description, Schema},
value::{ValueEmpty, ValueString},
};
pub struct PangolinProvider;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PangolinConfig {
base_url: String,
api_token: String,
}
#[async_trait]
impl Provider for PangolinProvider {
type Config<'a> = PangolinConfig;
type MetaState<'a> = ValueEmpty;
fn get_resources(
&self,
_diags: &mut Diagnostics,
) -> Option<HashMap<String, Box<dyn DynamicResource>>> {
todo!()
}
fn schema(&self, _diags: &mut Diagnostics) -> Option<Schema> {
Some(Schema {
version: 1,
block: Block {
description: Description::plain("Pangolin Provider"),
attributes: map! {
"base_url" => Attribute {
attr_type: AttributeType::String,
description: Description::plain("The base URL for the API endpoint of the pangolin server. i.e. https://api.pangolin.com/v1"),
constraint: AttributeConstraint::Optional,
sensitive: false,
deprecated: false,
},
"api_token" => Attribute {
attr_type: AttributeType::String,
description: Description::plain("The API token for the API integration."),
constraint: AttributeConstraint::Optional,
sensitive: true,
deprecated: false,
}
},
..Default::default()
},
})
}
}

5
src/resource.rs Normal file
View File

@@ -0,0 +1,5 @@
#[expect(clippy::module_inception)]
pub mod resource;
pub mod rule;
pub mod site_resource;
pub mod target;

120
src/resource/resource.rs Normal file
View File

@@ -0,0 +1,120 @@
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tf_provider::{
AttributePath, Diagnostics, Resource as TfResource, schema::Schema, value::ValueEmpty,
};
#[derive(Default, Debug, Clone, Copy)]
pub struct Resource;
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
pub struct ResourceState {}
#[async_trait]
impl TfResource for Resource {
type State<'a> = ResourceState;
type PrivateState<'a> = ValueEmpty;
type ProviderMetaState<'a> = ValueEmpty;
fn schema(&self, diags: &mut Diagnostics) -> Option<Schema> {
todo!()
}
async fn validate<'a>(&self, diags: &mut Diagnostics, config: Self::State<'a>) -> Option<()> {
todo!()
}
async fn read<'a>(
&self,
diags: &mut Diagnostics,
state: Self::State<'a>,
private_state: Self::PrivateState<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<(Self::State<'a>, Self::PrivateState<'a>)> {
todo!()
}
async fn plan_create<'a>(
&self,
diags: &mut Diagnostics,
proposed_state: Self::State<'a>,
config_state: Self::State<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<(Self::State<'a>, Self::PrivateState<'a>)> {
todo!()
}
async fn plan_update<'a>(
&self,
diags: &mut Diagnostics,
prior_state: Self::State<'a>,
proposed_state: Self::State<'a>,
config_state: Self::State<'a>,
prior_private_state: Self::PrivateState<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<(Self::State<'a>, Self::PrivateState<'a>, Vec<AttributePath>)> {
todo!()
}
async fn plan_destroy<'a>(
&self,
diags: &mut Diagnostics,
prior_state: Self::State<'a>,
prior_private_state: Self::PrivateState<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<Self::PrivateState<'a>> {
todo!()
}
async fn create<'a>(
&self,
diags: &mut Diagnostics,
planned_state: Self::State<'a>,
config_state: Self::State<'a>,
planned_private_state: Self::PrivateState<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<(Self::State<'a>, Self::PrivateState<'a>)> {
todo!()
}
async fn update<'a>(
&self,
diags: &mut Diagnostics,
prior_state: Self::State<'a>,
planned_state: Self::State<'a>,
config_state: Self::State<'a>,
planned_private_state: Self::PrivateState<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<(Self::State<'a>, Self::PrivateState<'a>)> {
todo!()
}
async fn destroy<'a>(
&self,
diags: &mut Diagnostics,
prior_state: Self::State<'a>,
planned_private_state: Self::PrivateState<'a>,
provider_meta_state: Self::ProviderMetaState<'a>,
) -> Option<()> {
todo!()
}
async fn import<'a>(
&self,
diags: &mut Diagnostics,
_id: String,
) -> Option<(Self::State<'a>, Self::PrivateState<'a>)> {
diags.root_error_short("Import is not supported");
None
}
// async fn upgrade<'a>(
// &self,
// diags: &mut Diagnostics,
// _version: i64,
// _prior_state: RawValue,
// ) -> Option<Self::State<'a>> {
// diags.root_error_short("Upgrade is not supported");
// None
// }
}

1
src/resource/rule.rs Normal file
View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

1
src/resource/target.rs Normal file
View File

@@ -0,0 +1 @@