pkg/apisix/resource.go (151 lines of code) (raw):

// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package apisix import ( "encoding/json" "errors" "fmt" "strconv" "strings" "github.com/apache/apisix-ingress-controller/pkg/log" v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) type getResponse struct { Item item `json:"node"` } // listResponse is the unified LIST response mapping of APISIX. type listResponse struct { Count IntOrString `json:"count"` Node node `json:"node"` } // listResponseV3 is the v3 version unified LIST response mapping of APISIX. type listResponseV3 struct { Total IntOrString `json:"total"` List items `json:"list"` } // IntOrString processing number and string types, after json deserialization will output int type IntOrString struct { IntValue int `json:"int_value"` } func (ios *IntOrString) UnmarshalJSON(p []byte) error { result := strings.Trim(string(p), "\"") count, err := strconv.Atoi(result) if err != nil { return err } ios.IntValue = count return nil } type createResponse struct { Action string `json:"action"` Item item `json:"node"` } type createResponseV3 struct { item } type updateResponse = createResponse type updateResponseV3 = createResponseV3 type node struct { Key string `json:"key"` Items items `json:"nodes"` } type items []item // UnmarshalJSON implements json.Unmarshaler interface. // lua-cjson doesn't distinguish empty array and table, // and by default empty array will be encoded as '{}'. // We have to maintain the compatibility. func (items *items) UnmarshalJSON(p []byte) error { if p[0] == '{' { if len(p) != 2 { return errors.New("unexpected non-empty object") } return nil } var data []item if err := json.Unmarshal(p, &data); err != nil { return err } *items = data return nil } type item struct { Key string `json:"key"` Value json.RawMessage `json:"value"` } // route decodes item.Value and converts it to v1.Route. func (i *item) route() (*v1.Route, error) { log.Debugf("got route: %s", string(i.Value)) list := strings.Split(i.Key, "/") if len(list) < 1 { return nil, fmt.Errorf("bad route config key: %s", i.Key) } var route v1.Route if err := json.Unmarshal(i.Value, &route); err != nil { return nil, err } return &route, nil } // streamRoute decodes item.Value and converts it to v1.StreamRoute. func (i *item) streamRoute() (*v1.StreamRoute, error) { log.Debugf("got stream_route: %s", string(i.Value)) list := strings.Split(i.Key, "/") if len(list) < 1 { return nil, fmt.Errorf("bad stream_route config key: %s", i.Key) } var streamRoute v1.StreamRoute if err := json.Unmarshal(i.Value, &streamRoute); err != nil { return nil, err } return &streamRoute, nil } // upstream decodes item.Value and converts it to v1.Upstream. func (i *item) upstream() (*v1.Upstream, error) { log.Debugf("got upstream: %s", string(i.Value)) list := strings.Split(i.Key, "/") if len(list) < 1 { return nil, fmt.Errorf("bad upstream config key: %s", i.Key) } var ups v1.Upstream if err := json.Unmarshal(i.Value, &ups); err != nil { return nil, err } // This is a workaround scheme to avoid APISIX's // health check schema about the health checker intervals. if ups.Checks != nil && ups.Checks.Active != nil { if ups.Checks.Active.Healthy.Interval == 0 { ups.Checks.Active.Healthy.Interval = int(v1.ActiveHealthCheckMinInterval.Seconds()) } if ups.Checks.Active.Unhealthy.Interval == 0 { ups.Checks.Active.Healthy.Interval = int(v1.ActiveHealthCheckMinInterval.Seconds()) } } return &ups, nil } // ssl decodes item.Value and converts it to v1.Ssl. func (i *item) ssl() (*v1.Ssl, error) { log.Debugf("got ssl: %s", string(i.Value)) var ssl v1.Ssl if err := json.Unmarshal(i.Value, &ssl); err != nil { return nil, err } return &ssl, nil } // globalRule decodes item.Value and converts it to v1.GlobalRule. func (i *item) globalRule() (*v1.GlobalRule, error) { log.Debugf("got global_rule: %s", string(i.Value)) var globalRule v1.GlobalRule if err := json.Unmarshal(i.Value, &globalRule); err != nil { return nil, err } return &globalRule, nil } // consumer decodes item.Value and converts it to v1.Consumer. func (i *item) consumer() (*v1.Consumer, error) { log.Debugf("got consumer: %s", string(i.Value)) var consumer v1.Consumer if err := json.Unmarshal(i.Value, &consumer); err != nil { return nil, err } return &consumer, nil } func (i *item) pluginMetadata() (*v1.PluginMetadata, error) { log.Debugf("got pluginMetadata: %s", string(i.Value)) var pluginMetadata v1.PluginMetadata if err := json.Unmarshal(i.Value, &pluginMetadata.Metadata); err != nil { return nil, err } keys := strings.Split(i.Key, "/") pluginMetadata.Name = keys[len(keys)-1] return &pluginMetadata, nil } // pluginConfig decodes item.Value and converts it to v1.PluginConfig. func (i *item) pluginConfig() (*v1.PluginConfig, error) { log.Debugf("got pluginConfig: %s", string(i.Value)) var pluginConfig v1.PluginConfig if err := json.Unmarshal(i.Value, &pluginConfig); err != nil { return nil, err } return &pluginConfig, nil }