github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/es/writer/esAliases.go (about)

     1  /*
     2  Copyright 2023.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package writer
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  
    23  	jsoniter "github.com/json-iterator/go"
    24  	"github.com/siglens/siglens/pkg/utils"
    25  	vtable "github.com/siglens/siglens/pkg/virtualtable"
    26  	log "github.com/sirupsen/logrus"
    27  	"github.com/valyala/fasthttp"
    28  )
    29  
    30  func ProcessGetAlias(ctx *fasthttp.RequestCtx, myid uint64) {
    31  	log.Infof("ProcessGetAlias:")
    32  	aliasName := utils.ExtractParamAsString(ctx.UserValue("aliasName"))
    33  
    34  	respbody := make(map[string]interface{})
    35  	pres, indexName := vtable.IsAlias(aliasName, myid)
    36  	if !pres {
    37  		respbody["error"] = fmt.Sprintf("alias [%v] missing", aliasName)
    38  		respbody["status"] = 404
    39  		utils.WriteJsonResponse(ctx, respbody)
    40  		ctx.SetStatusCode(fasthttp.StatusNotFound)
    41  		return
    42  	}
    43  
    44  	// if it is a alias, then we have to do reverse lookup and find the index
    45  
    46  	emptyMap := make(map[string]interface{})
    47  	abody := make(map[string]interface{})
    48  	curIdxAliases, err := vtable.GetAliases(indexName, myid)
    49  	if err == nil {
    50  		for k := range curIdxAliases {
    51  			abody[k] = emptyMap
    52  		}
    53  	}
    54  	tBody := make(map[string]interface{})
    55  	tBody["aliases"] = abody
    56  	respbody[indexName] = tBody
    57  
    58  	utils.WriteJsonResponse(ctx, respbody)
    59  	ctx.SetStatusCode(fasthttp.StatusOK)
    60  }
    61  
    62  func ProcessGetAllAliases(ctx *fasthttp.RequestCtx, myid uint64) {
    63  
    64  	respbody := make(map[string]interface{})
    65  	allIndices, err := vtable.GetVirtualTableNames(myid)
    66  	if err != nil {
    67  		log.Errorf("ProcessGetAllAliases: Failed to get aliases for myid=%v, err=%v", myid, err)
    68  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
    69  		respbody := make(map[string]interface{})
    70  		respbody["error"] = err.Error()
    71  		utils.WriteJsonResponse(ctx, respbody)
    72  		return
    73  	}
    74  	emptyMap := make(map[string]interface{})
    75  
    76  	for idxName := range allIndices {
    77  		abody := make(map[string]interface{})
    78  		curIdxAliases, err := vtable.GetAliases(idxName, myid)
    79  		log.Debugf("ProcessGetAllAliases: idxName=%v, curIdxAliases=%v", idxName, curIdxAliases)
    80  		if err == nil {
    81  			for k := range curIdxAliases {
    82  				log.Debugf("ProcessGetAllAliases: idxName=%v, k=%v", idxName, k)
    83  				abody[k] = emptyMap
    84  			}
    85  		}
    86  		tBody := make(map[string]interface{})
    87  		tBody["aliases"] = abody
    88  		log.Debugf("ProcessGetAllAliases: abody=%v, tBody=%v", abody, tBody)
    89  		respbody[idxName] = tBody
    90  	}
    91  
    92  	utils.WriteJsonResponse(ctx, respbody)
    93  	ctx.SetStatusCode(fasthttp.StatusOK)
    94  
    95  }
    96  
    97  func ProcessGetIndexAlias(ctx *fasthttp.RequestCtx, myid uint64) {
    98  
    99  	indexName := utils.ExtractParamAsString(ctx.UserValue("indexName"))
   100  
   101  	if indexName == "" {
   102  		log.Errorf("ProcessGetIndexAlias: one of nil indexName=%v", indexName)
   103  		utils.SetBadMsg(ctx, "")
   104  		return
   105  	}
   106  	log.Infof("ProcessGetIndexAlias: indexName=%v", indexName)
   107  
   108  	currentAliases, err := vtable.GetAliases(indexName, myid)
   109  	if err != nil {
   110  		log.Errorf("ProcessGetIndexAlias: GetAliases returned err=%v", err)
   111  		utils.SetBadMsg(ctx, "")
   112  		return
   113  	}
   114  
   115  	respbody := make(map[string]interface{})
   116  	alvalues := make(map[string]interface{})
   117  	alvalues["aliases"] = currentAliases
   118  	respbody[indexName] = alvalues
   119  
   120  	utils.WriteJsonResponse(ctx, respbody)
   121  	ctx.SetStatusCode(fasthttp.StatusOK)
   122  }
   123  
   124  func ProcessPutAliasesRequest(ctx *fasthttp.RequestCtx, myid uint64) {
   125  	indexName := utils.ExtractParamAsString(ctx.UserValue("indexName"))
   126  	aliasName := utils.ExtractParamAsString(ctx.UserValue("aliasName"))
   127  
   128  	if indexName == "" || aliasName == "" {
   129  		log.Errorf("ProcessPutAliasesRequest: one of nil indexName=%v, aliasName=%v", indexName, aliasName)
   130  		utils.SetBadMsg(ctx, "")
   131  		return
   132  	}
   133  	log.Infof("ProcessPutAliasesRequest: add alias request, indexName=%v, aliasName=%v", indexName, aliasName)
   134  	err := vtable.AddAliases(indexName, []string{aliasName}, myid)
   135  	if err != nil {
   136  		log.Errorf("ProcessPutAliasesRequest: failed to add alias, indexName=%v, aliasName=%v, err=%v", indexName, aliasName, err)
   137  		utils.SetBadMsg(ctx, "")
   138  		return
   139  	}
   140  
   141  	respbody := make(map[string]interface{})
   142  	respbody["acknowledged"] = true
   143  	utils.WriteJsonResponse(ctx, respbody)
   144  	ctx.SetStatusCode(fasthttp.StatusOK)
   145  }
   146  
   147  /*
   148     {
   149  	"actions" : [
   150  		{ "add" : { "index" : "test1", "alias" : "alias1" } }
   151  	]
   152  	}
   153  */
   154  
   155  func ProcessPostAliasesRequest(ctx *fasthttp.RequestCtx, myid uint64) {
   156  	r := bytes.NewReader(ctx.PostBody())
   157  
   158  	log.Infof("ProcessPostAliasesRequest: body=%v", string(ctx.PostBody()))
   159  
   160  	jsonBody := make(map[string]interface{})
   161  	var json = jsoniter.ConfigCompatibleWithStandardLibrary
   162  	decoder := json.NewDecoder(r)
   163  	decoder.UseNumber()
   164  	err := decoder.Decode(&jsonBody)
   165  
   166  	if err != nil {
   167  		log.Errorf("ProcessPostAliasesRequest: error un-marshalling JSON: %v", err)
   168  		utils.SetBadMsg(ctx, "")
   169  		return
   170  	}
   171  	for key, value := range jsonBody {
   172  		switch value.(type) {
   173  		case []interface{}:
   174  			if key == "actions" {
   175  				processActions(ctx, jsonBody[key], myid)
   176  			} else {
   177  				log.Errorf("ProcessPostAliasesRequest: unknown key: %v", key)
   178  				utils.SetBadMsg(ctx, "")
   179  				return
   180  			}
   181  		default:
   182  			log.Errorf("ProcessPostAliasesRequest: unknown type key: %v, value.Type=%T", key, value)
   183  			utils.SetBadMsg(ctx, "")
   184  			return
   185  		}
   186  	}
   187  	respbody := make(map[string]interface{})
   188  	respbody["acknowledged"] = true
   189  	utils.WriteJsonResponse(ctx, respbody)
   190  	ctx.SetStatusCode(fasthttp.StatusOK)
   191  }
   192  
   193  /*
   194     [{ "add" : { "index" : "test1", "alias" : "alias1" } }]
   195     OR
   196     [{"remove": {"index": "test1", "alias" : "alias1"  } }]
   197  */
   198  
   199  func processActions(ctx *fasthttp.RequestCtx, actions interface{}, myid uint64) {
   200  
   201  	switch t := actions.(type) {
   202  	case []interface{}:
   203  		for _, value := range t {
   204  			switch t1 := value.(type) {
   205  			case map[string]interface{}:
   206  				for aKey, aValue := range t1 {
   207  					if aKey == "add" {
   208  						parseAddAction(ctx, aValue, myid)
   209  					} else if aKey == "remove" {
   210  						parseRemoveAction(ctx, aValue, myid)
   211  					} else {
   212  						log.Errorf("processActions: unhandled action aKey: %v", aKey)
   213  						utils.SetBadMsg(ctx, "")
   214  						return
   215  					}
   216  				}
   217  			default:
   218  				log.Errorf("processActions: unknown t1.type=%T, t1=%v", t1, t1)
   219  				utils.SetBadMsg(ctx, "")
   220  				return
   221  			}
   222  		}
   223  	default:
   224  		log.Errorf("processActions: unknown actions.(type)  value.type=%T", t)
   225  		utils.SetBadMsg(ctx, "")
   226  		return
   227  	}
   228  }
   229  
   230  /*
   231     { "index" : "test1", "alias" : "alias1" }}
   232  */
   233  
   234  func parseAddAction(ctx *fasthttp.RequestCtx, params interface{}, myid uint64) {
   235  	log.Infof("parseAddAction: add alias request, params=%v", params)
   236  	switch t := params.(type) {
   237  	case map[string]interface{}:
   238  		aliasName := t["alias"]
   239  		if aliasName == nil {
   240  			log.Errorf("parseAddAction: aliasName was nil, params=%v", params)
   241  			utils.SetBadMsg(ctx, "")
   242  			return
   243  		}
   244  		indexName := t["index"]
   245  		indices := t["indices"]
   246  		if indexName == nil && indices == nil {
   247  			log.Errorf("parseAddAction: both indexName and indices was nil, params=%v", params)
   248  			utils.SetBadMsg(ctx, "")
   249  			return
   250  		}
   251  		doAddAliases(ctx, indexName, aliasName, indices, myid)
   252  	default:
   253  		log.Errorf("parseAddAction: unknown params.(type)=%T  params=%v", params, params)
   254  		utils.SetBadMsg(ctx, "")
   255  		return
   256  	}
   257  }
   258  
   259  /*
   260     { "index" : "test1", "alias" : "alias1" }
   261     OR
   262     { "indices" : ["test1", "test2"], "alias" : "alias1" }
   263  */
   264  
   265  func doAddAliases(ctx *fasthttp.RequestCtx, indexName interface{}, aliasName interface{}, indices interface{}, myid uint64) {
   266  
   267  	log.Infof("doAddAliases: addalias for indexName=%v, aliasName=%v, indices=%v", indexName, aliasName, indices)
   268  
   269  	if indexName != nil {
   270  		err := vtable.AddAliases(indexName.(string), []string{aliasName.(string)}, myid)
   271  		if err != nil {
   272  			log.Errorf("doAddAliases: failed to add alias, indexName=%v, aliasName=%v err=%v", indexName.(string), aliasName.(string), err)
   273  			utils.SetBadMsg(ctx, "")
   274  		}
   275  		return
   276  	}
   277  
   278  	switch t := indices.(type) {
   279  	case []interface{}:
   280  		for _, iVal := range t {
   281  			err := vtable.AddAliases(iVal.(string), []string{aliasName.(string)}, myid)
   282  			if err != nil {
   283  				log.Errorf("doAddAliases: failed to add alias, indexName=%v, aliasName=%v err=%v", iVal.(string), aliasName.(string), err)
   284  			}
   285  		}
   286  	default:
   287  		log.Errorf("doAddAliases: unknown indices.(type)=%T  indices=%v", indices, indices)
   288  		utils.SetBadMsg(ctx, "")
   289  		return
   290  	}
   291  }
   292  
   293  /*
   294  
   295  	{ "index" : "test1", "alias" : "alias1" }
   296  
   297  */
   298  
   299  func parseRemoveAction(ctx *fasthttp.RequestCtx, params interface{}, myid uint64) {
   300  	log.Infof("parseRemoveAction: remove alias request, params=%v", params)
   301  	switch t := params.(type) {
   302  	case map[string]interface{}:
   303  		aliasName := t["alias"]
   304  		if aliasName == nil {
   305  			log.Errorf("parseRemoveAction: aliasName was nil, params=%v", params)
   306  			utils.SetBadMsg(ctx, "")
   307  			return
   308  		}
   309  		indexName := t["index"]
   310  		if indexName == nil {
   311  			log.Errorf("parseRemoveAction: both indexName was nil, params=%v", params)
   312  			utils.SetBadMsg(ctx, "")
   313  			return
   314  		}
   315  		err := vtable.RemoveAliases(indexName.(string), []string{aliasName.(string)}, myid)
   316  		if err != nil {
   317  			log.Errorf("parseRemoveAction: failed to remove alias, indexName=%v, aliasName=%v err=%v", indexName.(string), aliasName.(string), err)
   318  			utils.SetBadMsg(ctx, "")
   319  		}
   320  		return
   321  	default:
   322  		log.Errorf("parseRemoveAction: unknown params.(type)=%T  params=%v", params, params)
   323  		utils.SetBadMsg(ctx, "")
   324  		return
   325  	}
   326  }
   327  
   328  func ProcessIndexAliasExist(ctx *fasthttp.RequestCtx, myid uint64) {
   329  
   330  	//get indexName and aliasName
   331  	indexName := utils.ExtractParamAsString(ctx.UserValue("indexName"))
   332  	aliasName := utils.ExtractParamAsString(ctx.UserValue("aliasName"))
   333  	if indexName == "" {
   334  		ctx.SetStatusCode(fasthttp.StatusNotFound)
   335  		log.Errorf("ProcessIndexAliasExist : indexName is required")
   336  		ctx.SetContentType(utils.ContentJson)
   337  		return
   338  	}
   339  	alias, _ := vtable.IsAlias(aliasName, myid)
   340  
   341  	allIndexNames, _ := vtable.GetVirtualTableNames(myid)
   342  
   343  	_, exists := allIndexNames[indexName]
   344  	if exists {
   345  		ctx.SetStatusCode(fasthttp.StatusOK)
   346  		ctx.SetContentType(utils.ContentJson)
   347  		return
   348  	}
   349  	//for alias
   350  	if aliasName == "" || !alias {
   351  		ctx.SetStatusCode(fasthttp.StatusNotFound)
   352  		log.Errorf("ProcessIndexAliasExist : aliasName is required")
   353  		ctx.SetContentType(utils.ContentJson)
   354  	} else {
   355  		ctx.SetStatusCode(fasthttp.StatusOK)
   356  		ctx.SetContentType(utils.ContentJson)
   357  	}
   358  }