# Get controllers without async

**URL:** <https://forum.dfinity.org/t/get-controllers-without-async/16719>\
**Category:** Rust\
**Created:** [November 20, 2022, 12:14pm UTC](https://forum.dfinity.org/t/get-controllers-without-async/16719 "2022-11-20T12:14:43Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![GLdev](https://avatars.discourse-cdn.com/v4/letter/g/4bbf92/32.png) [@GLdev](https://forum.dfinity.org/u/GLdev)\
**Post date:** [November 21, 2022, 7:08pm UTC](https://forum.dfinity.org/t/get-controllers-without-async/16719/6 "2022-11-21T19:08:39Z")

</div>

> [@peterparker](#):
>
> that’s indeed what I had in mind - i.e. passing the list of controllers I would like to whitelist for calls as init param

Cool, then this should work. There are, however, some caveats. On the spawner canister you have to keep track of the principals you want to add as controllers, and do it in **2** places, to maintain further functionality with dfx / direct calling of the newly spawned canister.

In order to spawn a new canister the spawner canister needs to make 2 calls to the management canister: `create_canister` and `install_code`.

First, in order for the system (i.e. the management canister) to register a principal as a controller of a canister (with full controller powers) it needs to be added in the `create_canister` call.

```auto
#[derive(CandidType, Debug, Clone, Deserialize)]
pub struct CreateCanisterSettings {
    pub controllers: Option<Vec<Principal>>, //<--- HERE
    pub compute_allocation: Option<Nat>,
    pub memory_allocation: Option<Nat>,
    pub freezing_threshold: Option<Nat>,
}

#[derive(CandidType, Clone, Deserialize)]
pub struct CreateCanisterArgs {
    pub cycles: u64,
    pub settings: CreateCanisterSettings,
}

```

Whatever controllers you add here will have full controller status (that means they will be able to directly call the canister from dfx / whatever).

One issue is that the newly spawned canister can only receive arguments from the install\_code (_I think_). So we need to also add the same controllers to the `install_code` call.

```auto
#[derive(CandidType, Deserialize)]
enum InstallMode {
    #[serde(rename = "install")]
    Install,
    #[serde(rename = "reinstall")]
    Reinstall,
    #[serde(rename = "upgrade")]
    Upgrade,
}

#[derive(CandidType, Deserialize)]
struct CanisterInstall {
    mode: InstallMode,
    canister_id: Principal,
    #[serde(with = "serde_bytes")]
    wasm_module: Vec<u8>,
    #[serde(with = "serde_bytes")]
    arg: Vec<u8>, // <-- HERE
}

```

This “arg” gets passed down to the newly spawned canister, and it can read it from init() (as a sidetrack, also from pre\_ and post\_upgrade).

The way I managed to send this was like so:

```auto
#[derive(CandidType, Deserialize)]
struct CanisterInstallSendArgs {
    greet: String,
    controllers: Vec<Principal>,
}

let canister_install_args = Encode!(&CanisterInstallSendArgs {
                greet: "Hello from Index".to_string(),
                controllers: vec![Principal::from_text(
                    "l6s27-7ndcl-nowe5-xeyf7-ymdnq-dkemz-jkhfw-zr5wu-jvf2p-aupzq-2qe",
                )
                .unwrap(),],
            })
            .unwrap();

```

Where `CanisterInstallSendArgs` is something you define. I added a “greet” there just to test things out. This struct is what you get on the other side, from init().

Keep in mind that it’s on you to make sure the principal vecs look the same in both calls.

Also, as I mentioned previously, if someone adds a new controller via dfx it will be missed by this approach.

Speaking of init(), there’s a prettier way of accessing the args than that ugly thing I used first time 🙂 Check out [this](https://forum.dfinity.org/t/how-to-pass-install-arguments-from-dfx/12977) post for details. tl;dr; you can decorate the init() function with the `#[candid_method(init)]` macro, and the service will be correctly interpreted in the .did file and allow you to send install\_code arguments from dfx as well. (rust to rust would work with just what I described above)

---

_[View the full topic](https://forum.dfinity.org/t/get-controllers-without-async/16719)._
