Abstract

First of all, the following categories of readers are invited to mark their seats:

  • Those who are familiar with CMDB but new to Python are strongly advised to read the first few articles;
  • This article is highly recommended for those who have little knowledge of Python and can only write simple scripts;
  • This article is recommended for those who are comfortable writing Python scripts but not familiar with CMDB.
  • For those of you who know both Python and CMDB, go out and turn left for the next one.

In the last section, I took readers through a series of thinking before reading the source code, and developed some of our programming ideas, and then read part of the source code of CMDB V1.0.py, so today we start without too much verbose, followed by a section directly on the work.

On dry

Adding Asset Information

After initializing the region information, the first thing we need to do is add the asset information

  1. As we discussed in the last lesson, we should first consider what needs to be noted to implement this feature:
  • What kind of information to add?
  • Where to add information and how to locate the path to add?
  • How to persist updated data?
  1. Here I first in turn to you answer:
  • Because our data source isJSONThe format is stored in a text file, so we have to make sure that the information we add is as welljsonformat
  • JSONThe data source of the format corresponds to the dictionary in Python, so the dictionary can be indexed by key, so we can search for the dictionary position through the arrangement of multiple keys, for example, can bekey1/key2/key3In the form of
  • Persistence of data still chooses to passJSONTo persist data to a text file
  1. Now that we have a basic idea of how to add asset information, we need to refine the idea even further into implementable pseudocode:
  • We need to define oneadd()Function to implement this function, and this function needs to take two parameters, respectively the information to add and the specified path to update the information, then our function signature should beadd(attrs, path)

“Attrs” is an abbreviation for “attributes”. In the process of writing code, I hope you will develop a good habit of naming variables with proper standard names. Beginners should avoid using pinyin to name variables or functions.

  • What we pass inattrsMust be a string in JSON format, passed inpathMust be a pass/Delimited string
  • throughpathTo locate the specified location in the data source hierarchically, by dictionary assignmentattrsAdd to the data source
  • throughjson.loadandjson.dumpDo data persistence
  1. The next step is to write a pseudo-code that can achieve the above functions, as follows:
def add(path, attrs) :
    # Judge the validity of attrs
    if attrs is valid
    Parse attrs to a Python type
    attrs = parse_attrs()
    Read the data source from a text file
    data = read_file()
    # Split the path
    seg = path.split()
    Locate the specified location of the data source based on the path
    target_path = position_data()
    Add attrs to the specified path
    data[target_path] = attrs
    Save the data to a text file
    write_file(data)
    # print data source
    print(data)
Copy the code
  1. The final source code for adding asset information is as follows:
def add(path, attrs=None) :
    if attrs is None:  # Judge the validity of attrs
        print("add operation must have attrs arg")
        return
    try:  Parse attrs to a Python type
        attrs = json.loads(attrs)
    except Exception:
        print("input attribute is an invalid json string")
        return
    with open("data.json"."r+") as f:  Read the data source from a text file
        data = json.load(f)
    path_seg = path.split("/")  # Split the path
    target_path = data
    for idx, seg in enumerate(path_seg[1:]):  Locate the specified location of the data source based on the path
        if idx == len(path_seg)-2:
            if seg in target_path:
                print("%s already exists in %s, please use update operation" %
                      (seg, path))
                return
            target_path[seg] = attrs  Add attrs to the specified path
            break
        target_path = target_path[seg]
    with open("data.json"."w+") as f:  Save the data to a text file
        data = json.dump(f, indent=2)
    print(json.dumps(data, indent=2))  # print data source
Copy the code

Many readers may feel a little confused at step 5, as if they have just learned 1+1=2 and are jumping to advanced algebra and calculus, but each part of the code is easier to understand in isolation.

  • judgeattrsAnd will beattrsParse to Python type
if attrs is None:
    print("add operation must have attrs arg")
    return
try:  Parse attrs to a Python type
    attrs = json.loads(attrs)
except Exception:
	print("input attribute is an invalid json string")
    return
Copy the code

Loads are being parsed with json.loads are being parsed with json.loads are being parsed with loads that are not valid json. You need to exit the function; If attrs is valid JSON, we can parse it as a Python data type and apply it in the following code. About the try… Except we will talk about it in detail.

The way to check whether a variable is None in Python is not if var == None, but if var is None. We recommend using the second method.

  • Read the data source from a file

This step is to use what we talked about last time, and I won’t repeat it here

  • segmentationpathThe path
path_seg = path.split("/") [1:]  # Split the path
Copy the code

Str.split () is used to split a string. By passing in a delimiter, you can split the string into arrays and return them. So path_seg is an array of paths. Location layer by layer to the specified location of the data source. Here, the principle of array slicing is also applied. Since the path is assumed to be in the format of /region/ IDC /switch, the path array will be [“”, “region”, “IDC “, “switch”] according to /, and the first element will be an empty string. So only the second to last path elements are taken by path_seg[1:].

  • Locates the specified location of the data source based on the path and willattrsAdd to the specified path
target_path = data
for idx, seg in enumerate(path_seg):  Locate the specified location of the data source based on the path
    if idx == len(path_seg)-1:
        if seg in target_path:
            print("%s already exists in %s, please use update operation" % (seg, path))
            return
        target_path[seg] = attrs  Add attrs to the specified path
 		break
    target_path = target_path[seg]
Copy the code

First, we define a variable target_path for the target path, which is equal to the outermost layer of the entire data at the beginning. In the following loop, it will be updated continuously. Enumerate (), a Python syntactic sugar used in looping statements, loops over both subscripts and contents by passing in an iterable (in this case, our path array), For IDX, seg in enumerate(path_seg[1:]) IdX and SEG indicate the subscript and content of a certain path in the path array respectively.

Here to explain the essence of the loop statement, the loop is actually a repeated operation in the execution, when reaching a certain boundary conditions will exit the loop, so the general loop statement will have boundary conditions, if there is no boundary conditions we call it an infinite loop.

The boundary condition of our code block above is to iterate through the entire array of paths, evaluating data layer by layer and returning each time, until we reach the last element of the array of paths (its subscript idx == len(path_seg)-1, -1 because the subscript starts at 0, So the length of the array will be bigger than the last subscript 1), then we can judge whether the path element exists in the current position, if there are instructions can not add, directly through the return exit function, if there is no our way through the dictionary assignment will attrs is added to the position, and through the end of the break.

Tips: break and continue

For those new to programming, the difference between break and continue may not be clear. Break can be interpreted as simply exiting the loop, regardless of whether the loop reaches a boundary condition or not. Continue skips the loop and continues the next loop if the boundary condition has not been reached. The following code

for i in [1.2.3] :if i == 2:
        continue
    print(i)
 Output 1, 3
 for i in [1.2.3] :if i == 2:
        break
    print(i)  
 Output 1 #
Copy the code

The above description may be a little difficult to understand, but let’s Debug to see the value of the variable each time through the loop.

Suppose we have executed the statement Python cmdb-v1.0.py init Beijing, then our data source is as follows:

{
  "beijing": {
    "idc": "beijing"."switch": {},
    "router": {}}}Copy the code

So that’s when we execute

Python CMDB – v1.0. Py the add/Beijing/switch / 10.0.0.1 ‘{\ “IP \” : \ “10.0.0.1 \”, \ “role \” : \ “asw \}’ for debugging

/ Beijing /switch/10.0.0.1 is the path we want to specify

‘{\ “IP \” : \ “10.0.0.1 \”, \ “role \” : \ “asw \}’ is the information, we will add the information here is a json format string

  1. The values of the variables before the loop is started are as follows

The target_path = {” Beijing “: {” idc” : “Beijing”, “switch” : {}, “router” : {}}}

  1. After the end of the first loop, the values of each variable are as follows

At this time of the seg = “Beijing” target_path = {” idc “:” Beijing “, “switch” : {}, “router” : {}}

  1. The values of each variable after the second cycle are as follows

At this time of the seg = “switch” target_path = {” idc “:” Beijing “, “switch” : {}, “router” : {}}

  1. When I loop the last time

Seg = “10.0.0.1” targe_path = {}, idc and path_seg are the same length, and seG does not exist, so you can update attrs to target_path.

Target_path is a pointer that starts at the outermost layer of the dictionary. As the loop goes through, it moves up and down the seG hierarchy until it points to the target path. Adding attrs completes the final operation.

The final data are as follows:

{
  "beijing": {
    "idc": "beijing"."switch": {
      "10.0.0.1": {
        "ip": "10.0.0.1"."role": "asw"}},"router": {}}}Copy the code

In this section, we’ll stop here, this time we mainly explained the add asset information source in detail, looks though the code is not long, but really need to pay attention to the ideas and new friends note there are still a lot of knowledge points, debugging and running, hope we can go to yourself carefully experience every loop variables in the process of change. Look forward to the next section.

After the article language

In fact, this section in addition to the code details, we read the source code before the five steps are more critical. According to me the interpretation of the above five steps, you can find again, in the process of programming, the former one to four steps can be said to be the final code, forming the foundation and the above four steps in the process does not need we understand what a specific programming language, but we need to make full use of the thought of programming, to solve the problem step by step apart; The fifth step is to use the code to achieve, and we choose Python is a relatively easy language to use, which is also friendly to the friends who are new to programming. Finally, I hope you can develop good programming ideas in the process of learning step by step with me.


Welcome to add my personal public account [Python Playing automated Operation and Maintenance] to the reader exchange group, to get more dry content