Automation

last person joined: 2 days ago 

Ask questions and share experiences about Apstra, Paragon, and all things network automation.
  • 1.  for-each loop newbie issue

    Posted 02-25-2014 10:22

    Hi All,

     

    I'm new to scripting so this is definitely a noobie mistake but I can't figure it out.

    I'm trying to create a list of users and loop through the list. For each user that is not configured the script is to create it. The idea is to prevent these users from being accidentally deleted. I want it to report that it's recreating each user it has to, and only recreate the missing users but I'm not getting it right. This is what I'm trying to do (but doesn't work) :

     

     

    var $agents := {
       <name> "aaa";
       <name> "bbb";
       <name> "ccc";
    }

     

    match configuration {
       for-each ($agents/name) {
          if (jcs:empty(system/login/user[name==.])) {            /* This always calc's true even when user exists */
              <xnm:warning> {
                  <message> "Recreating deleted user "_.;        /* This way generates a commit error, not sure how to output */
              }                                                                                        /* which user is being recreated */
              <change> {
                 <system> {
                      <login> {
                           <user> {
                               <name> .;     /* this part actually works fine */
                               <class> "default";
         }
        }
       }
      }
     }
    }

     

    I appreciate the help on this.
    William



  • 2.  RE: for-each loop newbie issue

     
    Posted 02-25-2014 11:01
    ns exsl="http://exslt.org/common" ;
    
        var $agents = {
    	<name> "aaa" ;
    	<name> "bbb" ;
    	<name> "ccc" ;
        }
    
        for-each(exsl:node-set($agents)/*){
            if (jcs:empty($some-config/system/login/user[name==.])) {
                ...
    	}
    

    Try node-set conversion as above.

     

    Thanks,

    /Charlie



  • 3.  RE: for-each loop newbie issue

    Posted 02-25-2014 11:32

    Hi Charlie,

     

    Thanks for the reply. I tried this but I got the same result as before:

     

    This line:

    if (jcs:empty(system/login/user[name==.]))   --> still returns true even if the users are already created, so the if loop gets processed for every user whether or not it needs to be.

     

    And this line:

    <message> "Recreating deleted user ";  -> I haven't found a way to add the user here that won't generate an error at commit time.

     

    For example,

    <message> "Recreating deleted user "_.;    -> generates an error: unexpected input: '_.'; expected semi-colon (';')

     

     

    William



  • 4.  RE: for-each loop newbie issue

     
    Posted 02-25-2014 12:53

    This doesn't include configuration change part, but you may use it I think.

     

    	var $agents = {
    		<name> "ckim" ;
    		<name> "lab" ;
    		<name> "ccc" ;
    	}
    
    	var $get-config = <get-config> {
    		<source> {
    			<running> ;
    		}
    		<filter type="subtree"> {
    			<configuration> {
    				<system> {
    					<login> {
    						<user> ;
    					}
    				}
    			}
    		}
    	}
    	var $cur-config = jcs:invoke($get-config) ;
    
    	for-each(exsl:node-set($agents)/*){
    		var $agent = . ;
    		if( jcs:empty($cur-config/configuration/system/login/user[name == $agent])){
    			<output> "agent: " _ $agent _ " does not exist. add it." ;
    		}
    	}
    

     

    Sameple output is;

    ckim@mx480-ptsp> op url /var/home/ckim/test2.slax    
    agent: ccc does not exist. add it.
    
    ckim@mx480-ptsp> 

     

    Thanks,

    /Charlie

     



  • 5.  RE: for-each loop newbie issue

    Posted 02-26-2014 08:16

    Hi Charlie,

     

    I appreciate the help on this. That resolves one of the problems I was seeing!

     

    I'm creating a commit script so I adapted your suggestion a little bit and it almost works perfectly. There is just one problem I still can't figure out. The if statement runs whether or not the user exists. I attached the code I have so far. The output I get is this:

     

    >commit
    warning: User missing. Readding user: aaa
    warning: User missing. Readding user: bbb
    warning: User missing. Readding user: ccc
    configuration check succeeds
    commit complete

     

    It successfully adds the user to the configuration but it always thinks the user is not there whether it is or not. For example, this output I got when all three users were present in the configuration.

     

    The wierd thing is I have a similar if structure to check if 'class default' is created and that one works perfectly. The only difference is that I compare a literal string "default" in the structure that works and in the one that doesn't work I'm comparing the var $agent....

     

    William



  • 6.  RE: for-each loop newbie issue

     
    Posted 02-26-2014 09:28

    Hi William,

     

    Could you attach whole script to review?

     

    Thanks,

    /Charlie



  • 7.  RE: for-each loop newbie issue

    Posted 02-26-2014 09:47

    version 1.1;

     

    ns junos = "http://xml.juniper.net/junos/*/junos";
    ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
    ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
    ns exsl="http://exslt.org/common";

     

    import "../import/junos.xsl";

     

    var $agents = {
     <name> "aaa";
     <name> "bbb";
     <name> "ccc";
    }

     

    match configuration {


     for-each (exsl:node-set($agents)/*) {
      var $agent = .;

     

      /* This if statement always evaluates to true even when agent does exist! */
      if (jcs:empty(system/login/user[name==$agent])) {
       <xnm:warning> {
        <message> "User missing. Readding user: "_$agent;
       }
       <change> {
        <system> {
         <login> {
          <user> {
           <name> $agent;
           <class> "default";
          }
         }
        }
       }
      }
     }


     /* This if structure works exactly as it's supposed to */
     if (jcs:empty(system/login/class[name=="default"])) {
      <xnm:warning> {
       <message> "Recreating Class Default";
      }
      <change> {
       <system> {
        <login> {
         <class> {
          <name> "default";
          <permissions> "all";
         }
        }
       }
      }
     }
    }

     

     

    Thanks,

    William



  • 8.  RE: for-each loop newbie issue
    Best Answer

     
    Posted 02-26-2014 21:55

    Try below. The user names are captured in a node-set to reuse them. This script is using your original node-set pattern.

     

    version 1.1;
    
    ns junos = "http://xml.juniper.net/junos/*/junos";
    ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
    ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
    
    import "../import/junos.xsl";
    
    var $agents := { 
    	<name> "aaa";
    	<name> "bbb";
    	<name> "ccc";
    }
    
    match configuration {
    	var $the-users := {
    		for-each(system/login/user/name){
    			<name> . ;
    		}
    	}
    	for-each ($agents/name) {
    		var $agent = . ;
    		if (! $the-users[name=$agent]) {
    			<xnm:warning> {
    				<message> "User missing. Readding user: "_$agent;
    			}
    			<change> {
    				<system> {
    					<login> {
    						<user> {
    							<name> $agent;
    							<class> "default";
    						}
    					}
    				}
    			}
    		}
    	}
    	/* This if structure works exactly as it's supposed to */
    	if (jcs:empty(system/login/class[name=="default"])) {
    		<xnm:warning> {
    			<message> "Recreating Class Default";
    		}
    		<change> {
    			<system> {
    				<login> {
    					<class> {
    						<name> "default";
    						<permissions> "all";
    					}
    				}
    			}
    		}
    	}
    }

     

    Thanks,

    /Charlie



  • 9.  RE: for-each loop newbie issue

    Posted 02-27-2014 08:19

    Thanks Charlie,

     

    You did it! I finally have it working the way I wanted it. I'm not sure if I totally understand why we needed to do it this way but I'll keep this trick in mind for future implementations that have a similar configuration.

     

    I appreciate the help and following up with me until we got it fixed.

     

    William