Postman Collection to Copy Port Configs from one MS Switch Model to Another

Solved
Richard_B
Here to help

Postman Collection to Copy Port Configs from one MS Switch Model to Another

Working to upgrade some MS-350s to MS-355 so can't use the clone function. I had this script working for awhile, but it seems something changed with how the voiceVlan field is handled. So the collection runs with 48 iterations, a Get and Put operation for each switch port.

 

When using Get to pull switchport settings (MS-350), the voiceVlan field is blank, but when it is Put to the replacement switch (MS-355), the word null is required without quotes.

 

I could assign null manually, but the problem is I don't want to overwrite the port configs where the voiceVlan value is not null. When a voice vlan is configured on the port, the script works fine. I need an If "blank" statement to assign the value of null, just don't know how to write that statement in JSON.

 

Any thoughts on how to modify the JSON test to change voiceVlan variable value from "" to "null"?

 

This runs in tests on Get request:

var jsonData = JSON.parse(responseBody);
number = jsonData.number;
console.log(number);
pm.environment.set("number", number);
name = jsonData.name;
console.log(name);
pm.environment.set("name", name);
tags = jsonData.tags;
console.log(tags);
pm.environment.set("tags", tags);
enabled = jsonData.enabled;
console.log(enabled);
pm.environment.set("enabled", enabled);
poeEnabled = jsonData.poeEnabled;
console.log(poeEnabled);
pm.environment.set("poeEnabled", poeEnabled);
type = jsonData.type;
console.log(type);
pm.environment.set("type", type);
vlan = jsonData.vlan;
console.log(vlan);
pm.environment.set("vlan", vlan);
voiceVlan = jsonData.voiceVlan;
console.log(voiceVlan);
pm.environment.set("voiceVlan", voiceVlan);
allowedVlans = jsonData.allowedVlans;
console.log(allowedVlans);
pm.environment.set("allowedVlans", allowedVlans);
isolationEnabled = jsonData.isolationEnabled;
console.log(isolationEnabled);
pm.environment.set("isolationEnabled", isolationEnabled);
rstpEnabled = jsonData.rstpEnabled;
console.log(rstpEnabled);
pm.environment.set("rstpEnabled", rstpEnabled);
stpGuard = jsonData.stpGuard;
console.log(stpGuard);
pm.environment.set("stpGuard", stpGuard);
accessPolicyNumber = jsonData.accessPolicyNumber;
console.log(accessPolicyNumber);
pm.environment.set("accessPolicyNumber", accessPolicyNumber);
linkNegotiation = jsonData.linkNegotiation;
console.log(linkNegotiation);
pm.environment.set("linkNegotiation", linkNegotiation);

 

 

This runs with Put request after the Get populates variable values

{
"number": {{number}},
"name": "{{name}}",
"tags": "{{tags}}",
"enabled": {{enabled}},
"poeEnabled": {{poeEnabled}},
"type": "{{type}}",
"vlan": {{vlan}},
"voiceVlan": {{voiceVlan}},
"allowedVlans": "{{allowedVlans}}",
"isolationEnabled": {{isolationEnabled}},
"rstpEnabled": {{rstpEnabled}},
"stpGuard": "{{stpGuard}}",
"accessPolicyNumber": "{{accessPolicyNumber}}",
"linkNegotiation": "{{linkNegotiation}}"
}

 

1 Accepted Solution
Richard_B
Here to help

Update: It looks like there was a back end problem in Meraki causing this because we opened a case and it is now resolved. Using Get to pull switchport configs from MS-350 populates null as the voiceVlan value if there is no number assigned.

View solution in original post

13 Replies 13
vassallon
Kind of a big deal

Based on this link Handling JSON null and empty arrays and objects I would think you should be able to edit your code to use the following: 

 

"voiceVlan": null,

 

 

Found this helpful? Give me some Kudos! (click on the little up-arrow below)
Richard_B
Here to help

Thanks for replying. Yes, I could assign null manually, but the problem is I don't want to overwrite the port configs where the voiceVlan value is not null. When a voice vlan is configured on the port, the script works fine. I need an If "blank" statement to assign the value of null, just don't know how to write that statement in JSON.

jdsilva
Kind of a big deal

Just omit it completely from the PUT.

Richard_B
Here to help

Thanks, problem would be I would lose the config on any ports where a voice vlan value is assigned.

jdsilva
Kind of a big deal


@Richard_B wrote:

Thanks, problem would be I would lose the config on any ports where a voice vlan value is assigned.


I don't think that's true. If you omit the value it should just not modify it from current. Have you tried this?

Richard_B
Here to help

The problem, is I need to modify the value from current. The switch I am copying from might have no voice vlan configured or it might have vlan 815 for example. I need the switch I am copying to (currently at factory defaults) to get the value rather it is null or 815.

vassallon
Kind of a big deal

@Richard_B Okay, I think I understand better now. You are looking something along the lines of this:

 

If the value is blank then null 

 else return stored value

 

Let me see if I can figure anything out then to help you.

Found this helpful? Give me some Kudos! (click on the little up-arrow below)
Richard_B
Here to help

Exactly, thank you!

vassallon
Kind of a big deal

@Richard_B 

 

I think you would be after something like this:

 


protected String getOrNull(JSONObject voiceVlan, String key)
{
if (voiceVlan != null && json.containsKey(key))
{
return (String) json.get(key);
}
return null;
}

 

If this works I modified the code on example 9 from this site. https://www.programcreek.com/java-api-examples/?class=org.json.simple.JSONObject&method=containsKey

 

If not you might be able to find something that works with some modifications for your needs.

Found this helpful? Give me some Kudos! (click on the little up-arrow below)
Richard_B
Here to help

Thank you very much for the sample code. Trying to paste in one line at a time to validate.

 

I am having trouble with it, might be a Postman formatting difference, not sure.

 

Error on first statementError on first statement

vassallon
Kind of a big deal

@DexterLaBora Do you have any thoughts on how this might best be accomplished?

Found this helpful? Give me some Kudos! (click on the little up-arrow below)
DexterLaBora
Meraki Employee
Meraki Employee

I recently posted a project to accomplish a similar task of cloning a switch with a simple web app. 
https://community.meraki.com/t5/Solutions-APIs/Meraki-Switch-Swapper/m-p/53897#M1613

The project is built with VueJS so it's not an exact answer to your question regarding Postman. 



The basic web app flow:
- API call to pull source switch settings
- API call to pull source switch ports

- pull similar switch from inventory or same network

- clone switch by creating an action batch to make all changes

- loop each second to check status of action batch

 


Ultimately, you will want to use Action Batches to accomplish this in the most efficient way. 

tl;dr

The SwitchClone component that handles the clone logic.

example of "onClone" function within this Vue.js component.

onClone() {
      console.log(
        "Cloning Switches,  this.oldSwitchDetails.serial, this.newSwitchDetails.serial",
        this.oldSwitchDetails.serial,
        this.newSwitchDetails.serial
      );
      // set new switch settings/ports to that of old switch and remove hard coded properties
      let switchDetails = {};
      switchDetails = { ...switchDetails, ...this.oldSwitchDetails };
      delete switchDetails.serial;
      delete switchDetails.mac;
      console.log(
        "Cloning Switches AFTER MODs, this.oldSwitchDetails.serial, this.newSwitchDetails.serial",
        this.oldSwitchDetails.serial,
        this.newSwitchDetails.serial
      );
      this.loading = true;
      this.batchUpdateSwitch(
        this.orgId,
        this.netId,
        this.oldSwitchPorts,
        switchDetails,
        this.newSwitchDetails.serial
      ).then(res => {
        this.actionBatchDetails = res;
        if (!this.actionBatchDetails) {
          return;
        }
        // pull batch status (improve logic)
        let statusInterval = setInterval(() => {
          console.log("statusInterval");
          this.checkBatchUpdateStatus(
            this.orgId,
            this.actionBatchDetails.id
          ).then(res => {
            console.log("statusInterval", res);
            this.actionBatchDetails = res;
            // Handle Clone Results
            if (
              this.actionBatchDetails.status.completed ||
              this.actionBatchDetails.status.failed
            ) {
              console.log("clearing statusInterval");
              clearInterval(statusInterval);
            }
            if (this.actionBatchDetails.status.completed) {
              this.$emit("updatedSwitchDetails", this.updatedSwitchDetails);
              // refresh updated device details
              this.fetchSwitchDetails(this.newSwitchDetails.serial)
                .then(res => {
                  this.updatedSwitchDetails = res;
                  this.$emit("updatedSwitchDetails", this.updatedSwitchDetails);
                  return res;
                })
                .then(res => {
                  return this.fetchSwitchPorts(this.newSwitchDetails.serial);
                })
                .then(res => {
                  this.updatedSwitchPorts = res;
                  this.$emit("updatedSwitchPorts", this.updatedSwitchPorts);
                  return res;
                })
                .then(res => {
                  this.successDialog = true;
                })
                .catch(e => this.handleError(e))
                .finally(() => {
                  this.loading = false;
                });
            }
            if (this.actionBatchDetails.status.failed) {
              // Batch updated
              this.failDialog = true;
              this.loading = false;
            }
          });
        }, 2000); // wait 2 seconds and get status
      });
    },

 
You could modify this application to accept switches of different model types. The SwapForm component defines the filter logic. I just check for matching models but this could easily be adjusted.

    unusedAndNetworkSwitchesModelMatch() {
      return this.form.orgInventory.filter(i => {
        return (
          (i.networkId == this.network.id || !i.networkId) &&
          i.model == this.form.oldSwitchDetails.model &&
          i.serial != this.form.oldSwitchDetails.serial
        );
      });

 


Regarding the Python library setting empty properties as `null`, this is being investigated as a bug with the dynamic SDKs.


Hope this helps! 

Richard_B
Here to help

Update: It looks like there was a back end problem in Meraki causing this because we opened a case and it is now resolved. Using Get to pull switchport configs from MS-350 populates null as the voiceVlan value if there is no number assigned.

Get notified when there are additional replies to this discussion.