Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespaces are not Serializing #155

Closed
RileySeaburg opened this issue Feb 24, 2024 · 4 comments
Closed

Namespaces are not Serializing #155

RileySeaburg opened this issue Feb 24, 2024 · 4 comments

Comments

@RileySeaburg
Copy link

Great project here,

Just a note when trying to create any services inside a cluster using the API object leaves a error that comes up on basically every kubernetes object type.

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
pub struct KubernetesServiceResponse{
    namespace: String,
    serviceName: String,
    configMapName: String,
    ingressName: String,
    deploymentName: String,
}

impl KubernetesServiceResponse {
    pub fn new() -> KubernetesServiceResponse {
        KubernetesServiceResponse {
            namespace: "".to_string(),
            serviceName: "".to_string(),
            configMapName: "".to_string(),
            ingressName: "".to_string(),
            deploymentName: "".to_string(),
        }
    }
}

pub async fn deploy_kubernetes_service(
    domain: String,
    email: String,
    public_key: String,
    client_id: String,
    client_secret: String,
) -> Result<KubernetesServiceResponse, color_eyre::eyre::Error> {
    let mut kubernetes_service_response = KubernetesServiceResponse::new();
    let rand_number = rand::random::<u32>();
    let namespace_name_fallback = format!("quantum-forge-customer-{}", rand_number);
    let mut name_space_name = &domain.split(".").next().unwrap_or(&namespace_name_fallback);

// defining variables
    // defining yaml values to avoid string interpolation issues
    let ingress_name = &domain.split('.').next().unwrap_or("quantum-forge-customer");
    let ingress_host = &domain;
    let ingress_service_name = &domain.split('.').next().unwrap_or("quantum-forge-customer");
    let ingress_tls_host = &domain;
    let ingress_tls_secret_name = &domain.split('.').next().unwrap_or("quantum-forge-customer");

    let service_yaml = serde_yaml::from_str(&format!(
        r#"apiVersion: v1
kind: Service
metadata:
  name: {}-service
  namespace: {}
spec:
  selector:
    app: {}-app
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
    "#,
        &name_space_name,
        &name_space_name,
        &name_space_name
    )).unwrap();

// create the api interface
  let service_api = Api::<Service>::namespaced(client.clone(), domain.clone().split("").next().unwrap_or("quanutum-forge-customer"));
  
      // apply the service
    service_api
        .create(&PostParams::default(), &service_yaml)
        .await
        .unwrap();
        
        
    // check that the service was created
    loop {
        match service_api.get("quantum-forge-customer-platform").await {
            Ok(service) => {
                kubernetes_service_response.serviceName = service.clone().metadata.name.unwrap();
                println!(
                    "Service {} is ready.",
                    service.metadata.name.unwrap_or_default()
                );
                break;
            }
            Err(e) => {
                println!("Error checking service: {:?}", e);

                tokio::time::sleep(Duration::from_secs(5)).await;
            }
        }
    }
    ...more code here for services
    
        Ok(kubernetes_service_response)
}
thread 'actix-rt|system:0|arbiter:0' panicked at 'called `Result::unwrap()` on an `Err` value: Api(ErrorResponse { status: "Failure", message: "Service \"rileyseaburg-service\" is invalid: metadata.namespace: Required value", reason: "Invalid", code: 422 })', src\controllers\api\onboarding.rs:436:10

As you can see the Namespace for the service is clearly defined using an object from earlier.
When we runt the print on this object the namespace is represented as Some("namespace_name");

It appears there is a serialization error, but it's not happening when the service is defined, rather its occurring when the API is called, and the service is being created.

@clux
Copy link

clux commented Feb 24, 2024

this is more kube related than k8s-openapi since you are bypassing the structs entirely. i don't use create much myself since it's an older pattern, but on a suspicious note, are you passing string serialised yaml to the api (which takes json)? see a normal create example.

you can also increase the log level of kube to see what goes on the wire.

@RileySeaburg
Copy link
Author

Hey @clux I appreciate your swift response.

I'm not sure what you referring to in regards to "bypassing the structs".

I can confirm that the Yaml version does work for creating namespaces.
It also works for creating deployments.

It just seems to get stuck on other items such as ingresses.

I'll go ahead and serialize my yaml to json and see what I come up with.

Thanks again and great project.

@Arnavion
Copy link
Owner

@clux I'm surprised this works as well, but also the doc of Api::create does specifically allow it:

This function requires a type that Serializes to K, which can be:

  1. Raw string YAML

@RileySeaburg
Copy link
Author

Lol @Arnavion

error prone (run-time errors on
typos due to failed serialize
attempts)

Can confirm this is true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants