Luci model/cbi questions

Hey @jow, @hnyman, I' wondering if you could help me out?

I have a few ideas on improving the luci-app-https-dns-proxy and have some questions.

In this code:

s3 = m:section(TypedSection, "https_dns_proxy", translate("Instances"))
s3.template = "cbi/tblsection"
s3.sortable  = false
s3.anonymous = true
s3.addremove = true

prov = s3:option(ListValue, "url_prefix", translate("Provider"))
prov:value("https://cloudflare-dns.com/dns-query?ct=application/dns-json&","Cloudflare")
prov:value("https://dns.google.com/resolve?","Google")
prov.write = function(self, section, value)
  if value and value:match("cloudflare") then
    uci:set("https_dns_proxy", section, "bootstrap_dns", "1.1.1.1,1.0.0.1")
    uci:set("https_dns_proxy", section, "url_prefix", "https://cloudflare-dns.com/dns-query?ct=application/dns-json&")
  else
    uci:set("https_dns_proxy", section, "bootstrap_dns", "8.8.8.8,8.8.4.4")
    uci:set("https_dns_proxy", section, "url_prefix", "https://dns.google.com/resolve?")
  end
  uci:set("https_dns_proxy", section, "user", "nobody")
  uci:set("https_dns_proxy", section, "group", "nogroup")
  uci:save("https_dns_proxy")
end
  1. If I create an s3.write function -- which one will be executed first, prov.write or s3.write? I want to clear out dhcp.@dnsmasq[0].server within s3.write and then fill it within prov.write.
  2. Within that s3 block, is it possible to get the index, as in -- wherever it's https_dns_proxy.@https_dns_proxy[0] or https_dns_proxy.@https_dns_proxy[1]? How? Instead of the placeholder, I want to pre-fill the ports starting with 5053 for the first instance and 5054 for the next one.
  1. There is no section level write() - any reason why you can't clear in prov.write() as well?
  2. As there is no write callback for sections, the question does not apply - in prov.write() you can figure out the section type index using code like this:
prov.write = function(self, section, value)
    local n = 0
    uci:foreach("https_dns_proxy", "https_dns_proxy", function(s)
        if s[".name"] == section then
            return false
        end
        n = n + 1
    end)

    -- Variable 'n' will hold the section index
    ...
end
1 Like

Thank you!

When in prov.write what's the correct way of accessing the lp.value and la.value from the same section?

Also, is luci.model.uci article up to date? What's the luci equivalent of uci del_list and uci add_list?

I'm not sure what you mean with lp and la but assuming that these are variables containing the result of s3:option(), then you can access the values like this:

prov.write = function(self, section, value)
    local lp_val = lp:formvalue(section)
    local la_val = la:formvalue(section)
end

There are no direct functions for adding and removing list items, the usual way is to manipulate the array and to write it back, like this:

function uci_del_list(conf, sect, opt, value)
  local lval = uci:get(conf, sect, opt)
  if lval == nil or lval == "" then
    lval = {}
  elseif type(lval) ~= "table" then
    lval = { lval }
  end

  local i
  local changed = false
  for i = #lval, 1 do
    if lval[i] == value then
      table.remove(lval, i)
      changed = true
    end
  end

  if changed then
    if #lval > 0 then
      uci:set(conf, sect, opt, lval)
    else
      uci:delete(conf, sect, opt)
    end
  end
end

function uci_add_list(conf, sect, opt, value)
  local lval = uci:get(conf, sect, opt)
  if lval == nil or lval == "" then
    lval = {}
  elseif type(lval) ~= "table" then
    lval = { lval }
  end

  lval[#lval+1] = value
  uci:set(conf, sect, opt, lval)
end
2 Likes

Hello @jow. I'm guessing I needed to express what I'm hoping to achieve better.

So I have this piece of code and my hope was that at every save, the prov.write will be called for every single TypedSection, however it is only called for the updated entries.

What I want to achieve is to have a function called for each TypedSection entry, so that I would first delete dhcp.@dnsmasq[0].server and then set it for each TypedSection entry.

The problems with the current code are:

  1. I don't think the uci_del_list is working or is being called enough -- if I delete a TypedSection entry and add it again, I'm seeing duplicate entries in dhcp.@dnsmasq[0].server.
  2. It doesn't seem to clean up the extra dhcp.@dnsmasq[0].server when I just delete a TypedSection entry.

If I could just have the function called for each TypedSection entry on save, I believe it would solve both problems.

Hmm, you could try .forcewrite = true on the prov option - that should trigger its :write() callback regardless of whether the underlying value changed or not.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.