apisix icon indicating copy to clipboard operation
apisix copied to clipboard

help request: error loading custom plugin

Open satishviswanathan opened this issue 1 year ago • 10 comments

Description

I followed this link to see if I can have a custom plugin loaded.

https://apisix.apache.org/docs/apisix/next/plugin-develop/

But getting this error

nginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: /opt/apisix/plugins/3rd-party.lua:2: loop or previous error loading module 'apisix.core') in /usr/local/apisix/conf/nginx.conf:415

Not sure what I'm missing, any help is appreciated.

apisix config.yml

apisix:
  node_listen: 9080              # APISIX listening port
  enable_ipv6: false
  extra_lua_path: "/opt/apisix/plugins/3rd-party.lua"
  plugins:                           # plugin list (sorted by priority)
    - 3rd-party                      # priority: 2561
  enable_control: true
  control:
    ip: "0.0.0.0"
    port: 9092

deployment:
  admin:
    allow_admin:               # https://nginx.org/en/docs/http/ngx_http_access_module.html#allow
      - 0.0.0.0/0              # We need to restrict ip access rules for security. 0.0.0.0/0 is for test.

    admin_key:
      - name: "admin"
        key: edd1c9f034335f136f87ad84b625c8f1
        role: admin                 # admin: manage all configuration data

      - name: "viewer"
        key: 4054f7cf07e344346cd3f287985e76a2
        role: viewer

  etcd:
    host:                           # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
      - "http://etcd:2379"          # multiple etcd address
    prefix: "/apisix"               # apisix configurations prefix
    timeout: 30                     # 30 seconds

plugin_attr:
  prometheus:
    export_addr:
      ip: "0.0.0.0"
      port: 9091

Apisix docker-compose.yml

version: "3"

services:
  apisix-dashboard:
    image: apache/apisix-dashboard:3.0.1-alpine
    restart: always
    volumes:
    - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
    ports:
    - "8080:9000"
    networks:
      apisix:

  apisix:
    image: apache/apisix:${APISIX_IMAGE_TAG:-3.6.0-debian}
    restart: always
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
      - ./auth:/usr/local/apisix/auth
      - ./custom-plugins:/opt/apisix/plugins:ro
    depends_on:
      - etcd
    ##network_mode: host
    ports:
      - "9180:9180/tcp"
      - "9080:9080/tcp"
      - "9091:9091/tcp"
      - "9443:9443/tcp"
      - "9092:9092/tcp"
    networks:
      apisix:

  etcd:
    image: bitnami/etcd:3.4.15
    restart: always
    volumes:
      - etcd_data:/bitnami/etcd
    environment:
      ETCD_ENABLE_V2: "true"
      ALLOW_NONE_AUTHENTICATION: "yes"
      ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
      ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
    ports:
      - "2379:2379/tcp"
    networks:
      apisix:

  web1:
    image: nginx:1.19.0-alpine
    restart: always
    volumes:
      - ./upstream/web1.conf:/etc/nginx/nginx.conf
    ports:
      - "9081:80/tcp"
    environment:
      - NGINX_PORT=80
    networks:
      apisix:

  web2:
    image: nginx:1.19.0-alpine
    restart: always
    volumes:
      - ./upstream/web2.conf:/etc/nginx/nginx.conf
    ports:
      - "9082:80/tcp"
    environment:
      - NGINX_PORT=80
    networks:
      apisix:

  prometheus:
    image: prom/prometheus:v2.25.0
    restart: always
    volumes:
      - ./prometheus_conf/prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    networks:
      apisix:

  grafana:
    image: grafana/grafana:7.3.7
    restart: always
    ports:
      - "3000:3000"
    volumes:
      - "./grafana_conf/provisioning:/etc/grafana/provisioning"
      - "./grafana_conf/dashboards:/var/lib/grafana/dashboards"
      - "./grafana_conf/config/grafana.ini:/etc/grafana/grafana.ini"
    networks:
      apisix:
  
  postgres:
      image: postgres:12.2
      container_name: postgres
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
      networks:
        apisix:
      depends_on:
        - apisix
        
  keycloak:
      image: jboss/keycloak:9.0.2
      container_name: keycloak
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_PASSWORD: password
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: password
        PROXY_ADDRESS_FORWARDING: "true"
      ports:
        - 3001:8080
      networks:
        apisix:
      depends_on:
        - postgres 
networks:
  apisix:
    driver: bridge

volumes:
  etcd_data:
    driver: local

3rd-party.lua

local require       = require
local core          = require("apisix.core")
local plugin_name   = "3rd-party"


local schema = {
    type = "object",
    properties = {
        body = {
            description = "body to replace response.",
            type = "string"
        },
    },
    required = {"body"},
}

local plugin_name = "3rd-party"

local _M = {
    version = 0.1,
    priority = 12,
    name = plugin_name,
    schema = schema,
}


function _M.check_schema(conf)
    return core.schema.check(schema, conf)
end


function _M.access(conf, ctx)
    return 200, conf.body
end

Environment

  • APISIX version (run apisix version):
  • Operating system (run uname -a):
  • OpenResty / Nginx version (run openresty -V or nginx -V):
  • etcd version, if relevant (run curl http://127.0.0.1:9090/v1/server_info):
  • APISIX Dashboard version, if relevant:
  • Plugin runner version, for issues related to plugin runners:
  • LuaRocks version, for installation issues (run luarocks --version):

satishviswanathan avatar Feb 08 '24 23:02 satishviswanathan

Hi, the configs you have shared look scary as they have been misunderstood as markdown files by github. Please use "```" wherever necessary.

shreemaan-abhishek avatar Feb 09 '24 04:02 shreemaan-abhishek

@shreemaan-abhishek Thank you for your response. Can you check if my config are good to load a custom plugin

Apologies should have uploaded the file for better readability. I have renamed the extension of the files so that it can be uploaded.

3rd-party.txt docker-compose.txt config.txt (apisix config) conf.txt (dashboard config)

satishviswanathan avatar Feb 09 '24 14:02 satishviswanathan

Tru updating extra_lua-path to /opt/\?.lua

kayx23 avatar Feb 10 '24 23:02 kayx23

@kayx23 initially I tired that way as suggested in the documentation but the plugin didn't get picked up .. but when I gave the full path it's picking up but getting errors as well. I'm also using apisix dashboard. I have updated with it's config as well.

satishviswanathan avatar Feb 12 '24 14:02 satishviswanathan

I have seem that error when using the full path as well. Here is a newer piece of documentation on the topic for reference:

https://docs.api7.ai/apisix/how-to-guide/custom-plugins/create-plugin-in-lua#update-apisix-configuration-file

I don't have knowledge of the dashboard unfortunately.

kayx23 avatar Feb 12 '24 16:02 kayx23

@kayx23 - I tried that but still it didn't work, however I resolved that issue by copying the custom plugin under the plugins folder where all the plugins are residing (apisix/plugins/) and then updated the config-default.yaml with the new custom plugin. So I don't have the extra_lua_path any more. With these changes I was able to enable the custom plugin. However as soon as the plugin was enabled I can see the following logs from APISIX.

Do you know what this error is ? Any help is appreciated

2024/02/16 17:05:39 [error] 212#212: *148682 [lua] config_etcd.lua:883: failed to fetch data from etcd: /usr/local/openresty/lualib/resty/lrucache.lua:229: table index is nil apisix_1 | stack traceback: apisix_1 | /usr/local/openresty/lualib/resty/lrucache.lua:229: in function 'set' apisix_1 | /usr/local/apisix/apisix/core/lrucache.lua:97: in function 'cached_validator' apisix_1 | /usr/local/apisix/apisix/core/schema.lua:49: in function 'get_validator' apisix_1 | /usr/local/apisix/apisix/core/schema.lua:60: in function 'check_schema' apisix_1 | /usr/local/apisix/apisix/plugin.lua:887: in function 'check_single_plugin_schema' apisix_1 | /usr/local/apisix/apisix/plugin.lua:1041: in function 'check_schema' apisix_1 | /usr/local/apisix/apisix/plugin.lua:1090: in function 'plugin_checker' apisix_1 | /usr/local/apisix/apisix/http/route.lua:122: in function 'checker' apisix_1 | /usr/local/apisix/apisix/core/config_etcd.lua:677: in function 'sync_data' apisix_1 | /usr/local/apisix/apisix/core/config_etcd.lua:827: in function </usr/local/apisix/apisix/core/config_etcd.lua:817> apisix_1 | [C]: in function 'xpcall' apisix_1 | /usr/local/apisix/apisix/core/config_etcd.lua:817: in function </usr/local/apisix/apisix/core/config_etcd.lua:795>, etcd key: /apisix/routes, context: ngx.timer

satishviswanathan avatar Feb 16 '24 17:02 satishviswanathan

Any help here @shreemaan-abhishek

kayx23 avatar Feb 16 '24 18:02 kayx23

quick update I got the plugins loaded by settings the extra_lua_path "/opt/apisix/plugins/?.lua" and in my apisix docker I gave it as follows.

apisix: image: apache/apisix:${APISIX_IMAGE_TAG:-3.8.0-debian} restart: always volumes: - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro - ./auth:/usr/local/apisix/auth - ./custom-plugins:/opt/apisix/plugins/apisix/plugins:ro

The change was I gave the path as "/opt/apisix/plugins/apisix/plugins". If I give anyother path it wouldn't work. For example initially I was giving it as "/opt/apisix/plugins/".

Now apis six is running with the custom plugin enabled and I'm bale to hit by endpoint and get the response back. I'm not sure if the custom plugin got executed. However I'm still seeing that error in the background

2024/02/16 21:54:26 [error] 52#52: *17900 [lua] config_etcd.lua:883: failed to fetch data from etcd: /usr/local/openresty/lualib/resty/lrucache.lua:229: table index is nil apisix_1 | stack traceback: apisix_1 | /usr/local/openresty/lualib/resty/lrucache.lua:229: in function 'set' apisix_1 | /usr/local/apisix/apisix/core/lrucache.lua:97: in function 'cached_validator' apisix_1 | /usr/local/apisix/apisix/core/schema.lua:49: in function 'get_validator' apisix_1 | /usr/local/apisix/apisix/core/schema.lua:60: in function 'check_schema' apisix_1 | /usr/local/apisix/apisix/plugin.lua:887: in function 'check_single_plugin_schema' apisix_1 | /usr/local/apisix/apisix/plugin.lua:1041: in function 'check_schema' apisix_1 | /usr/local/apisix/apisix/plugin.lua:1090: in function 'checker' apisix_1 | /usr/local/apisix/apisix/core/config_etcd.lua:677: in function 'sync_data' apisix_1 | /usr/local/apisix/apisix/core/config_etcd.lua:827: in function </usr/local/apisix/apisix/core/config_etcd.lua:817> apisix_1 | [C]: in function 'xpcall' apisix_1 | /usr/local/apisix/apisix/core/config_etcd.lua:817: in function </usr/local/apisix/apisix/core/config_etcd.lua:795>, etcd key: /apisix/global_rules, context: ngx.timer

Custom plugin. I don't have much knowledge on lua, just trying to see if it can be loaded and see it in action so that later we can built custom plugins according to our needs

local core = require("apisix.core") local io = require("io") local ngx = ngx local plugin_name = "3rd-party"

local plugin_schema = { type = "object", properties = { path = { description = "path to replace response.", type = "string" }, }, required = {"path"}, }

local _M = { version = 1.0, priority = 12, name = plugin_name, schema = plugin_schema }

function _M.check_schema(conf) return core.schema.check(consumer_schema, conf) end

function _M.access(conf, ctx) return 200, conf.body end

function _M.log(conf, ctx) core.log.warn(core.json.encode(conf))

end

return _M

satishviswanathan avatar Feb 16 '24 20:02 satishviswanathan

My custom plugin worked.

Loading issue resolved by giving the following volume path in the docker to load the custom plugin.

  • ./custom-plugins:/opt/apisix/plugins/apisix/plugins:ro

The above error might be a syntax issue. I just got a copy of existing plugin and wrote a log message and it worked.

satishviswanathan avatar Feb 16 '24 22:02 satishviswanathan

Ok, any other question pending on this thread?

kayx23 avatar Feb 19 '24 00:02 kayx23

Thank you all for the help.

My objective of the custom plugin is to execute an existing plugin "plugins.authz-casbin". Can you show me how to invoke a plugin from a custom plugin.

satishviswanathan avatar Feb 20 '24 23:02 satishviswanathan

you cannot invoke one plugin from another but you can call functions present in other plugin's code or implement similar functions through code :)

shreemaan-abhishek avatar Feb 21 '24 05:02 shreemaan-abhishek

@shreemaan-abhishek thank you. IAs you suggested I got it working by calling the functions in other plugin's code

satishviswanathan avatar Feb 22 '24 20:02 satishviswanathan

@shreemaan-abhishek , In apisix is there a way I can control the request timeout. sometimes my oauth provider api is slow which causes the gateway to return 403 with error saying that the oauth end point timed out. Is there a way in apisix config I can increases this timeout value ?

satishviswanathan avatar Mar 19 '24 17:03 satishviswanathan